作者:編碼磚家
出處:https://www.cnblogs.com/xiaoyangjia/p/11245235.html
很早就閱讀過《代碼整潔之道》(英文版Clean Code),當時博主是個青澀的菜鳥,正在為團隊創造著混亂的代碼。多年的工作中,屢次被別人的代碼坑的苦不堪言,回想起當年我留下的代碼,肯定也坑害了後來的同僚。當閱讀JDK源碼或者其他優秀開源工程時,歎服作者代碼構建之精良,他們都有共同的特點:精確的變量名、恰到好處的設計模式、詳細而不贅述的註釋等等。如今重讀本書,總結一下內容並加上自己的一些見解與大家分享。
代碼是團隊溝通方式
工作的溝通,不只是電子郵件或者面對面語言交流,代碼也是溝通方式之一。用代碼實現需求,只是萬里長征走完了第一步,必須讓代碼表達自己的設計思想。試想一下,你負責的功能被另外一個同事接手,如果你的代碼結構清晰、註釋合理,他就不用頻繁的詢問代碼疑點,不用打斷你的工作。編寫代碼的時候,應該考慮到別人的閱讀感受,減少閱讀障礙,為整個團隊創造代碼,而不是你自己。
讓營地比來時更乾淨
這是美國童子軍規的諺語,美國童子軍相當於半軍事化管理的青少年夏令營。夏令營結束後孩子們離開營地,要打掃衛生保持整潔,讓營地比來時更乾淨。在軟件開發過程中,可以理解為不要破壞規則,不要引入混亂。如果團隊已經制定了代碼規範,比如類名必須有子系統前綴比如BiOrderService(Bi指BI業務部門),就繼續遵循下去;再比如,團隊已經提供了公共庫比如MD5的加密,那就不要再次引入新的MD5庫。很多新手程序員接活兒後,看到不喜歡的規範就另起爐灶,需要某些工具類也不詢問老司機公共庫有沒有,直接引入自己熟悉的庫,造成兼容性或者其他問題。
合適的命名
合適的命名是頭等大事,正如給新生兒起個好名字那樣重要。不合適的命名通常是詞不達意、誤導觀眾、過度縮寫等,由於英文並非我們的母語,找個合適的單詞命名似乎真的很難。我建議是先把業務弄清楚,組織會議定下常用業務領域的單詞,禁止組員各自發明。比如代碼裡使用canteen表示飯堂,那就不要再發明DinnerHall,既囉嗦又誤導同僚。
看看反例:
// 手機號
String phone = “13421800409”;
// 獲取地址
private String getDiZhi();
//修改密碼
private void modifyPassword(String password1 ,String password2)
看看正例:
// 手機號 mobileNo比phone更精確
String mobileNo= “13421800409”;
// 避免英文拼音混雜
private String getAddress();
// 參數的命名要區分意義
private void modifyPassword(String oldPassowrd,String newPassword)
短小的方法
方法有多短小才合適沒有定論,但是長達500行的一個方法,絕對讓閱讀者起殺人之心。過長的方法,讓閱讀者不知道從何看起,看了前面忘記後面。將複雜的方法,拆分成邏輯相對簡單的短方法。
看看反例:
// 獲取個人信息
private UserDTO getUserDTO(Integer userId)
{
//獲取基本信息
… 此處寫了10行
//獲取最近的一次訂單信息
… 此處寫了30行
// 獲取錢包餘額、可用優惠券張數等
… 此處寫了30行
return userDTO;
}
看看正例:
// 獲取個人信息
private UserDTO getUserDTO(Integer userId)
{
//獲取基本信息
UserDTO userDTO= getUserBasicInfo(userId);
//獲取最近的一次訂單信息
userDTO.setUserLastOrder(getUserLastOrder(userId));
// 獲取錢包、可用優惠券張數等
userDTO.setUserAccount(getUserAccount(userId));
return userDTO;
}
private UserDTO getUserBasicInfo(Integer userId);
private UserLastOrder getUserLastOrder(Integer userId);
private UserAccount getUserAccount(Integer userId);
減少if/else嵌套
為什麼要減少嵌套,難道嵌套看上去不時尚嗎?我曾經看到某位同事的一段代碼嵌套達到9層,他自己再去維護的時候都看暈了。代碼過度嵌套的結果是隻有原作者才能讀懂,接盤俠一臉茫然。
看看反例:
看看正例:
正例採用衛語句減少了嵌套,但是並非所有場景都適合這樣改寫。如果不適合,可以將關聯性高的邏輯抽取成一個獨立的方法減少嵌套。
抽離try/catch
大家有沒有見過一個超長的方法,從頭到尾被一個try/catch照顧著?博主經歷過的項目中,這種不負責的寫法比比皆是。並非每行代碼都會拋出錯誤,只要將會拋出錯誤的業務放在一個獨立的方法即可。
看看反例:
看看正例:
封裝多個參數
如果方法參數將超過3個,建議放在類中包裝起來,否則再增加參數時,由於語義的強耦合會導致調用方語法錯誤。在後臺管理中的分頁查詢接口,常常會有很多查詢參數,而且有可能增加,封裝起來是最好的。
看看反例:
// 分頁查詢訂單 6個參數
public Page<order> queryOrderByPage(Integer current,Integer size,String productName,Integer userId,Date startTime,Date endTime,Bigdecimal minAmount ,Bigdecimal maxAmount) {
}
/<order>
看看正例:
@Getter
@Setter
public class OrderQueryDTO extends PageDTO {
private String productName;
private Integer userId;
private Date startTime;
private Date endTime;
private Bigdecimal minAmount ;
private Bigdecimal maxAmount;
}
// 分頁查詢訂單 6個參數
Public Page<order> queryOrderByPage(OrderQueryDTO orderQueryDTO) {
}
/<order>
第三方庫
Lombok
Lombok組件通過註解的方式,在編譯時自動為屬性生成構造器、getter/setter、equals、hashcode、toString方法
舉例如下:
@Setter 註解在類或字段,註解在類時為所有字段生成setter方法,註解在字段上時只為該字段生成setter方法。
@Getter 使用方法同上,區別在於生成的是getter方法。
@ToString 註解在類,添加toString方法。
@EqualsAndHashCode 註解在類,生成hashCode和equals方法。
@NoArgsConstructor 註解在類,生成無參的構造方法。
@RequiredArgsConstructor 註解在類,為類中需要特殊處理的字段生成構造方法,比如final和被@NonNull註解的字段。
@AllArgsConstructor 註解在類,生成包含類中所有字段的構造方法。
@Data 註解在類,生成setter/getter、equals、canEqual、hashCode、toString方法,如為final屬性,則不會為該屬性生成setter方法。
常規寫法:
Public class Order {
private Integer userId;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
return this.userId = userId;
}
}
採用Lombok:
@Getter
@Setter
Public class Order {
private Integer userId;
}
Apache Commons系列
Apache Commons系列組件給我們提供了關於字符串、集合、IO操作等工具方法。這些組件是個大寶庫,提供了不少輪子。
看看例子:
例1: 判斷集合是否為空:
CollectionUtils.isEmpty(null): true
CollectionUtils.isEmpty(new ArrayList()): true
CollectionUtils.isEmpty({a,b}): false
例2: 判斷集合是否不為空:
CollectionUtils.isNotEmpty(null): false
CollectionUtils.isNotEmpty(new ArrayList()): false
CollectionUtils.isNotEmpty({a,b}): true
例3:2個集合間的操作:
集合a: {1,2,3,3,4,5}
集合b: {3,4,4,5,6,7}
CollectionUtils.union(a, b)(並集): {1,2,3,3,4,4,5,6,7}
CollectionUtils.intersection(a, b)(交集): {3,4,5}
CollectionUtils.disjunction(a, b)(交集的補集): {1,2,3,4,6,7}
CollectionUtils.disjunction(b, a)(交集的補集): {1,2,3,4,6,7}
CollectionUtils.subtract(a, b)(A與B的差): {1,2,3}
CollectionUtils.subtract(b, a)(B與A的差): {4,6,7}
閱讀更多 程序員聖經 的文章