Chapter 7 High-Quality Routines (Page 198-223)
高品質的子程式
7.1 Valid Reasons to create a Routine
建立子程式的正當理由
1. 降低複雜度
2. 引入中間,易懂的抽象
3. 避免代碼的重複
代碼分解(decomposition)
4. 支援子類化覆蓋(subclassing override)
5. 隱藏順序
6. 隱藏指標操作
指標操作的可讀性通常很差,且易出錯。通過把這些操作隔離在子程式內部,你就可以把精力集中於操作的意圖本身,而不
是指標操作機制的細節。
7. 提高可移植性
8. 簡化複雜的布爾判斷
9. 改善效能
把代碼集中在一處可以更方便地查出哪些代碼的運行效率低下。、
10. 確保所有的子程式都很小
避免下面的觀點:
Operations That Seem Too Simple to Put Into Routines
似乎過於簡單而沒有必要寫成子程式的操作
7.2 Design at the Routine Level
在子程式層上設計
內聚性(cohesion),是指子程式中各種操作之間聯絡的緊密程度。
關於內聚性cohesion的討論一般會涉及到內聚性的幾個層次。以下概念可以協助你思考如何讓子程式儘可能地內聚。
功能的內聚性(functional cohesion)
它是最強也是最好的一種內聚性,也就是說讓一個子程式僅執行一項操作。
除此之外,還有其他的內聚性人們卻通常認為不夠理想的。
順序上的內聚性(sequential cohesion)
通訊上的內聚性(communicational cohesion)
臨時的內聚性(temporal cohesion)
過程上的內聚性(procedural cohesion)
邏輯上的內聚性(logical cohesion)
巧合的內聚性(coincidental cohesion)
7.3 Good Routine Names
好的子程式的名字
1. 描述子程式所做的所有事情
2. 避免使用無意義的,模糊或表述不清的動詞。
3. 不要緊通過數字來形成不同的子程式名字
4. 根據需要確定子程式名字的長度
研究表明,變數名的最佳長度是9-15個字元。
5. 給函數命名時要對傳回值有所描述
6. 給過程命名時使用語氣強烈的動詞加賓語的形式
7. 準確使用對仗詞。
8. 為常用操作確立命名規則
7.4 How Long can a routine Be
子程式可以寫多長
理論上認為的子程式最佳最大長度通常是一屏代碼或列印出來1到2頁的代碼,也就是約50-150行代碼。
人們在子程式長度問題上積累了大量的研究成果,其中適用於現代編程:
1. 子程式長度和錯誤量成反比。
2. 另一項研究發現,子程式的長度與錯誤量沒有關聯,而結構複雜度以及資料量卻與錯誤量有關。
3. IBM研究發現,最容易出錯的是那些超過500行代碼的子程式。超過500行之後,子程式的出錯率就會與其長度成正比。
總結,如果編寫超過200行代碼的子程式,那你要小心了。對於超過200行代碼的子程式來說,沒有哪項研究發現它能降低成本和/或
降低出錯率,而且在超過200行後,你遲早會在可讀性方面遇到問題。
7.5 How to Use Routine Parameters
如何使用子程式參數
1. 按照輸入-修改-輸出的順序排列參數
2. 考慮自己建立in和out關鍵字
例如,C++中,可以預定義IN和OUT這兩個宏關鍵字只是起到說明性的作用。
3. 如果幾個子程式都用了類似的一些參數,應該讓這些參數的排列順序保持一致。
子程式的參數順序可以產生記憶效應----不一致的順序會讓參數難以記憶。
4. 使用所有的參數
如果傳遞了一個參數,就一定要用到這個參數。如果不用它,則要把它從子程式的介面中刪去。未用到的參數和出錯率的增
加不無關係。成正比的。
5. 把狀態或出錯變數放在最後
6. 不要把子程式的參數用做變數
7. 在介面中對參數的假定加以說明
8. 把子程式的參數個數限定在大約7個以內。
心理學研究發現,通常人類很難同時記住超過7個單位的資訊。
9. 考慮對參數採用某種表示輸入,修改,輸出的命名規則
10. 為子程式傳遞用以維持其介面抽象的變數或對象
傳遞3項值好?還是傳遞對象(包括10項值)好呢?這要看:子程式的介面要表達何種抽象?
11. 使用具名參數
12. 確保實際參數與形式參數相匹配
形式參數也稱為“啞參數(dummy parameters)”,是指在子程式定義中聲明的變數。
實際參數是指在實際的子程式調用中用到的變數,常量或者運算式。
7.6 Special Considerations in the Use of Functions
使用函數時要特別考慮的問題
1. When to use a Function and When to use a Procedure?
2. Setting the Function's Return Value
設定函數的傳回值
a. 檢查所有可能的返迴路徑
b. 不要返回指向局部資料的引用或指標
3. Macro Routines and Inline Routines
宏子程式和內聯子程式
Key Points 要點
1. 建立子程式最主要的目的是提高程式的可管理性,當然也有其他一些好的理由。其中,節省代碼空間只是一個次要的原因;提高
可讀性,可靠性和可修改性等原因都更要重要一些。
2. 有時候,把一些簡單的操作寫成獨立的子程式也非常有價值。
3. 子程式可以按照其內聚性分為很多類,而你應該讓大多數子程式具有功能上的內聚性,這是最佳的一種內聚性。
4. 子程式的名字是它的品質的指標。如果名字糟糕但恰如其分,那就說明這個子程式設計的很差勁。如果名字糟糕而且有不準確
,那麼他就反映不出程式是幹什麼的。不管怎樣,糟糕的名字都意味著程式需要修改。
5. 只有在某一個子程式的主要目的是返回由其名字所描述的特定結果時,才應該使用函數。
6. 細心的程式員會非常謹慎的使用宏,而且只在萬不得已時才用。