1. 程式人生 > >《程式碼整潔之道》學習總結

《程式碼整潔之道》學習總結

1. 整潔程式碼

1.1 整潔的程式碼力求集中,每個函式,每個類和每個模組都全神貫注於一事,完全不受四周細節的干擾和汙染。

1.2 減少重複程式碼,提高表達力,提早構建簡單物件(即不要重複程式碼,只做一件事,表達力,小規模抽象)。

1.3 設計原則的引用,包括單一職責原則(Single Responsibility Principle,SRP),開放閉合原則(Open Closed Principle,OCP)和依賴倒置原則(Dependency Inversion Principle,DIP)

2. 有意義的命名

2.1 如果名稱需要註釋來補充,那就不算是名副其實。

2.2 在命名時可以選擇指明瞭計量物件和計量單位的名稱。

2.3 別用accountList來指明一組賬號,除非它真的是List型別,List一詞對程式設計師有特殊意義,容易引起錯誤的判斷,用accountGroup或bunchOfAccount,甚至用accounts都會好一些。

2.4 長名稱勝於短名稱,搜得到的名稱勝於用自造編碼代寫就的名稱,當然短名稱若能表達出明顯的意圖則更好。

2.5 如果介面和實現必須選一個來編碼的話,選擇實現。ShapeFactoryImpl,甚至是醜陋的CShapeFactory,都比對介面名稱編碼來的好。

2.6 類名和物件名應該是名詞或名詞短語,不應當是動詞。

2.7 方法名應當是動詞或動詞短語。

2.8 過載構造器時,使用描述了引數的靜態工廠方法名,可以考慮將相應的構造器設定為private,強制使用這種命名手段。(即通過構造器私有化,通過靜態方法提供例項物件。)

2.9 當涉及多個概念(類似一系列controller,manager,driver等)時,可以通過公共類特徵+s進行統一。

2.10 避免將同一單詞用於不同目的,同一術語用於不同概念,即雙關語。比如多個類中均有add方法,則按不同的語義情景進行命名,也可以通過給名稱加前後綴,以此新增語境加以區分。

3. 函式

3.1 函式應該做一件事。做好這件事,只做這一件事。函式的語句都要在同一抽象層級上。

3.2 別害怕長名稱,長而具有描述性的名稱,要比短而令人費解的名稱好。長而具有描述性的名稱,要比描述性的長註釋好。

3.3 使用與模組名一脈相承的短語,名詞和動詞給函式命名。

3.4 如果函式要對輸入引數進行轉換操作,轉換結果就該體現為返回值。

3.5 如果函式需要兩個,三個或三個以上引數,就說明其中一些引數應該封裝為類了。

3.6 普遍而言,應避免使用輸出引數(需求減少)。

3.7 在進行boolean值判斷時,應當把指令與詢問分隔開來,相當於可以把判斷邏輯封裝在函式裡,用類似xxxIsTrue/Existed代替。

3.8 最好把try和catch程式碼塊的主體部分抽離出來,另外形成函式。

3.9 使用異常代替錯誤碼,新異常就可以從異常類派生出來,無需重新編譯或重新部署。

3.10 在不斷嘗試中消滅重複。打磨程式碼,分解函式,修改名稱,消除重複,甚至縮短和重新安置方法,拆散類,保持測試通過。

4. 註釋

4.1 註釋總是一種失敗,我們總無法找到不用註釋就能表達自我的方法,所以總要有註釋。儘管有時也需要註釋,我們也該多花心思儘量減少註釋量。

4.2 用程式碼去解釋你大部分的意圖,唯一真正好的註釋是你想辦法不去寫的註釋。

4.3 註釋的作用是解釋未能自行解釋的程式碼,如果註釋本身還需要解釋,那就太遺憾了。

4.4 雖然Javadoc對於公共API非常有用,但對於不打算作公共用途的程式碼就令人厭惡了。

5. 格式

5.1 幾乎所有的程式碼都是從上往下讀,從左往右讀。每行展現一個表示式或一個子句,每組程式碼行展示一條完整的思路,這些思路用空白行區分開來。(比如不同方法間,展現垂直方向上區隔的作用)。

5.2 被呼叫的函式應該放在執行呼叫函式的下面,這樣就建立了一種自頂向下貫穿原始碼模組的良好資訊流。 

5.3 水平分割中,強聯絡的程式碼單詞之間不用空格分開,弱聯絡的用空格字元加強分隔效果。(類似乘法因子之間沒加空格,因為它們具有較高優先順序。加減法運算項之間用空格隔開,因為加法和減法優先順序較低)。

6. 物件和資料結構

6.1 物件把資料隱藏於抽象之後,曝露操作資料的函式。資料結構曝露其資料,沒有提供有意義的函式。(兩種定義本質上是對立的)。

6.2 過程式程式碼難以新增新資料結構,因為必須修改所有函式。面向物件程式碼難以新增新函式,因為必須修改所有類。

6.3 得墨忒耳律認為:模組不應瞭解它所操作物件的內部情形,方法不應呼叫由任何函式返回的物件的方法(類似於呼叫了返回值結果的方法,效果呈現連續呼叫,也稱“火車失事”)。

6.4 最為精煉的資料結構,是一個只有公共變數,沒有函式的類。這種資料結構有時被稱為資料傳送物件,或DTO(Data Transfer Objects)。DTO是非常有用的結構,尤其是在於資料庫通訊,或解析套接字傳遞的訊息之類場景中。

6.5 物件曝露行為,隱藏資料,便於新增新物件型別而無需修改既有行為,同時也難以在既有物件中新增新行為;資料結構曝露資料,沒有明顯的行為,便於向既有資料結構新增新行為,同時也難以向既有函式新增新資料結構。

7. 錯誤處理

7.1 錯誤處理很重要,但如果它搞亂了程式碼邏輯,就是錯誤的做法。

7.2 使用異常而非返回碼,往往使用定義異常+錯誤碼+Msg。

7.3 用特定物件返回代替業務邏輯與錯誤處理結合,將異常行為封裝到指定物件中。

7.4 如果你打算在方法中返回null值,不如丟擲異常,或是返回特例物件。如果你在呼叫某個第三方API中可能返回null值的方法,可以考慮用新方法打包這個方法,在新方法中丟擲異常或返回特例物件。(類似於一箇中間轉換)。

7.5 如果將錯誤處理隔離看待,獨立於主要邏輯之外,就能寫出強固而整潔的程式碼。

8. 邊界

8.1 邊界上的介面(Map)是隱藏的,它能隨來自應用程式其他部分的極小的影響而變動。

9. 單元測試

9.1 TDD三定律:                                      

 定律一  在編寫不能通過的單元測試前,不可編寫生產程式碼 。

 定律二  只可編寫剛好無法通過的單元測試,不能編譯也算不通過。

 定律三  只可編寫剛好足以通過當前失敗測試的生產程式碼。

9.2 測試程式碼和生產程式碼一樣重要,需要保證可讀性。

9.3 雙重標準,有些事你大概永遠不會在生產環境中做,而在測試環境中做卻完全沒有問題。

9.4 單個測試中的斷言數量應該最小化。

9.5 最佳規則也許是應該儘可能減少每個概念的斷言數量,每個測試函式只測試一個概念。

10. 類

10.1 系統應該由許多短小的類而不是少量巨大的類組成。每個小類封裝一個權責,只有一個修改的原因,並與少數其他類一起協同達成期望的系統行為。

10.2 開放-閉合原則(Open Closed Principle,OCP):類應當對擴充套件開放,對修改封閉。在理想系統中,我們通過擴充套件系統而非修改現有程式碼來新增新特性。

10.3 依賴倒置原則(Dependency Inversion Principle,DIP),本質而言,DIP認為類應當依賴於抽象而不是具體細節。

(未完待續~)