普通的工程師堆砌代碼,優秀的工程師優雅代碼,卓越的工程師簡化代碼。如何寫出優雅整潔易懂的代碼是一門學問,也是軟件工程實踐裏重要的一環。筆者推薦三本經典的書籍《代碼整潔之道 》、《編寫可讀代碼的藝術》、《重構:改善既有代碼的設計》,下文重點將從註釋、命名、方法、異常、單元測試等多個方面總結了一些代碼整潔最佳實踐,大部分是筆者總結於以上三本書中的精華,也有部分是筆者工程實踐的總結。篇幅有限,本文將總結性給出一些實踐建議,後續會有文章來給出一些代碼整潔之道的事例。html
不要給很差的名字加註釋,一個好的名字比好的註釋更重要;git
不要「柺杖註釋」,好代碼 > 壞代碼 + 好註釋;程序員
在文件/類級別使用全局註釋來解釋全部部分如何工做;編程
必定要給常量加註釋;設計模式
團隊統必定義標記:api
TODO 待處理的問題;併發
FIXME 已知有問題的代碼;編程語言
HACK 不得不採用的粗糙的解決方案;函數
在註釋中用精心挑選的輸入輸出例子進行說明;單元測試
註釋應該聲明代碼的高層次意圖,而非明顯的細節;
不要在代碼中加入代碼的著做信息,git能夠乾的事情不要交給代碼;
源代碼中的html註釋是一種厭物, 增長閱讀難度;
註釋必定要描述離它最近的代碼;
註釋必定要與代碼對應;
公共api須要添加註釋,其它代碼謹慎使用註釋;
典型的爛註釋:
不恰當的信息;
廢棄的註釋;
冗餘註釋;
糟糕的註釋;
註釋掉的代碼;
惟一真正好的註釋是你想辦法不去寫的註釋:
不要有循規式註釋,好比setter/getter註釋;
不要添加日誌式註釋,好比修改時間等信息(git能夠作的事情);
註釋必定是表達代碼以外的東西,代碼能夠包含的內容,註釋中必定不要出現;
若是有必要註釋,請註釋意圖(why),而不要去註釋實現(how),你們都會看代碼;
適當添加警示註釋;
儘量使用標準命名方法,好比設計模式,通用學術名詞等;
命名要找更有表現力的詞:
使用更專業的詞,好比不用get而使用fetch或者download;
避免空泛的名字,像tmp;
使用具體的名字來細緻的描述事物;
給變量名帶上重要的細節,好比加上單位ms等;
爲做用域大的名字採用更長的名字,做用域小的使用短名字;
變量類型爲布爾值表達加上is,has,can,should這樣的詞會更明確;
變量名稱長短應該與其做用域對應;
別懼怕長名稱,長而具備描述性的名稱比短而使人費解的名稱好;
函數名稱應該說明反作用,名稱應該表達函數,變量或類的一切信息,請不要掩蓋反作用,好比CreateAndReturnXXX;
函數不該該有100行那麼長,20行封頂最好:
if else while等控制語句其中代碼塊應該只有一行,也就是一個函數調用語句;
函數的鎖進層次不該該多於兩層;
一個函數只作一件事,一個函數不該該能抽象出另一個函數;
某個公共函數調用的私有函數緊隨其後;
最理想的參數是零參數,最長不要超過三個入參,儘可能不要輸出參數:
若是函數傳入三個及以上參數最好將其抽象爲類;
標識參數十分醜陋,向函數傳入布爾值用於區分不一樣業務的作法很醜陋,應該拆分爲多個函數;
別返回null值,拋出異常或者返回特殊對象,儘可能避免NPE;
別傳入null值;
抽離try catch包含的代碼塊,其中代碼塊抽象爲一個函數;
拋出的每一個異常,都應當提供足夠的環境說明,已便判斷錯誤的來源與處所;
不要將系統錯誤歸咎於偶然事件;
分離併發相關代碼與其它代碼;
嚴格限制對可能被共享的數據的訪問;
避免使用一個共享對象的多個同步方法;
保持同步區域微小,儘量少設計臨界區;
不要怕單元測試的方法名字太長或者繁瑣,測試函數的名稱就像註釋;
不要追求過高的測試覆蓋率,測試代碼前面90%一般比後面10%花的時間少;
使用最簡單的而且可以完整運用代碼的測試輸入;;
給測試函數取一個完整性的描述性名字,好比 Test _;
測試代碼與生產代碼同樣重要;
若是測試代碼不能保證整潔,你就會很快失去他們;
每一個測試一個斷言,單個測試中斷言數量應該最小化也就是一個斷言;
FIRST原則:
快速 Fast;
獨立 Independent 測試應該相互獨立;
可重複 Repeatable 測試應當在任何環境中重複經過;
自足驗證 Self-Validating 測試應該有布爾值輸出;
及時 Timely 最好的方式是TDD;
代碼行長度控制在100-120個字符;
可能用大多數爲200行,最長500行的單個文件構造出色的系統;
關係密切的代碼應該相互靠近:
變量聲明應該靠近其使用位置;
若某個函數調用了另一個,應該把他們放在一塊兒,並且調用者應該放在被調用者上面;
自上向下展現函數調用依賴順序;
應該把解釋條件意圖的函數抽離出來,儘量將條件表達爲確定形式;
不要繼承常量,好比接口中定義常量,不要使用繼承欺騙編程語言的做用範圍規則;
模塊不該瞭解它所操做對象的內部狀況;
DTO(Data Transfer Objects)是一個只有公共變量沒有函數的類;
對象暴露行爲,隱藏數據;
不要使用「尤達表示法」 如 if(null == obj),現代編譯器對if(obj = null)這樣的代碼會給出警告;
通常狀況使用if else,簡單語句使用三目運算符;
一般來說提前返回能夠減小嵌套並讓代碼整潔;
類應該足夠短小:
類應該知足單一權責原則(SRP),類和模塊只有一個修改理由;
類應該只有少許的實體變量;
類應該遵循依賴倒置原則 DIP(Dependency Inversion Principle),類應該依賴於抽象而不是依賴於具體細節;
類中的方法越少越好,函數知道的變量越少越好,類擁有的實體變量越少越好;
經過減小變量的數量和讓他們儘可能「輕量級」來讓代碼更有可讀性:
減小變量;
縮小變量的做用域;
只寫一次的變量更好,如常量;
最好讀的代碼就是沒有代碼:
從項目中消除沒必要要的功能,不要過分設計;
重新考慮需求,解決版本最簡單的問題,只要能完成工做就行;
常常性地通讀標準庫的整個API,保持對他們的熟悉程度;
簡單設計:
運行全部測試;
不可重複;
表達了程序員的意圖;
儘量減小類和方法的數量;
以上規則按重要程度排列;
不管是設計系統或者單獨模塊,別忘了使用大概可工做的最簡單方案;
整潔的代碼只提供一種而非多種作一件事的途徑,他只有儘可能少的依賴。明肯定義並提供儘可能少的API;
減小重複代碼,提升表達力,提前構建,簡單抽象;
做爲代碼整潔之道系列的第一篇,本文從註釋、命名、方法,單元測試,併發等視角簡單給出了一些最佳實踐,下文咱們會展開來從每一個方面介紹更多的實踐事例。相信每個優秀的工程師都有一顆追求卓越代碼的心,在代碼整潔工程實踐上你有哪些好的建議?數百人協做開發的代碼如何保證代碼整潔一致性?歡迎你們來討論。