▄︻┻┳═一Agenda:html
▄︻┻┳═一(1/8)[代碼整潔之道]你真的會用枚舉嗎?非也!java
▄︻┻┳═一(2/8)枚舉的錯誤用法 之 方法參數程序員
▄︻┻┳═一(3/8)枚舉的錯誤用法 之 方法參數(二)spring
▄︻┻┳═一(4/8)枚舉的錯誤用法 之 方法返回值數據庫
▄︻┻┳═一(5/8)枚舉的錯誤用法 之 方法體內部ide
▄︻┻┳═一(6/8)枚舉的錯誤用法 之 分支判斷post
▄︻┻┳═一(7/8)藉助枚舉說一下數據類型定義規範this
▄︻┻┳═一(8/8)RPC接口能用枚舉就請考慮枚舉編碼
§1 url
《代碼整潔之道》裏提到」用異常代替返回錯誤碼「。若是缺少代碼維護經驗,估計一時理解不了其中含義。寫代碼是一回事,維護代碼是一回事。
用異常代替返回錯誤碼是對代碼「職責」的運用,即分離業務邏輯代碼和錯誤處理代碼。同時,用拋出異常的方式代替返回錯誤碼並未改變方法的返回值,對方法沒有產生任何破壞。
§2
我在小組的開發規範裏指明一條「嚴禁不加思考的代碼copy。當代碼copy超過10行,你必定要思考,是否是該重構了?」
也許有些同窗並不知道DRY原則,也不清楚「小規模複用」。 So,Just do it!照作便可,往後也許會懂。
若是變量值僅在一個範圍內變化,且帶有名稱以外的延伸屬性,則定義爲枚舉類。(《阿里巴巴Java開發手冊》中也有說起)
毋庸置疑,枚舉提升了代碼的可讀性和可維護性。
我給前面這句話加個定語——「正確使用」。就是說,正確使用枚舉能夠提升代碼的可讀性和可維護性。
若是使用不當,可能達不到效果,甚至拔苗助長。
若是把某域定義成了枚舉,那麼,正確使用枚舉要注意以下幾點:
說明一下,上面兩點提到的「外」指的是當前應用系統的外部,如db、其餘交易系統、http接口調用。
要作到上面兩點,容易,也不容易。 我見到不少的程序,都沒有正確使用枚舉。因此再也不一遍一遍重複講了,看這篇博客吧。下面以一例來闡釋。
簡單寫一個demo,目錄結構以下圖:
§1 各package的職責:common是通用的,這裏只定義了一個枚舉類CurrencyEnum;bo是程序裏用到的業務數據對象;po即持久化對象,對應數據庫裏的數據表;service是業務處理服務類。(參考PO/POJO/BO/DTO/VO的區別)
§2 各class文件說明:
CurrencyEnum把「貨幣類型」這個域定義爲枚舉。
PayPO是持久化對象,數據類型只能用基本類型。咱們通常就是在讀寫庫時用它。其中,currency字段存儲的值是枚舉裏定義的CNY、USD、GBP、JPY、HKD。
PayBO是程序裏各class方法傳輸的對象。那麼它就不一樣於PayPO了。它頻繁穿梭在程序裏,因此咱們要能很容易就能識別出來它是最好的了(可讀性),這裏,就用到了上面定義的枚舉類型。
RouteService是模擬的一個獲取路由的服務類,爲了說的更明白,這裏使用方法重載定義了兩個方法,一個方法的參數是枚舉,一個方法的參數是bo。
用法見MainService。模擬了一個從db獲取對象,而後轉換成枚舉或bo獲取路由的過程。
§3 代碼:
CurrencyEnum:
package enumdemo.common; /** * 貨幣類型枚舉 */ public enum CurrencyEnum { CNY("CNY", "人民幣"), USD("USD", "美圓"), GBP("GBP", "英鎊"), JPY("JPY", "日元"), HKD("HKD", "港元"); //alphabet private final String alphabetCode; private final String name; CurrencyEnum(String alphabetCode, String name) { this.alphabetCode = alphabetCode; this.name = name; } public String getAlphabetCode() { return alphabetCode; } public String getName() { return name; } /** * 經過英文字母編碼獲取對應的貨幣類型</br> * * @param alphabetCode 英文字母貨幣 * @return */ public static CurrencyEnum getByAlphabetCode(String alphabetCode) { if (null == alphabetCode) { return null; } for (CurrencyEnum currencyEnum : values()) { if (currencyEnum.getAlphabetCode().equals(alphabetCode)) { return currencyEnum; } } return null; } }
PayPO:
package enumdemo.po; import java.math.BigDecimal; public class PayPO { String orderNo; BigDecimal money; String currency; // getter/setter(略) }
PayBO:
package enumdemo.bo; import enumdemo.common.CurrencyEnum; import java.math.BigDecimal; public class PayBO { String orderNo; BigDecimal money; CurrencyEnum currency; // getter/setter(略) }
RouteService:
package enumdemo.service; import enumdemo.common.CurrencyEnum; import enumdemo.bo.PayBO; import enumdemo.bo.RouteBO; public class RouteService { public RouteBO getRoute(CurrencyEnum currency) { switch (currency) { case CNY: RouteBO routeBO1 = new RouteBO(); //邏輯代碼略 return routeBO1; default: RouteBO routeBO2 = new RouteBO(); //邏輯代碼略 return routeBO2; } } public RouteBO getRoute(PayBO payBO) { RouteBO routeBO = new RouteBO(); if (CurrencyEnum.CNY == payBO.getCurrency()) { //邏輯代碼略 return routeBO; } else { //邏輯代碼略 return routeBO; } } }
MainService:
package enumdemo.service; import enumdemo.common.CurrencyEnum; import enumdemo.bo.PayBO; import enumdemo.po.PayPO; import enumdemo.bo.RouteBO; import org.springframework.beans.factory.annotation.Autowired; public class MainService { @Autowired RouteService routService; public void process() { final PayPO payRecord = null;//TODO:僞代碼,這裏是讀庫獲得的 String alphabetCode = payRecord.getCurrency(); CurrencyEnum currencyEnum = CurrencyEnum.getByAlphabetCode(alphabetCode); // ** 直接傳枚舉類型 RouteBO routeBO = routService.getRoute(currencyEnum); PayBO payBO = new PayBO(); payBO.setMoney(payRecord.getMoney()); payBO.setCurrency(currencyEnum); // ** 傳bo RouteBO routeBO1 = routService.getRoute(payBO); } }
上面示例裏PayBO的枚舉類型屬性 和 RouteService方法的枚舉類型參數或bo參數,使得枚舉的使用和判斷變得一目瞭然! 若是這裏把貨幣類型currency變量定義成String,那麼,你能夠比較與定義成CurrencyEnum的不一樣。一樣,PayBO裏的currency也如是。
有同窗該反問,這有什麼呀!你們記住貨幣類型有CNY、USD、GBP、JPY、HKD那幾個值不就好了。 那麼問題來了,咱們作的一個項目,可不是這個demo這麼簡單喲~,會有好多好多這樣的域,如訂單狀態,支付方式,產品類型,用戶類型,營銷方式。。。。。。,這些域的各個項的code多是0、一、二、三、四、五、六、七、8等這樣的數字(程序員對這些code的定義每每比較隨意,即便不隨意,受限於英語水平或拼音水平,定義出來的也每每不容易記憶),服務邏輯也遠比這個demo要複雜。你若是能記得住,舅服你。不過,你記得住,並不表明全部人都記得住。要知道,你不是一我的在做戰,你的項目也不是孤立的。