在《重構》一書中,列舉了一些代碼的壞味道,同時以舉例方式講解了重構代碼的一些手法,本文是讀書後的關於如何寫好代碼的筆記,主要包括可讀性、代碼職責、面向對象思惟方面。前端
下面是一些提高代碼可讀性的手段、方法。java
當一個方法比較複雜、行數較多時,讀起來使人費解,這時應該抽取出一個個小段代碼的方法,且合理的命名方法,主方法中調用這些方法完成它所作的事情。
固然也不僅是方法複雜時須要抽取方法。後端
優點:
一、經過方法命名,讓主方法調用這些方法就能清晰表達主方法的流程,不須要經過註釋來解釋代碼做用
二、方法小了,代碼簡潔清晰,易於複用數組
代碼邏輯繁雜時,或一些複雜運算,能夠引入變量,並經過對變量的命名來提高可讀性。
如:.net
methodB(ClassX.methodC(methodA(a, b))) 能夠改成: int someValue = ClassX.methodC(methodA(a, b)); methodB(someValue);
如code
void method(Object A){ A = new Object(); }
當方法參列表較長時,提取對象進行包裝。通常建議參數個數≤3。對象
根據代碼的功能職責合理命名,便於理解blog
其目的引入解釋性變量相似繼承
將複雜的表達式拆分紅多個簡短的表達式,每個明確其意義。
如:接口
if(a.status != null && a.status = true && date > XXX && date < YYY){ ...... } 取代爲: if(validStatus(a.status) && valiadDate(date) ){ ...... }
能夠更清楚的表達出條件判斷的含義
if與else自己表達的是平級的關係,若是是某些特殊罕見條件特殊處理,採用if return的形式予以重視。
這樣可以清晰的體現代碼的主流程,不被一些特殊的處理掩蓋,讀起來更順暢。
如:
boolean flag; if(conditionX){ flag = false; } else{ if(conditionY){ flag = false; } else{ do something…… flag = calculate(); } } return flag; 改成: if(conditionX) return false; if(conditionY) return false; do something…… flag = calculate(); return flag;
服務內部不要採用錯誤碼來表示錯誤,如return -1表示失敗,而應該拋出異常表達
後端與前端服務間的交互可採用errorCode的方式。
關於異常可參考本人另外一篇文章: https://my.oschina.net/hebaod...
咱們常常說面向對象的單一職責原則,大到一個系統、模塊的職責邊界劃分,小到一個類、一個方法的職責。
清晰的劃分類、方法的職責,保持其單1、穩定的功能,能避免往後代碼愈來愈臃腫。
下面是關於代碼職責的處理方法。
某個方法不該該屬於這個類或package,移動方法到合適的地方。
某個屬於不該該屬於該對象,移動之。
類愈來愈大,如某個Service的public方法愈來愈多,功能混雜,考慮抽取不一樣的class維護這些方法或屬性。
代碼中出現多個if或switch case語句根據不一樣的條件,採起不一樣的行爲時,應該採用多態的思想。
如:
switch(var){ case v1: behavior1(); break; case v2: behavior2(); break; defalut: behavior3(); } 能夠提煉一個interfa Behavior,根據不一樣var建立不一樣的實現類,最後只須要調用behavior.method便可,也是一種策略模式的體現。
可是,上述說法還沒完全解決switch case的問題,由於要建立不一樣實現類,一種方法是定義一個map存儲映射關係。
採用繼承時,須要區分出某些屬性,方法究竟是共性仍是特性,共性就應該上移到超類中。特性即僅某些子類才具備,應該下移到子類。合理的進行抽象。
發現代碼中有一些共同或相似的行爲屬性時,要考慮提煉超類or接口。定義好抽象的關係,使代碼保持內聚。
關於抽象類與接口參考:https://www.zhihu.com/questio...
通常來講組合優先於繼承,組合表達的是has a的關係,繼承表達的是is a的關係。
組合的擴展性更強,且java不支持多繼承。更多關於組合與繼承的討論自行Google吧。
ps:我的blog地址:https://my.oschina.net/hebaod...