編寫出規範,易讀,優雅的代碼能夠大大方便代碼的維護,推薦相關書籍——代碼整潔之道。
目錄
3.行數不易過多,50行左右,最多不過100行,一般超過100行,說明方法內部有代碼需要整合成另一個方法,當然,賦值超過100行不算
一、變量名
1.名字和變量的意義要一致;
2.一個變量,不能當成倆個變量來使用
場景:在一個方法內,程序員發現有一個字符串變量只有在最開始或者某一段中使用到時,爲了充分利用這個變量,不再重新聲明新變量,而是一直對該變量進行操作。
private String getTempString(String type)
{
if ("xxx".equals(type))
{
return "";
}
String temp = "xxxxx";
//下面全是對temp字符串進行操作,type已經沒有用了
return temp;
}
對於上面那種情況,可能少部分程序員發現type只有在最開始用到了,而之後從來沒有使用,那麼他可能會選擇不聲明temp變量,而使用type來操作,這個時候,雖然你減少了局部變量的個數,但是變量的意義在這個方法內確有不同的意義了,那麼對於後來維護代碼的人來說,這是很痛苦的,並且這個方法的意義就是獲取temp字符串,你返回一個type字符串,雖然可能最後的值相同,但是對於第三者來說,會覺得很矛盾。比如,上面的代碼寫成這樣:
private String getTempString(String type)
{
if ("xxx".equals(type))
{
return "";
}
type = "xxxxx";
//下面全是對temp字符串進行操作,type已經沒有用了
return type;
}
二、方法
1.只關注一件事,那就是這個方法名所賦予的事
2.參數個數要少,這樣耦合性就低,規範要求是少於5個
3.行數不易過多,50行左右,最多不過100行,一般超過100行,說明方法內部有代碼需要整合成另一個方法,當然,賦值超過100行不算
4.方法內位於同一抽象層級
舉個例子,如下:
private void deleteSomeThing(String user, String startTime, String endTime)
{
if (user.length() > 5)
{
user = user.substring(0, user.length() - 5);
}
Date startDate = simpleDateFormat.parse(startTime);
Date endDate = simpleDateFormat.parse(endTime);
Calendar startCalendar = Calendar.getInstance();
startCalendar.setTime(startDate);
/**
* xxxxxxx
* xxxxxxx
* xxxxxxx
* 一系列對user,startTime,endTime的操作,然後最後得到一個刪除條件
*/
String condition = "xxxxxx";
//最後通過mapper或者dao操作數據庫刪除數據
mapper.deleteSomeThingByCondition(condition);
}
像這種,直接在一個方法內,寫了太多的操作,如果邏輯複雜一點,行數就會飆升,代碼可讀性也變得很差;如果修改如下:
private String getUserCondition(String user)
{
if (user.length() > 5)
{
user = user.substring(0, user.length() - 5);
}
//xxxxxxxx
//xxxxxxxx
//xxxxxxxx
String userConditon = "xxxxx";
return userConditon;
}
private String getTimeCondition(String startTime, String endTime)
{
Date startDate = simpleDateFormat.parse(startTime);
Date endDate = simpleDateFormat.parse(endTime);
Calendar startCalendar = Calendar.getInstance();
startCalendar.setTime(startDate);
//xxxxxxxx
//xxxxxxxx
//xxxxxxxx
String timeCondition = "xxxxxx";
return timeCondition;
}
private String mergeCondition(String userCondition, String timeCondition)
{
String allCondition = "xxxxx";
return allCondition;
}
private String getConditions(String user, String startTime, String endTime)
{
String userCondition = getUserCondition(user);
String timeCondition = getTimeCondition(startTime, endTime);
String condition = mergeCondition(userCondition, timeCondition);
return condition;
}
private void deleteSomeThing(String user, String startTime, String endTime)
{
mapper.deleteSomeThingByCondition(getConditions(user, startTime, endTime));
}
其實,如果能夠實現,每個方法抽象層級相同,那麼方法的其他規範就很容易滿足,像上面這種修改,通過抽象層級的劃分,每個方法的行數一定會很少,參數也不會很多。雖然多出了很多方法,但是每個方法幹什麼都能一清二楚,並且可能不需要你閱讀方法內的代碼,你只需要看方法名就知道作用了。不過這個列子比較極端,拆分了很多方法,具體需要如何拆分,拆分多少個方法視情況而定,比如整個操作代碼行數都不過50行,那麼全部寫在一個方法內也可以。
那麼再回到抽象層級來講,以這個列子爲例,
第一層:deleteSomeThing(String user, String startTime, String endTime)
deleteSomeThing方法內部層級只有mapper層,和條件變量(可以把getConditions返回值返回給一個條件變量,然後mapper傳入這個變量),因爲當你要刪除某些數據的時候,最直觀的就是,調用mapper,刪除滿足條件的數據,至於,這個條件是什麼,怎麼獲取,這個層級是不關心的;
第二層:getConditions(String user, String startTime, String endTime)
這個層級只需要返回條件給上一層調用,不需要操作參數來合成條件(當然,如果邏輯簡單,也可以在這一次層級操作參數),所以他只關心條件本身,不關心條件如何操作。這個方法內部就只有各種已經處理好的條件變量。
第三層:
getUserCondition(String user)
getTimeCondition(String startTime, String endTime)
mergeCondition(String userCondition, String timeCondition)
這三層都是操作參數以返回目標條件格式,所以,這三層關心的就是對參數的操作。
三、實體類
至於數據庫交互,與數據庫表或者文檔中的字段一一對應,不多不少;在新增數據,更新數據時使用該類。
四、模型類
與前端交互,前端需要哪些屬性,模型類中就應該有哪些屬性。
其實大部分情況系,模型類和實體類的屬性字段相差不大,或者說可能一模一樣,那麼在這種情況下有必要分實體類和模型類嗎?答案是肯定的,之所以有這兩個層級,就是爲了將保存數據和前端交互分隔開。考慮一種情況,當前實體類和模型類字段一模一樣,那麼不久之後因爲業務的變更,模型類字段突然發生了大改變,但是保存的數據還是和之前一直,那麼,如果最開始不區分實體類和模型類,都用同一個類,這個時候這個類的定義就會模糊了,因爲這個類的字段是數據庫表中的字段和前端需要的字段的融合,而且因爲修改了這個類,可能會對於數據的保存和查詢都產生影響。但是如果一開始就區分了,那麼只需要修改模型類,對保存數據這部分是沒有任何影響的。
五、服務類
提供一組功能,完成某個模塊的所有功能,主要是對業務邏輯的處理
六、Controller類
與前端交互,只負責對前端數據的傳遞,接收和返回,不參與數據的處理、加工
七、mapper或者dao類
只與數據庫交互,儘量不參與數據的加工。