讀阿里巴巴Java開發手冊v1.2.0之編程規約有感【架構篇】


    不為過去蹉跎,改變當下。

  為什么開篇就送這么一句話給大家,我相信很多處於1-3年碼齡的哥們兒們,在平時的編碼歷程中編碼的個性可能是多彩的,每個人都有每個人特定的風格,但是我們現在這么隨意寫,以后這么隨意寫,好沒問題,但是等你離開這個公司了或者是去開發別的項目了,再等別人過來接手維護你一手寫出來的這段個性十足的代碼時,那么你的右眼皮時不時地就會跳,因果我就不說了~~

  所以我建議看到這篇博文的朋友們,或許你稍微改變一下你的編碼風格,遵從一套好的編碼規約對己對人都是有好處的。可能朋友的公司也有專門的編碼規約,但是逃不了我們平時在開發一些屬於自己的項目,比如有一天從李智慧老師的《大型網站技術架構:核心原理與案例分析》著作中學到一些非常好的東西,那么我們就想開始動手編碼來實現一下,這時候如果盡量遵從一套很好的編碼規約風格,將寫出來的代碼分享給身邊的同事學習一下,提提建議多好。

  2017-05-20這一天,阿里巴巴集團技術團隊終於發布了版本號:1.2.0的Java開發手冊,在這之前他們總共發布過5個版本,都有幸被我看到了。當時在地鐵上一貫地翻開手機,直接打開《阿里技術》微信公眾號,就一眼瞅到了"搶鮮下載|阿里Java開發手冊最新完美版,千錘百煉始出爐——阿里巴巴Java開發手冊v1.2.0",當時第一反應就是趕緊先拿到它,接着迅速找到下載入口,完美地保存在手機上了。

  快速飄過前言,手冊的願景就是碼出高效,碼出質量。所謂無規矩不成方圓,無規范不能協作。質量的提升是告訴我們盡可能少踩坑,少吃那些無用的虧,高效協作即降低協同成本,提升溝通效率,再說現在的軟件架構都需要多個程序員協同開發完成,公司也不可能讓某個技術大牛獨自去完成,所以讓大家統一方式一起做事,才能提升開發效率。

  手冊結構總共由5部分組成:編程規約、異常日志、MySQL數據庫、工程結構和安全規約。

  一:編程規約

  首先來說說編程規約吧,這部分是我個人極力推薦各位朋友能夠借鑒,一個程序員有一個好的編碼風格,真的是異於其他碼農。我們誰都想要一個好聽的名字,除了好聽這個名字它還要有特殊的意義。在編碼的過程中我們定義一個變量也是一樣的,假如你定義的變量很爛,被人看到不僅會鄙視你,還會從心里認為你沒文化,就算我們英文不好,但是也可以百度啊,讓人看到一眼就能見名知意,多和諧啊~~

  1、命名風格

  見名知意;類名、方法名、參數名、成員變量和局部變量使用駝峰式(但是這里強調一下,我們項目中難免會有很多分層領域的模型類,比如DO/BO/DTO/VO/AO,這些可以使用UserDO、QueryVO等形式);常量名大寫;抽象類命名以Abstract或Base開頭;異常類命名使用Exception結尾;測試類以Test結尾;包名統一使用小寫;接口中的方法和屬性盡量不要加任何修飾符(如果可以public也不要加),為了代碼簡潔;任何pojo類中布爾類型的變量,不要使用is做前綴,否則部分框架解析會引起序列化錯誤。

  我們現在軟件項目大部分都是分層的,對各個層中的方法和模型類地命名也有一定的講究,Service/DAO層中各方法的命名:獲取單個對象的方法采用get做前綴;獲取多個對象的方法采用list做前綴;獲取統計值的方法采用count做前綴;插入的方法采用save或insert做前綴,但是推薦使用save;刪除的方法采用remove或delete做前綴,但是推薦使用remove;修改的方法采用update做前綴。Service/DAO層中各模型類的命名:數據對象采用XXXDO,一般和數據庫中的表名對應;數據傳輸對象采用XXXDTO,一般是與業務領域相關的傳輸對象;視圖層展示對象采用XXXVO,一般用於傳遞到視圖層。

  2、代碼格式:

  (1)、if語句的使用方面,小括號內的倆端不要出現空格並且if關鍵字后面添加一個空格(不光是if關鍵字,在if/for/switch/while/do關鍵字后面都要有空格);

  (2)、在二目、三目運算符的左右都建議添加一個空格,比如=、==、&&、+-/*等運算符左右都應該添加空格;

  (3)、在代碼縮進方面,盡量不要使用tab鍵,建議使用4個空格縮進,如果單行代碼超過120個字符,則建議換行;

  (4)、多個參數同時傳遞時,逗號前建議有個空格;

  3、OOP規約:

  訪問此類的靜態變量或靜態方法時,直接使用類名訪問,無須通過對象引用訪問此類的靜態資源,如果你使用對象引用訪問則無謂增加編譯器解析成本;所有的覆蓋方法必須添加@Override注解;在使用object類的equals方法時,盡量使用確定的值來調用equals方法,避免出現空指針異常(參考下圖代碼);所有的pojo類的屬性必須使用包裝類;定義任何pojo類的屬性時,不要設定任何屬性的默認值;構造方法中進制加入任何業務邏輯代碼;建議所有的pojo類都添加toString()方法,方便排查問題。

  4、並發處理:

  獲取單例對象需要保證線程安全,其中的方法也要保證線程安全;線程資源需要通過線程池獲取,不建議顯式創建線程;對多個資源、數據庫表、對象同時加鎖時,需要保持一致的加鎖順序,否則可能會造成死鎖。

  5、注釋規約

  首先所有的類都應該添加創建者和創建日期;方法內部添加注釋時,盡量采用單行注釋,注釋添加在被注釋的代碼上方,如果強制使用多行/**/注釋,則應該與代碼對齊;所有的抽象方法和接口中的方法,都必須在方法上面采用多行注釋/***/解析清楚該方法是用來干什么的,實現了什么功能;如果某個方法的功能還未完善,則必須添加待辦事宜TODO注釋。

  

  二:異常日志

  對於異常日志這部分,我們絕對不能忽視,你不敢保證你寫出的代碼永遠不會掛吧,那么我們就必須借助日志的力量來快速定位到問題的位置,以便解決。

   1、異常處理:

  對大段代碼進行try-catch,這是不負責任的表現,我們應該精確處理,建議盡量將try塊的代碼放到事務代碼中,一旦代碼拋出異常,則必須回滾事務,一定要注意手動回滾事務;如果代碼中使用到流等資源finally塊必須對它們進行關閉,必須做,而且在關閉的時候如果可能出現異常則必須進行try-catch處理;不能在finally塊中使用return語句。

  2、日志規約:

  我們平時的開發過程中,避免不了定時查看日志,分析日志,建議日志文件中的內容必須保存在15天以上,因為有些異常具備以“周”為頻次發生的特點;推薦對日志進行分類,將系統運行產生的錯誤日志和系統運行產生的業務日志分開存儲,方便開發人員查看;謹慎的記錄日志,生產環境禁止輸出debug日志,有選擇性的輸出info日志,一定要注意日志輸出量的問題,避免把硬盤撐爆。

  三:MySQL數據庫

  作為一名Java開發程序員,樣樣都得會點兒,不僅得辛苦的敲代碼,而且還要具備大局觀有時候還需要你來設計庫結構和表關系,但是這時候我們盡量不要隨意來搞,說不好聽了你一旦隨意起來,那么有一天你會前功盡棄地,因為我們的程序大多都是依托數據來運行的,所以,朋友們如果真要你遇上設計庫表時,請認真對待。

  (1)、建表規約

   首先在命名上,如果某個表的字段代表是與否的概念,則應該用is_XXX的方式開頭,數據類型應該是unsigned tinyint(1表示是、0表示否);表名和字段名應該使用小寫或數字,但是不能以數字開頭,切記數據庫中的字段名修改起來代價可是非常大的,因為無法進行預發布,所以在建表時命名字段名稱時一定要慎之又慎;表名不適用負數名詞,我們在開發中習慣將表名定義成負數名詞,代表多個記錄的統稱,這樣是不建議的;如果某個字段的數據類型為小數時,建議定義成decimal,不建議使用float或double,因為float或double有可能存在精度丟失,在進行的值的比較時會得到錯誤的結果,如果存儲的數據超過decimal數據類型的存儲范圍時,建議將整數和小數分開存儲;如果存儲的字符串長度幾乎相等,則建議使用定長char;創建一張表,必備的三個字段:id(主鍵)、gmt_create(創建時間)、gmt_modified(修改時間);表的命名一般建議是加上業務名稱來作為表前綴;表中的字段允許存在冗余,以便提高查詢效率,但是不能是varchar超長長度,更不能是text數據類型;單表行數超過500萬行或大小超過2GB時,才建議分庫分表。

  (2)、索引規約

  業務上具有唯一特性的字段,或者是多個字段的組合,也必須建成唯一索引;在查詢時超過3張表禁止使用join,需要join的字段,數據類型必須一致,多表關聯查詢時,保證被關聯的字段需要有索引;頁面搜索禁止走左模糊或者全模糊,如果需要應該搜索引擎來解決;如果有order by的場景,請注意利用索引的有序性,order by最后的字段是組合索引的一部分,並且放在索引組合順序的最后,避免出現file_sort的情況,影響查詢效率;SQL性能優化的目標:至少達到range級別(對索引進行范圍檢索)、要求是ref級別(指的是使用普通的索引)、如果可以的達到consts(單表中只有一個行匹配,即主鍵或唯一索引,在優化階段即可讀取到數據)最好;防止因字段類型不同導致的隱式轉換,導致索引失效。

  (3)、SQL語句:

  我們在書寫sql語句時大多數人都存在一個習慣,就是用count(列名)或count(常量)來代替count(*),count(*)是SQL92定義的標准的統計行數的語法,跟數據庫無關,跟NULL和非NULL有關,請記住這句話:count(*)會統計值為NULL的記錄,但是count(列名)是不會統計NULL的記錄,導致數據讀取錯誤;在代碼中寫分頁查詢邏輯時,若總計錄數為0時,應該直接返回,避免執行后面的分頁語句;禁止使用存儲過程,因為存儲難以調試和擴展,更沒有移植性;我們在進行刪除或修改記錄時,要學會先select一下,接着再做delete或update也不遲,以免眼疾手快造成毀滅性的災難;在使用in關鍵字是能避免則盡量避免,如果避免不了,應該仔細評估in后面的集合元素數量,盡量控制在1000以內,以免影響查詢效率。

  (4)、ORM映射:

  在mapper文件中進行全表查詢時,一律不要使用*號,需要哪些字段則應該明確寫明;pojo類中的屬性不應該以is開頭,但是數據庫中的字段名稱必須以is_XXX開頭,這時可以在resultMap中進行字段和屬性的映射;在mapper文件中盡量不要使用${},應該使用#{},以免造成SQL注入問題;不允許直接拿HashMap和HashTable作為查詢結果的輸出;@transactional注解盡量不要濫用,事務會影響數據庫的QPS,另外使用事務的地方,必須要考慮好事務回滾的最優方案,包括緩存回滾、搜索引擎回滾、消息補償和統計修正等問題;

  四:安全規約

  我們在開發中不僅要最求效率和質量,也要做到百毒不侵,做好系統的安全工作。一般系統中牽扯到用戶個人的頁面或者功能時必須做權限校驗;用戶的一些敏感數據不能直接展示,必須對展示數據進行脫敏;用戶輸入的SQL參數必須嚴格進行參數綁定或者metadata字段值限定的操作,防止發生SQL注入的問題,切記:禁止允許用戶使用字符串拼接SQL的方式來訪問數據庫,這危害可就大了去了~~,在開發中用戶請求傳入的參數必須做有效性驗證,如果有必要則實現雙重校驗,即前后台校驗,忽略參數校驗,可能會導致page size過大導致內存溢出、惡意order by導致數據庫慢查詢、任意重定向、反序列化注入等問題;禁止向HTML頁面輸出未經安全過濾或位正確轉義的用戶數據;表單、AJAX提交必須執行CSRF安全過濾(CSRF是一類常見的編程漏洞,意為跨站請求偽造,對於存在CSRF漏洞的網站或應用,攻擊者可以事先構造好URL,只要受害者用戶一旦訪問網站或應用,后台便在用戶不知情的情況下對數據庫中用戶參數進行相應的修改);在使用平台資源,譬如短信、郵件、電話、下單和支付等業務場景時,必須實現正確的防重放限制,比如數量的限制、疲勞度控制、驗證碼校驗,避免被濫刷,資損等情況。

  干到這兒我本人學到的一些經驗全部分享完畢,能力有限,總結的可能不太到位,希望各位讀者見諒!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM