讀書報告之《修改程式碼的藝術》 (II)續2
阿新 • • 發佈:2018-10-31
這裡作為(II)的第二個續篇,繼續複雜的巢狀if else 的處理。 為了保持篇幅不會太長,以一篇新的文章形式給出。
化簡複雜的if else語句,基本的手段
- 針對頭重腳輕的if else,使用return快速返回,從而減少巢狀層數。
- 合併分支。有些分支的執行內容相同,往往意味著可以合併為一個分支
- 扁平化。
這裡給出最後一個舉例,也是從網上隨便搜尋摘錄的
原始程式碼
List<TWorkFlowwork> wfwList=errorProcessingService.findWorkFlowworkByWorkType("7",workbillcode.getId()+""); boolean flag=false; if(wfwList!=null&&wfwList.size()>0){ for(int i=0;i<wfwList.size();i++){ TWorkFlowwork wfw=wfwList.get(i); if(wfw!=null){//當前待辦是原件校驗並且如果已經結束了則啟用原件校驗待辦 if(wfw.getStatus()!=null&&!"".equals(wfw.getStatus())){ if("1".equals(wfw.getStatus())){ flag=true; break; } } } } if(!flag){//如果原件校驗待辦都結束了,則產生一條原件校驗待辦 TWorkBillcode wb=errorProcessingService.findWorkBillcodeByParameters(flow.getBussid(),flow.getBusstype()); wb.setIsmatchpage("1"); errorProcessingService.updateWorkBillcode(wb); } }
老規矩,簡單點評一下這個程式碼:唉~~~~~~~
- 魔幻數字"7",“1”
- 大量的空物件判斷。 這個不是表示嚴謹,而是程式碼設計有問題
- 極深的if else 巢狀,主要都是極端的頭重腳輕形式的if 語句
if(wfw.getStatus()!=null&&!"".equals(wfw.getStatus())
&& "1".equals(wfw.getStatus())){
flag=true;
break;
}
仔細分析,不難發現wfw.getStatus()!=null&&!"".equals(wfw.getStatus()) 根本是多餘的。
於是程式碼變成這個樣子List<TWorkFlowwork> wfwList=errorProcessingService.findWorkFlowworkByWorkType("7",workbillcode.getId()+"");
boolean flag=false;
if(wfwList==null || wfwList.size()==0) { return; }
for (TWorkFlowwork wfw : wfwList) {
//當前待辦是原件校驗並且如果已經結束了則啟用原件校驗待辦
if (wfw == null) { continue; }
if("1".equals(wfw.getStatus())){
flag=true;
break;
}
}
if(!flag){//如果原件校驗待辦都結束了,則產生一條原件校驗待辦
TWorkBillcode wb=errorProcessingService.findWorkBillcoHideByParameters(flow.getBussid(),flow.getBusstype());
wb.setIsmatchpage("1");
errorProcessingService.updateWorkBillcode(wb);
}
接下來,本來想對第一個迴圈做一個方法抽取,因為實際操作比較像查詢——查詢是否所有原件已經校驗結束。改成查詢之後,不僅含義上清楚到無需註釋,而且可以去掉討厭的標記變數flag以及wfwList為空的判斷。 可惜沒有全部程式碼,不知道這樣修改是否會產品副作用。因為對最後一段“如果原件校驗待辦都結束了,則產生一條原件校驗待辦”這個註釋無法拿捏得很準,這個“產生一條”是指產生下一條? 所以說,理想的情況是讓程式碼自注釋。如果寫了註釋,一定要維護程式碼的同時維護註釋,錯誤的註釋比沒有註釋更糟糕。不管如何,原本複雜的if else 我們已經大大簡化了。 最後再囉嗦一下,面試時程式碼的編寫確實是必不可少的一部分:從這份程式碼就可以看出
- 原作者對java的基本語法不熟;// 迴圈語句很拙劣,可能是從C轉入沒多久
- 之前系統的培訓過或者認真看過相關編碼的書; // 大量的魔幻數字,wfwList.size()==0 而不是isEmpty()
- 程式碼量不大。// 這個程式碼片段不長,卻非常費解。而且程式碼層次感不強,各種高層的介面和底層的介面雜糅在一起
最後的最後,做個簡單的總結。
這一部分主要是舉例討論複雜的鋸齒形 if else語句的處理。基本方法不外乎三個- 針對頭重腳輕的if else,使用return快速返回,從而減少巢狀層數。
- 合併分支。有些分支的執行內容相同,往往意味著可以合併為一個分支
- 扁平化。
- 修改if else 最忌憚的是天馬行空,自負自己對程式碼的理解,直接重新改寫條件語句。但另一方面,相信各位看官也注意到了,理解又是必不可少的,完全死死的做邏輯變形是異常繁瑣的(這個在第二個例子中尤為明顯),具體如何操作,不好意思,這就是"修改程式碼的藝術"。口才不行,修行還靠個人。
- 不要做不成熟的優化。相對來說,程式碼的清晰度高於效能的優化,而且很多時候兩者並不是衝突的,當代碼更清新了,往往有更好的優化方案。
- 舉例中的一些程式碼風格,比如return快速返回,不是每個人都能接受。求同存異,這也是個人座右銘。
- 大千世界,簡化 if else的方法肯定不止上面幾種。但這幾種還是很實用,歡迎個人崇拜,不要懷疑者,不要腦殘粉。(玩笑,勿當真,只是想說,"不要怕,不要悔",剛開始時,儘管做,不要太多懷疑)
最後,如果對重構還有興趣,可以看一看《重構--我的遺留系統改進之路》,這是一個培訓ppt,寫得不錯。這裡推薦一下