組織直線型代碼
我對這句話的理解是:要讓你的代碼符合人的閱讀習慣——由上到下。
代碼不應該只是純粹爲了通過編譯而寫,更重要的是要讓人更容易讀懂,這也是編程的藝術,如果所有代碼的目的都僅僅是通過編譯可以運行就行,那編程還有什麼藝術感美感可言,這裏粗略的將代碼分爲以下兩類:
- 必須有明確順序的語句
- 順序無關的語句
1.必須有明確順序的語句
當語句之間有依賴關係時,後一語句的執行必須依賴前一語句的結果
(下面所提的子程序可以理解爲方法或者某一可執行模塊)
data = ReadData();
results = CalculateResultsFromData();
PrintResults(result);
這段代碼就能看出前後之間的依賴性,也就是它們非按這個順序運行不可。
如果語句之間存在這樣的關係,那麼就一定要儘可能將它們這種關係明顯清晰地表達出來,這樣更有利程序的可讀性,接下來是相應的一些組織代碼的原則:
-
使依賴關係變得明顯
要點在於使語句的功能儘量精簡而明確,每一個子程序應該有自己明確的處理任務,比如計算方法就不應該讓它承擔變量初始化的工作,並且這樣做更有利於爲子程序起名,因爲ComputeXxxxAndInitiatialXxxxx() 終歸是太長了,不如分爲兩行ComputeXxxx() 和InitatialXxxxx()。
這樣做雖然更麻煩,但是卻更靈活更清晰,你不僅一眼可以看出兩個動作的先後順序,更可以自由的在兩個動作之間再加入新的動作。 -
使子程序名能凸顯依賴關係
如之前所說,一個子程序不應該做它自己名字內容以外的事,否則它就是一個糟糕的子程序。 -
使子程序參數明確顯示依賴關係
上面的代碼就是一個很好的例子。
4.使用狀態變量或者錯誤處理碼
它還有一個更高大上的名字——內務管理變量 (housekeeping variables)
這裏加粗是因爲這對我來說是一個新事物,當然這也是十分重量的做法,一般用於十分重要的類或者方法中,當然不建議到處濫用。
例如:
class DataOperation{
boolean isDataPrepared;
//準備就緒
void getPrepared(){
isDataprepared = true;
};
void addData(){
if(this.isDataPrepared==true){
//如果爲true,方可執行
}else{
return;
}
}
}
在一個類中添加一個布爾成員變量isDataPrepared,並在構造器中將其初始化爲false,j假設增刪改查方法在執行前必須檢查isDataPrepared變量,若爲true方可執行,如此必然可以得出getPrepare()方法必須優先得到執行,否則後續無法操作。
當然這樣做的是有風險的,因爲它引入了更多的變量,修改了構造器,並且你必須要爲其編寫出錯代碼,所以我們需要在它的利弊之間權衡。
- 使用註釋來對不清晰的依賴關係進行說明
這就是最下策了,當你的程序不允許你對它進行結構上的調整時,那你就只能用註釋加以說明了。我們更應該依賴上面的方法而不是依賴於註釋。
2.順序無關的語句
就近原則(Principle of Proximity):把相關操作放在一起。
十分好理解了,相關操作指同一個對象的方法,同一個類的方法等應該放在一起,而不是不同的方法穿插在一起。
這裏畫一個圖來生動表示:
這樣做的好處是:
- 儘可能縮小對象的存活(alive)行數。
明明兩個方法可以連續執行完後就不需要引用方法的對象了,那就沒必要在兩個方法之間摻雜其他操作。儘量減少對象閒置無操作的代碼行數,這樣的好處是使程序更加清爽,一定程度提高了程序的性能。 - 使代碼易於自上而下的閱讀。
要點 key point
- 組織線性代碼的最主要原則是按照依賴關係進行排列
- 可以用好的子程序名、參數列表、註釋,以及——如果代碼足夠重要——內務管理變量可以讓依賴關係表現的更加明顯
- 如果代碼之間沒有順序依賴關係,那就設法使相關的語句儘可能接近