《代碼大全第二版》學習筆記(二)

第三部分 變量

第十章 使用變量的一般事項

10.3 變量初始化原則

1.         在聲明變量的時候初始化。

2.         在靠近變量第一次使用的位置初始化它。相關的操作放在一起。

3.         理想情況下,在靠近第一次使用變量的位置聲明和定義該變量。

4.         在可能的情況下使用final或者const

5.         特別注意計數器和累加器。

6.         在類的構造函數裏初始化該類的數據成員。

7.         檢查是否需要重新初始化。

8.         一次性初始化具名常量:用可執行代碼來初始化變量。

9.         使用編譯器設置來自動初始化所有變量。

10.     利用編譯器的警告信息。

11.     檢查輸入參數的合法性。

12.     使用內存訪問檢查工具來檢查錯誤的指針。

13.     在程序開始時初始化工作內存。把程序的工作內存填充爲一個可以預料的值。也能保證程序不會因內存初始值的隨機性而受到影響。

10.4 作用域

減小作用域的一般原則。

1.         在循環開始之前再去初始化該循環裏使用的變量,而不是在該循環所屬的子程序的開始處初始化這些變量。

2.         直到變量即將被使用時再爲其賦值。

3.         把相關語句放到一起。

4.         把相關語句組提取成單獨的子程序。

5.         開始時採用最嚴格的可見性,然後根據需要擴展變量的作用域。

這是方便性和智力可管理性理念的爭鬥。

10.5持續性

與持續性相關的最主要問題是變量實際生命期比你想象的要短。

1.         在程序中加入調試代碼或者斷言來檢查哪些關鍵變量的合理取值。如果變量取值變得不合理,就發出警告信息通知你去尋找是否有不正確的初始化。

2.         準備拋棄變量時給它們賦上不合理的數值。例如指針置null

3.         編寫代碼時要假設數據並沒有持續性。不適於static

4.         養成在使用所有數據之前聲明和初始化的習慣。

10.6 綁定時間

把變量和它的值綁定在一起的時間。

1.         編碼時(使用神祕數值)。

2.         編譯時(使用具名常量)。

3.         加載時(從Windows註冊表、Java屬性文件等外部數據源中讀取數據)。

4.         對象實例化時(例如在美刺窗體創建的時候讀取數據)。

5.         即時(例如在每次窗體重繪的時候讀取數據)。

綁定時間越早靈活性越差,但複雜度也會降低。

10.8 爲變量指定單一用途

1.         每個變量只用於單一用途。少用temp這類。

2.         避免讓代碼具有隱含意義。比如祕密約定大於500000就是過期賬戶。

3.         確保使用了所有已聲明的變量。

第十一章 變量名的力量

11.1 選擇好變量名的注意事項

該名字要完全、準確地描述出該變量所代表的事物。

以問題爲導向。表達what而不是how

名字長度在8-20個字符之間。

對位於全局命名空間中的名字加以限定詞。

變量名中的計算值限定詞放到名字的最後,如revenueTotalcustomerCountcustomerIndex

變量名中常用的對仗詞:

11.2 爲特定類型的數據命名

1.         爲循環下標命名,描述性。

2.         爲狀態變量命名,別帶flag,描述性。

3.         爲臨時變量命名,警惕臨時變量,這表示你還沒有弄清它們的實際用途。

4.         爲布爾變量命名,

a)         謹記典型的布爾變量名。如:done/error/found/success

b)         給布爾變量賦予隱含真/假含義的名字:isDone/isProcessingComplete

c)         使用肯定的布爾變量名,以免雙重否定。

5.         爲枚舉變量命名,使用組前綴區別組。

6.         爲常量命名,描述性。

11.4 非正式命名規則

與語言無關的命名規則的指導原則

1.         區分變量名和子程序名字。

2.         區分類和對象。如 Widget aWidget;

3.         標識全局變量。g_前綴。

4.         標識成員變量。m_前綴。

5.         標識類型聲明。如t_Color

6.         標識具名常量。如c_

7.         標識枚舉類型的元素。如Color_前綴。

8.         格式化命名以提高可讀性。

與語言相關的命名規則的指導原則

第十二章 基本數據類型

12.1 數值概論

1.         避免使用magic number

2.         如果需要,可以使用硬編碼的01.

3.         預防除零錯誤。

4.         使類型轉換變得明顯。

5.         避免混合類型的比較。

6.         注意編譯器的警告。

12.2 整數

1.         檢查整數除法。應當最後執行除法,以防截去小數後的錯誤。

2.         檢查整數溢出。

3.         檢查中間結果溢出。換用更長的整型或者浮點型。

12.3 浮點數

1.         避免數量級相差巨大的數之間的加減運算。先對這些數排序,然後從最小值開始把它們加起來。

2.         避免等量判斷。先確定可接受的精確度範圍,然後用布爾函數判斷數值是否足夠接近。Equals()函數。

3.         處理舍入誤差問題。

4.         檢查語言和函數庫對特定數據類型的支持。

12.4 字符和字符串

1.         避免使用神祕字符和神祕字符串。

2.         避免off-by-one錯誤。即因爲讀寫操作超出了字符串末尾而導致的錯誤。

3.         瞭解你的語言和開發環境是如何支持Unicode的。

4.         在程序生命期中儘早決定國際化/本地化策略。比如,決定是否把所有字符串保存在外部資源裏,是否爲每一種語言創建單獨的版本,或者在運行時確定特定的界面語言。

5.         如果你知道只需要支持單一文字的語言(如英語,非漢語),請考慮使用ISO8859字符集。

6.         如果你需要支持多種語言,請使用Unicode

7.         採用某種一致的字符串類型轉換策略。

12.5 布爾變量

1.         用布爾變量對程序加以文檔說明。不同於僅僅判斷一個布爾表達式,你可以把這種表達式的結果賦給一個變量,從而使得這一判斷的含義變得明顯。

2.         用布爾變量來簡化複雜的判斷。

3.         如果需要的話,創建你自己的布爾類型。C++不需要。

12.6 枚舉類型

1.         用枚舉類型來提高可讀性。特別適用於定義子程序參數。

2.         用枚舉類型來提高可靠性。

3.         用枚舉類型來簡化修改。

4.         將枚舉類型作爲布爾變量的替換方案。

5.         檢查非法數值。

6.         定義出枚舉的第一項和最後一項,以便用於循環邊界。

7.         把枚舉類型的第一個元素留做非法值。即0

8.         明確定義項目代碼編寫標準中第一個和最後一個元素的使用規則,並且在使用時保持一致。合法項都從1開始?美劇中第一個和最後一個元素合法嗎?

9.         警惕給枚舉元素明確賦值而帶來的失誤。小心中間是否有非法數值。

12.具名常量

1.         在數據聲明中使用具名常量。

2.         避免使用magic number,即使是安全的。

3.         統一地使用具名常量。

12.8 數組

少用,用容器。

12.9 創建你自己的類型(類型別名)

typedef float coordinate;         // for coordinate variables

易修改,數據集中在一處好管理,增加可靠性。

1.         給所創建的類型取功能導向的名字。

2.         避免使用預定義類型。

3.         不要重定義一個預定義的類型。

4.         定義替代類型以便於移植。

5.         考慮創建一個類而不是使用typedef

第十三章 不常見的數據類型

13.1 結構體

用結構體(只讓相關的東西在一起)的理由:

1.         用結構體來明確數據關係。

2.         用結構體簡化對數據塊的操作。

3.         用結構體來簡化參數列表。

4.         用結構體來減少維護。

13.2 指針

1.         把指針操作限制在子程序或者類裏面。

2.         同時聲明和定義指針。初始化。

3.         在與指針分配相同的作用域中刪除指針。誰創建誰刪除。

4.         使用指針之前檢查指針。

5.         先檢查指針所引用的變量再使用它。

6.         用狗牌字段來檢測損毀的內存。tag field或者dog tag是指你加入結構體內的一個僅僅用於檢測錯誤的字段。在分配一個變量的時候,把一個應該保持不變的數值放在它的標記字段裏。當使用該結構的時候——特別是釋放其內存的時候——檢測這個標記字段的取值。如果這個標記字段的取值與預期不相符,那麼這一數據就被破壞了。

7.         用額外的指針變量來提高代碼清晰度。

8.         簡化複雜的指針表達式。

9.         畫一個圖。

10.     分配一片保留的內存後備區域。

11.     在刪除或者釋放指針之後把它們設爲空值。

12.     在刪除變量之前檢查非法指針。

13.     編寫覆蓋子程序,集中實現避免指針問題的策略。SAFE_NEW/SAFE_DELETE

針對C++

1.         理解指針和引用之間的區別。

2.         把指針用於按引用傳遞參數,把const引用用於按值傳遞參數。

3.         使用auto_ptr

4.         靈活運用智能指針。

13.3 全局數據

用訪問器子程序來取代全局數據。

1.         要求所有的代碼通過訪問器子程序來存取數據。

2.         不要把你所有的全局數據都扔在一處。

3.         用鎖定來控制對全局變量的訪問。

4.         在你的訪問器子程序裏構建一個抽象層。

5.         使得對一項數據的所有訪問都發生在同一個抽象層上。

只有萬不得已時才使用全局數據。

1.         創建一種命名規則來突出全局變量。

2.         爲全部的全局變量創建一份註釋良好的清單。

3.         不要用全局變量來存放中間結果。

4.         不要把所有的數據都放在一個大對象中併到處傳遞,以說明你沒有使用全局變量。

第四部分 語句

第十四章 組織直線型代碼

1.         組織直線型代碼的最主要原則是按照依賴關係進行排列。

2.         可以用好的子程序名、參數列表、註釋,以及——如果代碼足夠重要——內務管理變量來讓依賴關係變得更明顯。

3.         如果代碼之間沒有順序依賴關係,那就設法使相關的語句儘可能地接近。

第十五章 使用條件語句

1.         對於簡單的if-else語句,注意順序,特別是用來處理大量錯誤的時候。要確認正常的情況是清晰的。

2.         對於if-then-else語句串和case語句,選擇一種最有利於閱讀的排序。

3.         爲了捕捉錯誤,casedefaultif-then-else用最後的else

4.         各種控制結構並不是生來平等的。請爲代碼的每個部分選用最合適的控制結構。

第十六章 控制循環

1.         保持循環簡單有助於別人閱讀你的代碼。

2.         保持循環簡單的技巧包括:避免使用怪異的循環、減少嵌套層次、讓入口和出口一目瞭然、把內務操作代碼放在一處。

3.         循環下標易被濫用。因此命名要準確,並且要把它們各自僅用於一個用途。

4.         仔細地考慮循環,確認它在每一種情況下都運行正常,並且在所有可能的條件下都能退出。

第十七章 不常見的控制結構

17.1 子程序中的多處返回

1.         如果能增強可讀性,那麼久使用return

2.         用早返回或早退出來簡化複雜的錯誤處理,避免很深的嵌套邏輯。

3.         減少每個子程序中return的數量。

17.2 遞歸

1.         確認遞歸能夠停止。

2.         使用安全技術器防止出現無窮遞歸。

3.         把遞歸限制在一個子程序內。

4.         留心棧空間。可以new在堆上。

5.         不要用遞歸去計算竭誠或者斐波那契數列。

第十八章 表驅動法

表驅動法是一種編程模式(scheme——從表裏面查找信息而不使用邏輯語句(ifcase)。程序中的信息存放在數據裏而不是邏輯裏。

18.1 表驅動法使用總則

兩個問題:怎樣從表裏查詢條目;應該在表裏面存些什麼。

三種方法:直接訪問(Direct access)、索引訪問(Indexed access)、階梯訪問(Stair-step access)。

18.2 直接訪問表

構造查詢鍵值(如1-10一個樣,11-50一個樣,中間那些重複的怎麼辦?)

1.         複製信息從而能夠直接使用鍵值。冗餘易出錯。

2.         轉換鍵值以使其能夠直接使用。

3.         把鍵值轉換提取成獨立的子程序。

18.3 索引訪問表

有的時候,只用一個簡單的數學運算還無法把age這樣的數據轉換成爲表鍵值。這類情況中的一部分可以通過使用索引訪問的方法加以解決。

當你使用索引的時候,先用一個基本類型的數據從一張索引表中查出一個鍵值,然後再用這一鍵值查出你感興趣的主數據。

18.4 階梯訪問表

比索引訪問方法省空間,費時間。表中的記錄對於不同的數據範圍有效,而不是對不同的數據點有效。

1.         留心端點。

2.         考慮用二分查找取代順序查找。

3.         考慮用索引訪問取代階梯技術。

4.         把階梯表查詢操作提取成單獨的子程序。

第十九章 一般控制問題

19.1 布爾表達式

只用truefalse

簡化複雜的表達式:

1.         拆分複雜的判斷並引入新的布爾變量。

2.         把複雜的表達式做成布爾函數。

3.         用決策表代替複雜的條件。

編寫肯定形式的布爾表達式。

用括號使布爾表達式更清晰。

19.4 馴服危險的深層嵌套

1.         通過重複檢測條件中的某一部分來簡化嵌套的if語句。

2.         break塊來簡化嵌套if

3.         把嵌套if轉換成一組if-then-else語句。

4.         把嵌套if轉換成case語句。

5.         把深層嵌套的代碼抽取出來放進單獨的子程序。

6.         使用一種更面向對象的方法。多態。

7.         重新設計深層嵌套的代碼。

19.5 編程基礎:結構化編程

一個應用程序應該只採用一些單入單出的控制結構。單入單出的控制結構指的就是一個代碼塊,它只能從一個位置開始執行,並且只能結束於一個位置。初次之外再無其他入口或出口。

結構化編程的三個組成部分

1.         順序Sequence:順序指一組按照先後順序執行的語句。

2.         選擇Selection:選擇是一種有選擇的執行語句的控制語句。

3.         迭代Iteration:迭代是一種使一組語句多次執行的控制結構。循環。

將複雜度降低到最低水平是編寫高質量代碼的關鍵。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章