国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

常識之外的規范——阿里java開發手冊筆記(全章節)

Martin91 / 1541人閱讀

摘要:說明這篇文章是我第一次認真閱讀阿里巴巴開發手冊終極版的筆記。說明本手冊明確防止是調用者的責任。一年半載后,那么單元測試幾乎處于廢棄狀態。好的單元測試能夠最大限度地規避線上故障。

說明

這篇文章是我第一次(認真)閱讀《阿里巴巴 Java 開發手冊(終極版)》的筆記。手冊本身對規范的講解已經非常詳細了,如果你已經有一定的開發經驗并且有良好的編碼習慣和意識,會發現大部分規范是符合常識的。所以本文不會再去做重復的說明,只是對其中一些可能沒留意到的或者說不在(我的)常識之內的一些規范進行整理記錄。當然每家公司都有自己的一套規范標準,所以大家也沒必要過分追究。

其中或許會有遺漏或者理解錯誤,希望各位擔待提點。

重點我會用黑體標注。

引用部分為《阿里巴巴 Java 開發手冊(終極版)》原文

更新時間:2017-10-17

插件

ide插件已發布:《阿里巴巴Java開發手冊》IDEA插件與Eclipse插件使用指南

第一節 編程規約 1 命名規范

8.【強制】POJO 類中布爾類型的變量,都不要加 is,否則部分框架解析會引起序列化錯誤。

反例:定義為基本數據類型 Boolean isDeleted;的屬性,它的方法也是 isDeleted(),RPC框架在反向解析的時候,“以為”對應的屬性名稱是 deleted,導致屬性獲取不到,進而拋出異常。

16.【參考】各層命名規約:
A) Service/DAO 層方法命名規約
1) 獲取單個對象的方法用 get 做前綴。
2) 獲取多個對象的方法用 list 做前綴。(我習慣寫成 getXxxList)
3) 獲取統計值的方法用 count 做前綴。
4) 插入的方法用 save/insert 做前綴。
5) 刪除的方法用 remove/delete 做前綴。
6) 修改的方法用 update 做前綴。

2 常量定義

1.【強制】不允許任何魔法值(即未經定義的常量)直接出現在代碼中。
反例:
String key = "Id#taobao_" + tradeId;
cache.put(key, value);

魔法值:是指在代碼中直接出現的數值,而只有在這個數值記述的那部分代碼中才能明確了解其含義。
也就是我們常說的[硬編碼]或者[寫死],這類代碼需要定義常量來明確其含義。

3 代碼格式

5.【強制】采用 4 個空格縮進,禁止使用 tab 字符。
說明:如果使用 tab 縮進,必須設置 1 個 tab 為 4 個空格。IDEA 設置 tab 為 4 個空格時,請勿勾選 Use tab character;而在 eclipse 中,必須勾選 insert spaces for tabs。

有些同學可能會對這一條不以為然。如果是協調開發,兩個工程師的格式化規則不一致很可能A同學無意把B同學的代碼重新格式化并提交,導致后邊查看svn變更記錄時傻逼了。

7.【強制】單行字符數限制不超過 120 個,超出需要換行,換行時遵循如下原則:
1) 第二行相對第一行縮進 4 個空格,從第三行開始,不再繼續縮進,參考示例。
2) 運算符與下文一起換行。
3) 方法調用的點符號與下文一起換行。
4) 方法調用時,多個參數,需要換行時,在逗號后進行。
5) 在括號前不要換行,見反例。

120這個長度限制很有意思,如圖:

這個長度大概是15寸筆記本1080分辨率字體14號左右的最佳可視長度。當然應該也不一定非要這么精準吧。。

4 OOP 規約

7.【強制】所有的相同類型的包裝類對象之間值的比較,全部使用 equals 方法比較。
說明:對于 Integer var = ? 在-128 至 127 范圍內的賦值,Integer 對象是在IntegerCache.cache 產生,會復用已有對象,這個區間內的 Integer 值可以直接使用==進行判斷,但是這個區間之外的所有數據,都會在堆上產生,并不會復用已有對象,這是一個大坑,推薦使用 equals 方法進行判斷。

12.【強制】POJO 類必須寫 toString 方法。使用 IDE 的中工具:source> generate toString時,如果繼承了另一個 POJO 類,注意在前面加一下 super.toString。
說明:在方法執行拋出異常時,可以直接調用 POJO 的 toString()方法打印其屬性值,便于排查問題。

吐槽:"使用 IDE 的中工具" 碼字錯誤哦!

13.【推薦】使用索引訪問用 String 的 split 方法得到的數組時,需做最后一個分隔符后有無內容的檢查,否則會有拋 IndexOutOfBoundsException 的風險。
說明:
String str = "a,b,c,,";
String[] ary = str.split(",");
// 預期大于 3,結果是 3
System.out.println(ary.length);

最好的做法是對集合類型的變量本身進行判空校驗或者大小判斷,不要想當然。

5 集合處理

2.【強制】ArrayList的subList結果不可強轉成ArrayList,否則會拋出ClassCastException異常,即java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.
說明:subList 返回的是 ArrayList 的內部類 SubList,并不是 ArrayList ,而是ArrayList 的一個視圖,對于 SubList 子列表的所有操作最終會反映到原列表上。

5.【強制】使用工具類Arrays.asList()把數組轉換成集合時,不能使用其修改集合相關的方法,它的 add/remove/clear 方法會拋出 UnsupportedOperationException 異常。
說明:asList 的返回對象是一個 Arrays 內部類,并沒有實現集合的修改方法。Arrays.asList體現的是適配器模式,只是轉換接口,后臺的數據仍是數組。
String[] str = new String[] { "you", "wu" };
List list = Arrays.asList(str);
第一種情況:list.add("yangguanbao"); 運行時異常。
第二種情況:str[0] = "gujin"; 那么 list.get(0)也會隨之修改。

10.【推薦】使用 entrySet 遍歷 Map 類集合 KV,而不是 keySet 方式進行遍歷。
說明:keySet 其實是遍歷了 2 次,一次是轉為 Iterator 對象,另一次是從 hashMap 中取出key 所對應的 value。而 entrySet 只是遍歷了一次就把 key 和 value 都放到了 entry 中,效率更高。如果是 JDK8,使用 Map.foreach 方法。
正例:values()返回的是 V 值集合,是一個 list 集合對象;keySet()返回的是 K 值集合,是一個 Set 集合對象;entrySet()返回的是 K-V 值組合集合。

java8 是個好東西~

6 并發處理

5.【強制】SimpleDateFormat 是線程不安全的類,一般不要定義為 static 變量,如果定義為static,必須加鎖,或者使用 DateUtils 工具類。
正例:注意線程安全,使用 DateUtils。亦推薦如下處理:
private static final ThreadLocal df = new ThreadLocal() {
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
說明:如果是 JDK8 的應用,可以使用 Instant 代替 Date,LocalDateTime 代替 Calendar,DateTimeFormatter 代替 SimpleDateFormat,官方給出的解釋:simple beautiful strong immutable thread-safe。

再說一遍,java8 是個好東西!LocalDateTime相關API
附贈一個java.util.Date和LocalDateTime互轉的例子:

   private static Date localDateTimeToUDate(LocalDateTime localDateTime) {
       ZoneId zone = ZoneId.systemDefault();
       Instant instant = localDateTime.atZone(zone).toInstant();
       return Date.from(instant);
   }

   private static LocalDateTime uDateToLocalDate(Date date) {
       Instant instant = date.toInstant();
       ZoneId zone = ZoneId.systemDefault();
       LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
       return localDateTime;
   }

14.【參考】 HashMap 在容量不夠進行 resize 時由于高并發可能出現死鏈,導致 CPU 飆升,在開發過程中可以使用其它數據結構或加鎖來規避此風險。

7 控制語句

3.【推薦】表達異常的分支時,少用 if-else 方式,這種方式可以改寫成:
if (condition) {
...
return obj;
}
// 接著寫 else 的業務邏輯代碼;
說明:如果非得使用 if()...else if()...else...方式表達邏輯,【強制】避免后續代碼維護困難,請勿超過 3 層。
正例:超過 3 層的 if-else 的邏輯判斷代碼可以使用衛語句、策略模式、狀態模式等來實現...

我們公司codeReview時經常看到有些同學的代碼是if(){}else if(){} else if(){}else{} 除了看上去low更主要的原因是過多的大括號層級不便于閱讀很容易搞混,尤其是跳出代碼塊的時候,連續幾個}}}基本就不知道跳到哪了徹底懵逼,還得折疊代碼或者滾上去重新回憶一下。

6.【推薦】接口入參保護,這種場景常見的是用于做批量操作的接口。

解釋一下,接口入參保護就是對入參進行校驗,包括允許的最大值或者其他范圍或邊界。防止請求大量數據導致接口“爆炸”。比如限制返回數據最大條數,超過限制直接return或者拋異常。

8 注釋規約

感覺沒啥好說的。。

9 其它

1.【強制】在使用正則表達式時,利用好其預編譯功能,可以有效加快正則匹配速度。
說明:不要在方法體內定義:Pattern pattern = Pattern.compile(規則);

就是說定義成全局變量。

第二節 異常日志 1 異常處理

3.【強制】對大段代碼進行try-catch,這是不負責任的表現。catch時請分清穩定代碼和非穩定代碼,穩定代碼指的是無論如何不會出錯的代碼。對于非穩定代碼的catch盡可能進行區分異常類型,再做對應的異常處理。

9.【推薦】方法的返回值可以為null,不強制返回空集合,或者空對象等,必須添加注釋充分說明什么情況下會返回null值。調用方需要進行null判斷防止NPE問題。說明:本手冊明確防止NPE是調用者的責任。即使被調用方法返回空集合或者空對象,對調用者來說,也并非高枕無憂,必須考慮到遠程調用失敗、序列化失敗、運行時異常等場景返回null的情況。

需要說明的是是否可以返回null是需要根據接口約定來判斷的,如果明確的返回對象的結構類型,一定要返回這個對象,但他的屬性值可以是null,比如page對象:{data:null,pageNum:0,count:0}

2 日志規約

4.【強制】對trace/debug/info級別的日志輸出,必須使用條件輸出形式或者使用占位符的方式。
說明:logger.debug("Processingtradewithid: " + id+ "andsymbol: " + symbol);如果日志級別是warn,上述日志不會打印,但是會執行字符串拼接操作,如果symbol是對象,會執行toString()方法,浪費了系統資源,執行了上述操作,最終日志卻沒有打印。
正例:(條件)if (logger.isDebugEnabled()) { logger.debug("Processing trade with id: " + id + " and symbol: " + symbol); }
正例:(占位符)logger.debug("Processing trade with id: {} and symbol : {} ", id, symbol);

第三節 單元測試

4.【強制】單元測試是可以重復執行的,不能受到外界環境的影響。
說明:單元測試通常會被放到持續集成中,每次有代碼check in時單元測試都會被執行。如果單測對外部環境(網絡、服務、中間件等)有依賴,容易導致持續集成機制的不可用。
正例:為了不受外界環境影響,要求設計代碼時就把SUT的依賴改成注入,在測試時用spring這樣的DI框架注入一個本地(內存)實現或者Mock實現。

15.【參考】為了更方便地進行單元測試,業務代碼應避免以下情況:
構造方法中做的事情過多。?存在過多的全局變量和靜態方法。
存在過多的外部依賴。
存在過多的條件語句。說明:多層條件語句建議使用衛語句、策略模式、狀態模式等方式重構。

和第一節if-else提到的一樣,避免多層代碼塊嵌套

16.【參考】不要對單元測試存在如下誤解:
那是測試同學干的事情。本文是開發手冊,凡是本文內容都是與開發同學強相關的。
單元測試代碼是多余的。汽車的整體功能與各單元部件的測試正常與否是強相關的。
單元測試代碼不需要維護。一年半載后,那么單元測試幾乎處于廢棄狀態。
單元測試與線上故障沒有辯證關系。好的單元測試能夠最大限度地規避線上故障。

測試開發相親相愛是一家~

第四節 安全規約

4.【強制】用戶請求傳入的任何參數必須做有效性驗證
說明:忽略參數校驗可能導致:
pagesize過大導致內存溢出
惡意orderby導致數據庫慢查詢
任意重定向?SQL注入
反序列化注入
正則輸入源串拒絕服務ReDoS
說明:Java代碼用正則來驗證客戶端的輸入,有些正則寫法驗證普通用戶輸入沒有問題,但是如果攻擊人員使用的是特殊構造的字符串來驗證,有可能導致死循環的結果。

老生常談的問題,但在工作中有時會忽略。

第五節 MySQL數據庫 1. 建表規約

8.【強制】varchar是可變長字符串,不預先分配存儲空間,長度不要超過5000,如果存儲長度大于此值,定義字段類型為text,獨立出來一張表,用主鍵來對應,避免影響其它字段索引效率。

大字段建外連表,避免影響索引效率。難點在于如何說服主工程師(滑稽)。

13.【推薦】字段允許適當冗余,以提高查詢性能,但必須考慮數據一致。
冗余字段應遵循:
1)不是頻繁修改的字段。
2)不是varchar超長字段,更不能是text字段。
正例:商品類目名稱使用頻率高,字段長度短,名稱基本一成不變,可在相關聯的表中冗余存儲類目名稱,避免關聯查詢。

講一個笑話。公司老王出差去拉項目,對方博士生問“這個數據庫設計為什么不符合三范式?”
真事。

14.【推薦】單表行數超過500萬行或者單表容量超過2GB,才推薦進行分庫分表。
說明:如果預計三年后的數據量根本達不到這個級別,請不要在創建表時就分庫分表。

2. 索引規約

3.【強制】在varchar字段上建立索引時,必須指定索引長度,沒必要對全字段建立索引,根據實際文本區分度決定索引長度即可。
說明:索引的長度與區分度是一對矛盾體,一般對字符串類型數據,長度為20的索引,區分度會高達90%以上,可以使用count(distinctleft(列名, 索引長度))/count(*)的區分度來確定。

5.【推薦】如果有orderby的場景,請注意利用索引的有序性。orderby最后的字段是組合索引的一部分,并且放在索引組合順序的最后,避免出現file_sort的情況,影響查詢性能。
正例:wherea=? andb=? orderbyc;索引:a_b_c
反例:索引中有范圍查找,那么索引有序性無法利用,如:WHEREa>10 ORDERBYb;索引a_b無法排序。

6.【推薦】利用覆蓋索引來進行查詢操作,避免回表。
說明:如果一本書需要知道第11章是什么標題,會翻開第11章對應的那一頁嗎?目錄瀏覽一下就好,這個目錄就是起到覆蓋索引的作用。
正例:能夠建立索引的種類:主鍵索引、唯一索引、普通索引,而覆蓋索引是一種查詢的一種效果,用explain的結果,extra列會出現:usingindex。

3. SQL語句

1.【強制】不要使用count(列名)或count(常量)來替代count(*),count(*)是SQL92定義的標準統計行數的語法,跟數據庫無關,跟NULL和非NULL無關。
說明:count(*)會統計值為NULL的行,而count(列名)不會統計此列為NULL值的行。

乖乖滾回count(*)

【推薦】in操作能避免則避免,若實在避免不了,需要仔細評估in后邊的集合元素數量,控制在1000個之內。

4. ORM映射

3.【強制】不要用resultClass當返回參數,即使所有類屬性名與數據庫字段一一對應,也需要定義;反過來,每一個表也必然有一個與之對應。
說明:配置映射關系,使字段與DO類解耦,方便維護。

編程一時爽,維護兩行淚~

5.【強制】iBATIS自帶的queryForList(StringstatementName,intstart,intsize)不推薦使用。
說明:其實現方式是在數據庫取到statementName對應的SQL語句的所有記錄,再通過subList取start,size的子集合
正例:
Map map = new HashMap();
map.put("start", start);
map.put("size", size);

沒想到你是這樣的iBATIS!

第六節 工程結構 1. 應用分層

2.【參考】(分層異常處理規約)在DAO層,產生的異常類型有很多,無法用細粒度的異常進行catch,使用catch(Exceptione)方式,并thrownewDAOException(e),不需要打印日志,因為日志在Manager/Service層一定需要捕獲并打到日志文件中去,如果同臺服務器再打日志,浪費性能和存儲。在Service層出現異常時,必須記錄出錯日志到磁盤,盡可能帶上參數信息,相當于保護案發現場。如果Manager層與Service同機部署,日志方式與DAO層處理一致,如果是多帶帶部署,則采用與Service一致的處理方式。Web層絕不應該繼續往上拋異常,因為已經處于頂層,如果意識到這個異常將導致頁面無法正常渲染,那么就應該直接跳轉到友好錯誤頁面,加上用戶容易理解的錯誤提示信息。開放接口層要將異常處理成錯誤碼和錯誤信息方式返回。

2. 二方庫依賴

10.【參考】為避免應用二方庫的依賴沖突問題,二方庫發布者應當遵循以下原則:
1)精簡可控原則。移除一切不必要的API和依賴,只包含ServiceAPI、必要的領域模型對象、Utils類、常量、枚舉等。如果依賴其它二方庫,盡量是provided引入,讓二方庫使用者去依賴具體版本號;無log具體實現,只依賴日志框架。
2)穩定可追溯原則。每個版本的變化應該被記錄,二方庫由誰維護,源碼在哪里,都需要能方便查到。除非用戶主動升級版本,否則公共二方庫的行為不應該發生變化。

3. 服務器

4.【推薦】在線上生產環境,JVM的Xms和Xmx設置一樣大小的內存容量,避免在GC后調整堆大小帶來的壓力。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/67777.html

相關文章

  • 后端技術 - 收藏集 - 掘金

    摘要:理解迭代對象迭代器生成器后端掘金本文源自作者的一篇博文,原文是,俺寫的這篇文章是按照自己的理解做的參考翻譯。比較的是兩個對象的內容是后端掘金黑魔法之協程異步后端掘金本文為作者原創,轉載請先與作者聯系。 完全理解關鍵字with與上下文管理器 - 掘金如果你有閱讀源碼的習慣,可能會看到一些優秀的代碼經常出現帶有 with 關鍵字的語句,它通常用在什么場景呢?今天就來說說 with 和 上下...

    oujie 評論0 收藏0
  • 《大型網站系統與Java中間件》讀書筆記(上)

    摘要:另一個用戶請求過來,負載均衡器指派這個請求到服務器。這樣就平攤了請求這種方式就叫做輪詢策略還有很多種,就看你想怎么實現了,反正這個邏輯的代碼放在負載均衡器上。 前言 只有光頭才能變強。文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/ZhongFuCheng3y/3y 這本書買了一段時間了,之前在杭州沒帶過去,現在讀完第三章,來做做筆記 showI...

    baukh789 評論0 收藏0
  • Java - 收藏集 - 掘金

    摘要:強大的表單驗證前端掘金支持非常強大的內置表單驗證,以及。面向對象和面向過程的區別的種設計模式全解析后端掘金一設計模式的分類總體來說設計模式分為三大類創建型模式,共五種工廠方法模式抽象工廠模式單例模式建造者模式原型模式。 強大的 Angular 表單驗證 - 前端 - 掘金Angular 支持非常強大的內置表單驗證,maxlength、minlength、required 以及 patt...

    XiNGRZ 評論0 收藏0
  • 如何成為一位「不那么差」程序員

    摘要:能理解線程模型多線程優缺點以及如何避免。多線程的出現主要是為了提高的利用率任務的執行效率。所以要考慮清楚是否真的需要多線程。這一塊的內容可以然我們知道寫大牛處理并發的思路,對我們自己編寫高質量的多線程程序也有很多幫助。 showImg(https://segmentfault.com/img/remote/1460000015980196?w=2048&h=1363); 前言 已經記不...

    caspar 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<