這裏作爲(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(wfwList!=null&&wfwList.size()>0){ 超級的頭重腳輕,採用return 直接返回
其次,for(int i=0;i<wfwList.size();i++){ TWorkFlowwork wfw=wfwList.get(i); 可以利用java的語法甜頭,或者說是慣用法,替換爲for (TWorkFlowwork wfw : wfwList)
然後,if (wfw!=null) 又可以用衛語句處理,不過這裏不能使用return直接返回,而是應該用continue
最後,後面if status的判斷實際都可以合併起來
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,寫得不錯。這裏推薦一下