代碼整潔之道

一、勒布朗法則——稍後等於用不

二、不該該羞於告知本身的想法

咱們可能把混亂的代碼歸咎於專一於項目進度的產品經理、苛求的用戶,可是實際上是咱們太不專業了。 對於不合理的要求咱們應該提出來,多數經理想要知道實情,即使他們看起來不喜歡實情。多數經理想要好代碼,即使他們老是癡迷於進度。他們會奮力衛護進度和需求,那是他們應該乾的。所以咱們也應當以一樣的熱情衛護代碼java

1、有意義的命名

三、代碼塊要儘可能小

實際上,從有軟件起人們就在反覆強調這一點。越小越好。程序員

四、命名要儘可能名副其實

  • 變量、函數或類的名稱應該已經答覆了全部的大問題。
  • 不要懼怕名稱過長。
  • 選個好名字要花時間,但省下來的時間比花掉的多。
  • 一旦有更好的名稱,就換掉舊的。

五、命名要避免誤導

  • 應當儘可能避免使用與本意相悖的詞。
  • 別用accountList來指稱一組帳號,除非他真的是List類型。List一詞對程序員有特殊意義。若是包納帳號容器並不是真是個List,除非他真的是List類型。即便容器就是個List,最好也別再名稱中寫出容器名。甚至直接用accounts都會好一些。(PHP應該沒這些要求吧)
  • 類似的名稱就別用了

六、廢話就是冗餘

命名中儘可能避免廢話。bash

七、命名要儘可能使用讀得出來的名稱

人類長於記憶和使用單詞。數據結構

八、定義常量!!!!

方便查找和修改。app

九、避免思惟映射

循環計數器天然有可能被命名爲i或j或k(但千萬別用字母I),這是由於傳統上慣用但字母名稱作循環計數器。 其餘狀況下最好就別用了。函數

十、類名應該是名詞,如Customer,而不該該是動詞。

十一、方法名應當是動詞或動詞短語。

十二、每一個概念對應一個詞

controller這種名字相似的單元測試

2、函數

1三、短小

  • 函數的第一規則是要短小
  • 函數的第二條規則還要更短小

1四、只作一件事

函數應該作一件事。作好這件事。只作這一件事。 要判斷韓式是否不止作了一件事,有一個方法,就是看是否能再拆出一個函數,改函數不只是單純的從新詮釋其實現。測試

1五、每一個函數一個抽象層級

抽象層級是個什麼概念呢? 如: getHtml()算是較高抽象層 String pagePathName = PathParser.render(pagePath) 算是中間抽象層 .append("\n") 算是至關低的抽象層ui

1六、 switch 語句

  • 確保每一個switch都埋藏在較低的抽象層級,並且永遠不重複
  • 單一權責原則 簡單說,就是一個類負責一個職責。
  • 開放閉合原則 軟件實體(類、模塊、函數等等)應該能夠擴展,可是不可修改。
  • 儘量抽象 示例
public Money calculatePay(Employee e)
throws InvalidEmployeeType {
   switch (e.type) {
        case COMMISSIONED:
            return calculateCommissionedPay(e);
        case HOURLY:
            return calculateHourlyPay(e);
        case SALARIEED:
            return calculateSalariedPay(e);
        default:
            throw new InvalidEmployeeType(e.type);
        }
}
複製代碼

上述代碼可能處處都有相似結構的函數。多是isPayday(Employee e, Date date)或deliverPay(Employee e, Date date);this

解決方案就是:**將switch語句埋到抽象工廠地下,不讓任何人看到。該工廠使用switch語句爲Employee的派生物建立適當的實體,而不一樣的函數,如calculatePay、isPayday和deliverPay等,則藉由Employee接口多態的接受派遣。

1七、 函數參數

  • 參數儘可能要少 最理想的參數數量是零(零參數函數),其次是一(單參數函數),再次是二(雙參數函數),應儘可能避免三(三參數函數)。有足夠特殊的理由才能用三個以上參數(多參數函數)。——因此不管如何也不要這麼作。 若是函數看起來須要兩個、三個或三個以上參數,就說明其中一些參數應該封裝爲類了。

1八、無反作用

什麼是反作用? 反作用是函數只承諾作一件事情,但仍是作其餘被藏起來的實情。 若是咱們忽略了,就作了可能咱們並不指望的事情。

1九、輸出參數

static void appendFooter(StringBuilder sb) {
        sb.append("Here you go!");
    }
複製代碼

咱們應該儘可能避免使用appendFooter(s)這樣的用法。應儘可能使用report.appendFooter()方法。 由於咱們會浪費檢查函數聲明的時間。 面嚮對象語言中對輸出參數大部分的需求已經消失了,由於this也有輸出函數的意味在內。

20、使用異常代替返回錯誤碼

緣由:在深層次的嵌套結構中,當返回錯誤碼的時候,要求當即處理錯誤。 使用異常的話,錯誤處理代碼就能從主路徑代碼中分離出來,獲得簡化。

2一、抽離Try/Catch代碼塊

Try/Catch代碼塊醜陋不堪。他們搞亂了代碼結構,把錯誤代碼處理與正常流程混爲一談。最好把try 和 catch 代碼塊的主體部分抽離出來,另外造成函數。

2二、錯誤處理就是一件事

函數應該只作一件事。錯誤處理就是一件事。

2三、Error.java 依賴磁鐵

返回錯誤碼一般暗示某處有個類或是枚舉,定義全部錯誤碼。 若是使用它,Error枚舉修改時,全部這些其餘的類都須要從新編譯和部署。這對Error類形成了負面壓力 ===》程序員就使用舊的錯誤碼,不肯意增長新的錯誤代碼。 使用異常替代錯誤碼,新異常就能夠從異常類派生出來。無需從新編譯或從新部署。

2四、別重複本身!!!

不要寫重複代碼 重複代碼會增長忽略錯誤的可能性

3、註釋

註釋說明咱們代碼寫的並很差。 可是咱們有時候又必需要寫註釋。 可是程序員又不會及時維護註釋,因此隨着時間流逝,註釋離所描述的代碼愈來愈遠。 惟一真正好的註釋是你想辦法不去寫的註釋 用整理代碼的決心替代創造廢話的衝動。

2五、警示註釋

2六、TODO註釋

2七、括號後面的註釋

//while //try 相似的 這對於深層嵌套頗有意義 可是咱們爲何不寫更小的、封裝的函數呢?

2八、註釋掉的代碼

直接把代碼註釋掉是討厭的作法。別這麼幹!!!(我作了 55555~) 可能的緣由是:1⃣️不敢刪除2⃣️用於提示3⃣️…… 可是這些都不能否認混亂了代碼 如今的源代碼控制系統已經保證代碼丟不了了,刪除便可

4、格式

先明確一點,代碼格式很重要,代碼格式不可忽略,必須嚴肅對待。(以前的我…………)

2九、概念間垂直方向上的區隔

在封包聲明、導入聲明、每一個函數等等之間。有空白行隔開。這條極其簡單的規則很是有利於代碼閱讀。

30、垂直方向上的靠近

有緊密關係的代碼應該靠近,方便閱讀理解。

3一、垂直距離

  • 關係密切的概念應該互相靠近,有助於理解系統作什麼。而不是把時間和精力找到和記住代碼碎片在哪裏。(除非有很好的理由放到不一樣的文件中)
  • 變量聲明 應該儘量靠近其使用的位置。
  • 實體變量 實體變量應該在類的頂部聲明。
  • 相關函數 若某個函數調用另一個,就應該把他們放在一塊兒,並且調用者應該儘量發在被調者上面。
  • 概念相關 概念相關的代碼應該放到一塊兒。相關性越強,彼此之間的距離就該越短。

3二、橫向格式

應該儘可能保持代碼行短小。 能夠遵循一個原則:無需拖動滾動條到右邊的原則。

5、對象和數據結構

對象暴露行爲,隱藏數據。便於添加新對象類型而無需修改既有行爲。同時也難以在既有對象中添加新行爲。數據結構暴露數據,沒有明顯的行爲,便於向既有數據結構添加新行爲,同時也難以向既有函數添加新數據結構。

6、錯誤處理

錯誤處理很重要,但若是他搞亂了代碼邏輯,就是錯誤的作法

3三、使用異常而非返回碼

若是使用了錯誤碼,調用者必須在調用以後即刻檢查錯誤。不幸的是,這個步驟很容易被遺忘。

3四、先寫Try-Catch-Finally語句

異常的妙處之一是,他們在程序中定義了一個範圍 執行try-catch-finally語句中try部分的代碼時,是在代表可隨時取消執行,並在catch語句中繼續 在編寫可能拋出異常的代碼時,最好先寫出try-catch-finally語句。這能幫你定義代碼的用戶應該期待什麼。不管try代碼塊中執行的代碼出什麼錯都同樣

3五、使用不可控異常

  • 可控異常的代價是違反了開放/閉合原則
  • 若是你在方法中拋出可控異常而catch語句在三個層級之上,你就得在catch語句和拋出異常處之間的每一個方法簽名中聲明該異常
  • 以此類推,最終獲得的就是一個從軟件最底端貫穿到最高端的修改鏈。
  • 可控異常以這種方式破壞封裝簡直是一種恥辱
  • 對於通常的應用開發,可控異常的依賴成本要高於收益。

3六、給出異常發生的環境說明

有助於判斷錯誤的來源和處所

3七、依調用者須要調用異常類。

舉例說明:

ACMEPort port = new ACMEPort(12);

try {
    port.open();
 } catch (DeviceReesponseeException e) {
    reportPortError(e);
    logger.log("Device response exception", e);
} catch (ATM1212UnlockedException e) {
    reportPortError(e);
    logger.log("Unlock exception", e);
} catch (GMXError e) {
    reportPortError(e);
    logger.log("Device response exception");
} finally {
...
}
複製代碼

上述語句包含了一大堆重複的代碼。 咱們能夠將new port 和 異常處理打包一個新的函數。

好的作法是將第三方API打包。當你打包一個第三方API,你就下降了對他的依賴:將來你能夠不太痛苦的改用其餘代碼庫。在你測試本身的代碼時,打包也有助於模擬第三方調用

3八、別返回null 值

3九、別用null值

7、單元測試

40、TDD三定律

TDD是**測試驅動開發**(Test-Driven Development)的英文簡稱,是敏捷開發中的一項核心實踐和技術,也是一種設計方法論。TDD的原理是在開發功能代碼以前,先編寫單元測試用例代碼,測試代碼肯定須要編寫什麼產品代碼。TDD雖是敏捷方法的核心實踐,但不僅適用於XP(Extreme Programming),一樣能夠適用於其餘開發方法和過程。

  • 定律一 在編寫不能經過的單元測試前,不可編寫生產代碼。
  • 定律二 只可編寫恰好沒法經過的單元測試,不能編譯也算不經過。
  • 定律三 只可編寫恰好足以經過當前失敗測試的生產代碼。
相關文章
相關標籤/搜索