天天看點

如何提高代碼品質

說起代碼品質,腦子裡會冒出很多詞,命名規範、格式規範、日志規範、單元測試覆寫率... 但我覺得,代碼品質總結起來就兩個:好看和好用。 好看是指代碼可讀性好,容易了解、容易維護,别人接手了不罵你;好用則指代碼健壯,不容易出錯,機器跑着不罵你。即使出錯,也容易定位,容易止損和恢複。為何需要提高代碼品質?

以下是我認為的幾點:

提升代碼的可維護性,降低新人接手的成本

促進交流,促進知識共享,做好backup

促進風格一緻,降低團隊間應用流轉的難度

建設寫好代碼、做好設計的團隊氛圍

但有一點需要說明,我認為寫代碼本身是一個創造過程,能讓人享受其中,如果有太多的條條框框限制,寫代碼就失去了創造的樂趣,是以,這裡為代碼品質建設立一個原則:

隻提供建議,不強制遵循

鼓勵創造性的編碼

鼓勵藝術性的編碼

有兩種途徑:

第一種途徑:先有好的設計--->然後用優秀的編碼去實作--->再把優秀的編碼風格延續下去

第二種途徑:從糟糕的代碼開始--->不斷去重構,向優秀的設計方案和代碼風格不斷逼近--->再延續下去

首先得知道什麼是好的代碼,這就要有标準,那就是我們常常看到的各種各樣的規範,但我覺得要有幾個簡單的原則,太多了,記不住,有幾條原則簡單的原則,可以時不時拿來判斷,目前做得對不對。

然後就是去實踐規範,這裡需要一些技巧、一些工具,來幫助我們更好地遵循規範。

接着是度量,看我們對規範實踐的效果,這就是我們常說也常做的Code Review,但Code Review也需要遵循一定的規範,應用一定的技巧。

度量之後是改進,CR結果要及時跟進,這是最重要一環,否則CR就沒有實際意義。

總結不可少,複盤是一種很有用的工具,CR也需要複盤,總結CR流程、過程等方面好的和不好的地方,更新規範和checklist。

接下來我們分别聊一聊各個步驟。

從上邊高品質代碼的誕生途徑我們可以看出,設計也是很重要的一環,是以我們的規範包括設計規範和編碼規範,結合我們的生産實際,這裡加上安全生産的規範,是以規範有3部分:設計、編碼、安全生産。

設計: 先有優秀的方案

設計推薦多用圖表達,圖比文字有更直覺的傳達能力:

首先是業務流程圖,它能快速建構起我們對業務的認知,帶着對業務的了解再來看代碼,事半功倍。

然後是用例圖,清晰地表達出我們系統的職責、邊界、服務對象,結合業務流程圖,能快速建構起我們對系統職責的認知。

接着是架構圖,從我們日常的設計需求來看,架構圖是需要的。好的架構圖能快速給人搭建起了解的架構,再來看系統的細節部分,就很好了解。架構圖推薦 C4 規範,它是我目前接觸的表達最清晰的架構圖規範。

接着再用時序圖、狀态圖、ER圖等把關鍵和複雜部分的設計表達出來。

但日常我們的需求有大有小,方案也不需要都遵循統一的範本,為了設計而設計,就徒增加工作量了。以按需為第一原則,能把要做啥,怎麼做的表達清楚即可。這裡按場景推薦各個圖的使用場景:

建立應用/對原有應用進行重大修改/複雜項目

業務流程圖(交代業務背景)

C4的系統上下文、容器、元件這3張圖

用例圖:有多個外部參與者

類圖:關鍵模型超過5個

狀态圖:對象狀态超過3個

時序圖:關鍵流程或複雜鍊路的參與對象超過3個

ER圖:涉及資料庫變更(包含資料表結構文檔)

一般項目/重大日常

業務流程圖

時序圖(複雜功能、關鍵流程)

日常

按需

編碼最重要的是可讀,控制複雜度,做到自解釋,能讓人像讀自然語言一樣讀自己的代碼,這是最高境界,也是神仙境界。然後是可維護性和可變更性,能快速、安全地修改代碼是目标。最後是對優雅實作的要求,卓越的代碼會讓人拍着大腿叫好,這個不稀奇,我們亂糟糟的代碼裡也偶爾會有閃光的片段。

編碼最高原則:

可讀性

控制複雜度

self-document

可維護性

優雅

合理的代碼分層,能控制各層的複雜度,以分層的思路去設計,也能提高代碼的複用性。對于分層,我認為熟悉的就是好的,能滿足工作中的大部分情況就好,這裡不談六邊形架構、清晰架構、DODAF等概念,自己駕馭不了,還不能拿出來吹。我推薦DDD最基礎的4層分層架構,如下:

這裡舉個我實際項目中用到的例子:

上述項目結構中,因為是導購項目,view相當于使用者界面層,application是應用層,domain是領域層,infrastructure是基礎設施層。

再對包的劃分說明一下:

領域對象、值對象、DTO、Service等定義都放在子域的包下,不要有大而全的entity、service、impl等包(這裡的子域是一個内聚的邏輯概念,對應的是領域設計裡的子域,如上例中的item在我們的導購裡就是商品這個子域)

常量定義盡量跟着相關的類走,作為類的靜态字段,不要有大而全的Constant類(Switch相關的除外,但也要按職責盡量拆分開關類)

代碼規範就推薦阿裡經濟體開發規約,很全面,也是阿裡同學的基本要求。代碼規範就推薦「阿裡經濟體開發規約」,很全面,也是阿裡同學的基本要求,開源版本:阿裡巴巴java開發手冊 https://github.com/alibaba/p3c

結合自己的經驗,重點說幾點:

命名

命名不用泛稱(反例:processData)

盡量用完整的單詞描述清楚作用和意圖,不要怕字多

對象字尾領域對象不帶字尾DTO:RPC接口提供的對象以作為VO:跟前端互動的對象PO:跟資料庫直接互動的對象

日志

所有背景都要有記錄檔、資料變更日志

日志要配置異步寫盤

線上僅保留WARN和ERROR級别日志

所有日志都要有traceId

異常日志要有堆棧、入參、能說清楚是什麼錯誤的資訊(可以出統一元件)

列印日志時,禁止直接用JSON工具将對象轉換成String

異常

怎麼抛:盡量使用非受檢異常,提高代碼可讀性

怎麼處理:統一異常用切面處理,或依賴SpringMvc的ControllerAdvice統一處理

異常catch範圍盡量小,厘清穩定代碼和非穩定代碼

禁止直接吞掉異常

時刻警惕NPE,多用Optional處理

注釋

注釋隻為了說明為什麼這麼做,不用來說明是在做什麼

面向對象

遵循原則:SRP/OCP/LSP/ISP/DIP

盡量隻暴露行為,不暴露資料

慎用繼承,優先使用組合方式

其它規範

方法行數保持在一屏之内(30行以内)

代碼送出commit message一定要講清楚做了啥控制每次送出的代碼量(一個功能一送出)

參數盡量用不可變對象(不對入參做修改,保持明确的入參和出參)盡量不用隐式入參(ThreadLocal)

資料結構無随機讀取時,用LinkedList替代ArrayList

風格做好分層,同層用統一的風格(設計/編碼)

安全生産還沒有系統總結過,結合自己做穩定性的工作經驗提幾點,後邊跟負責安全生産的同學多學習學習,再來更新:

防資損

要有資損評估/監控

易恢複

任何新功能上線都要有灰階能力

監控/報警

兜底設計/監控

性能監控

異常監控

低容忍錯誤要報警

關鍵名額要監控(業務/技術)

減少不必要的報警

降級/限流

識别出弱依賴,保證弱依賴可降級

識别出可限流的依賴方,做好監控和限流配置

給一些原則和技巧建議,幫忙落地規範。

設計

圖都不是必須的,隻要能講明白是怎麼做的,為什麼這麼做

使用Aone-Idea,它已經內建了PMD/FindBugs/CheckStyle功能,給開發的同學點個暫,超牛逼。開源版本:Alibaba Java Coding Guidelines alibaba  https://plugins.jetbrains.com/plugin/10046-alibaba-java-coding-guidelines

使用lombok,保持代碼的簡潔性

不斷重構,且遵循以下原則: DRY/YAGNI/Rule Of Three/KISS/POLA每次需求都是重構契機反問自己,能不能在[可讀性/易維護性]做得更好

使代碼讀起來像自然語言

功能性代碼和非功能性代碼分離

這得跟着公司和部門規範來,學習學習再來補充。

Review時機

項目提測後第一時間:不要在項目上線的前夜review,來不及改,review結果容易擱置,浪費參與人的青春

Review方式

小子產品:随時/Aone代碼評審/@backup同學

項目代碼:面對面投屏/Aone代碼評審 + IDE show/項目組+重點關注同學

Review内容

關注代碼的設計是如何落地需求的

總體流程

關鍵設計

重點功能

Review前提

代碼是編譯通過的

開啟Aone-Idea的實時檢測

Checklist

規範性

可維護性(高内聚低耦合、面向對象原則、實作複雜性等)

可變更性(擴充性等)

安全性/健壯性輸入檢查異常處理邊界檢查

性能依賴合理性

有運作時風險的問題必須上線前完成改動

其它問題盡量上線前完成修改,如未修改則要加todo,指定人和時間來修改

用工具來統計和提示CR結果改進情況

定期回顧和總結(周會環節)

更新checklist和代碼規範

發現好的代碼和設計,定期展示,給與獎勵

繼續閱讀