在一定前提下,代碼要以容易理解的方式實現。這個課題包括的內容太廣,此文僅就近段時間讀的一段簡單程式為例說明一下似乎與“單入口單出口”原則相關的內容。而談及這個原則,也可以從不同角度和不同代碼形式來談,此文僅就下面代碼模型中的形式而談。下面代碼的背景是有三種unit,每種unit有相同種類的多個documentType;代碼實現的是擷取每種unit下每種documentType數量。代碼如下所示:
import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map; public class DocsGroup{ List<HashMap>docList = new ArrayList<HashMap>(); HashMap<String, Object>map = null; public Map<String,List> find(List<String> DocTyps) throws Exception { //遍曆所有文檔,擷取相關資訊 for ( String fileType :DocTyps){ searchAndMapData(fileType); } //設定傳回值 Map<String,List> res = new HashMap<String, List>(); res.put("docList", docList); return res; } /** * 擷取指定文檔相關資訊 */ private void searchAndMapData(String documentType){ //擷取1單元資訊 this.searchAndMapDataSupport( documentType, "1"); //擷取3單元資訊 this.searchAndMapDataSupport( documentType, "3"); //擷取5單元資訊 this.searchAndMapDataSupport( documentType, "5"); } private void searchAndMapDataSupport(String documentType,String unit){ int count = this.fetchCount(documentType, unitValue); if(count>0){ map = new HashMap<String, Object>(); map.put("documentType", documentType); map.put("unit", unit); map.put("Count", count); docList.add(map); } }}
上面的程式有很多值得肯定的地方,如它的模組化程度已經很高,後面兩個私人方法為前面的find方法做服務,如果將後兩個方法內容去不合并到find方法中,那find的複雜程度將大大提高,而維護難度也加大很多(要清楚,這個代碼模型中的每個方法中實際上會包含很多邏輯關係的)。如果可以把GOF設計模式,那find和searchAndMapData就相當於是一種面板模式——一種特殊的面板模式——其特殊不僅是體現在方法上提設計模式,也體現在searchAndMapData方法中的隱含性,例如所調用的方法是相同而簡單,實際上可能是不同而複雜的。
在編碼開始之前一定要好好分析要出來的業務,對業務進行建模分析,認真考慮資料結構。編寫程式指做三件事情——輸入、處理和輸出——而這些無不與資料結構有關,此外對業務的分析最終在代碼上體現的也是一個使用者輸入和展示資訊。
按照上面的說法,分析上述代碼返回結果的資料結構,是map裡有一個list,將每種documentType作為一個map存放到此List中,在結合上述業務情境,則會發現業務上有多少種documentType,List中就會有三倍於這個數位map。如果我們換個角度想一下,將每種Unit做為一個map,在要返回的資訊可以作為DTO放到map中進行返回。當然,我們還可探究此處的資料結構有沒有必要這麼複雜,但此文不討論哪種資料結構更好,只是闡述一下在coding前要對業務分析,對資料結構進行設計。
深入到代碼細節我們會發現,在類內定義了兩個公開變數,主要用於接收要返回的資訊。正是這種定義方式加上一種非常規的輸入輸出的操作導致讀這段很簡短的代碼有些吃力。首先在在find方法中不能很明確的告訴我們傳回值從何處擷取的。原因是,雖然我們調用了一個擷取傳回值得處理過程searchAndMapData,但它的職責卻絕非是一般意義上的過程,對比函數我們會清楚這個過程其實擔當著函數的角色卻披著件過程的皮(當然過程在多傳回值的處理中等是可以發揮相當作用的,但應該考慮更容易讓人理解的方式,此話題是另一個維度問題,在此不做延展)。另外,還要注意到這兩個變數是根本沒必要作為公開變數的。姑且將這類問題廣義的歸結到“單入口,單出口”原則上,不能說這種原則完全正確或有必要,但它也確實為代碼的清晰和品質做著貢獻。正如百科所言,它是為了保證開發程式的品質,要求過程中的資料流控制是必須在固定的程式段入口進入,固定的出口返回,不允許在編程中隨意使用資料。產生這類問題很多原因在於沒有對內部邏輯進行真正的規劃設計,僅僅是在coding……
上述代碼雖看似像是單入口單出口不明確引起的代碼不清晰,但其實質及其可挖掘的地方卻遠不止於此。說複雜了這涉及的是業務分析,設計分析和資料模型分析,說簡單了其實就是要認真對待“輸入、處理、輸出”三要素,而這三要素所涉及的不僅僅是代碼的清晰與否問題,更關係到其品質,關係到其韌性,乃至整個業務的完整性!