第二十五計:函數體最多不超過100行
記得以前看過一個函數有9000多行,很壯觀啊,從那以后看到長函數時也不奇怪了,我認為過長函數的主要缺點是:
1、嚴重影響代碼的閱讀,使用到某個變量的地方可能間隔幾百甚至上千行,如果if-else嵌套層次較多的話那就更噩夢了。
2、不利於代碼的重用,短小而獨立的邏輯處理單元更容易被重用,而過長的代碼段則需要經過進一步分解才行。
我覺得函數最好不要超過100行,對於過長的函數要盡可能地進行分解,如果實在不能分解,那么就通過注釋的方式增加該函數處理步驟的說明,例如:
public void foo(){ // 1、驗證參數、內部狀態的有效性 ... // 2、開始傾斜角度 ... // 2.1 計算角度1 ... // 2.2 計算角度2 ... // 3、輸出計算說明書 ...
}
第二十六計:使用語言的修飾符確保變量的不可變性
當聲明一個變量時,如果能十分確定該變量不會被修改或者不應該被修改,那最好把它聲明為不可變的,如使用Java中的final、C++中的const修飾符,這樣可以防止本該不變的變量被意外地修改。
第二十七計:對象狀態共享
大量對象的同時存在會占用系統寶貴的內存,如果這些對象中某些狀態是相同的,那么可以將這些狀態提取出來讓所有需要它的對象共享,這可以大大減少冗余對象,從而達到節省內存的目的,設計模式中的Flyweight模式可以解決這個問題。
第二十八計:用對象代替普通常量
由於普通常量本質上是一個簡單的數字或者字符串,當我們錯誤地將某個類別的常量在另一個類別的常量的場景中使用時,就會產生問題,但是編譯器並不會提示有錯誤,所以,這可能是一個不小的隱患,例如:
// 表示用戶狀態的常量聲明 public static int USER_STATE_ACTIVE = 0; public static int USER_STATE_DELETE = 1; // 表示用戶角色的常量聲明 public static int USER_ROLE_NORMAL = 2; public static int USER_ROLE_MANAGER = 3; // 下面用戶是否被激活的判斷 if(userState == USER_ROLE_NORMAL){ }
這個判斷本應該使用USER_STATE_ACTIVE和USER_STATE_DELETE兩個常量之一,卻意外地使用了其他常量,可能直到Bug產生后才能被發現。
可以使用對象常量來避免這種情況,例如:
public class State{ private int state; public State(int s){ state = s; } } // 表示用戶狀態的常量聲明 public static State USER_STATE_ACTIVE = new State(0); public static State USER_STATE_DELETE = new State(1); public class Role{ private int role; public Role(int r){ role = r; } } // 表示用戶角色的常量聲明 public static Role USER_ROLE_NORMAL = new Role(2); public static Role USER_ROLE_MANAGER = new Role(3);
下面的判斷是無法通過編譯的,因為userState是State類型的。
if(userState == USER_ROLE_NORMAL){ }
第二十九計:查詢函數中盡量不要有修改操作
我們一般都是根據函數的名字來判斷它的功能,“表里不一“的函數可能會引起一些問題,例如我們調了一個查詢函數(獲取類的成員變量值的函數):getName(),但是它內部卻修改了其他成員變量的值,當查找Bug的原因時,很可能會忽略這個函數,從它的名字看,覺得它不會引起問題,到最后發現就是它搗的鬼,心里估計會罵這個函數的作者:他奶奶的,代碼如其人,表里不一!
第三十計:盡量封裝對象的創建過程
本文之前曾提到過要盡量為成員變量增加set和get函數,主要目的是為了掌握成員變量的控制權,對象的創建過程也是如此,如果提供者掌握了對象創建過程的控制權,那么就可以屏蔽具體的實現類,並且任意修改對象的創建過程。