代碼質量的四個階段之3Rs軟件架構介紹
當提到代碼質量,我們可能會想到:代碼風格,命名,內(nèi)聚,耦合,重復代碼率,圈復雜度等等。當提到代碼優(yōu)化,我們可能會想到代碼風格規(guī)范,高內(nèi)聚,低耦合,單一職責,開放封閉原則,約定優(yōu)于配置,單元測試等等。
給你一段代碼,你能簡要扼要的說出當前代碼的質量情況,并提出優(yōu)化的方向嗎?
如果覺得很難,可以參考 3Rs 軟件架構[1]。
3Rs 軟件架構對代碼質量做了分層,給優(yōu)化代碼提供了方向:可讀性 => 可重用性 => 可重構。下面我們來具體了解下每層代碼的特點及優(yōu)化方法。
第 4 個階段: 很難維護的代碼
這階段的代碼很難維護,俗稱shi代碼。這階段的代碼,讀起來和改起來都很難。
這階段的代碼讀起來難。例如:
- 代碼風格不一致??s進,空格不一致。
- 謎一樣的命名。
- 很長很長的函數(shù)。
- 分支很多,嵌套很深的條件語句。
這階段的代碼改起來也難。例如:
- 大量重復代碼,導致一處有問題,要改多處。
- 高耦合的代碼導致,改一個模塊,會改對應的很多關聯(lián)模塊。
- 關聯(lián)很緊密的代碼,但離的很遠。改起來好累。
第 3 個階段:可讀的代碼(Readability)
這階段的代碼可讀性好??勺x性好換個說法就是讀起來不費腦子。它有以下的特征:
- 一致的代碼風格??崭瘢s進,命名風格(駝峰,中劃線等)等在整個項目里是一致的。
- 合理的命名。“看其名而知其意”。
- 必要的注釋。代碼本身無法清晰地闡述作者的意圖時,要寫注釋。
- 沒有代碼行數(shù)很多(超過1千行)的功能:文件,組件,函數(shù)等。
- 函數(shù)的參數(shù)數(shù)量不超過4個。
- 沒有圈復雜度很高的代碼。圈復雜度高往往意味著分支多或嵌套深。
如何達到
要達到這個階段相對比較容易。
代碼檢查工具能保證代碼風格的統(tǒng)一。代碼檢查工具也能檢查:函數(shù)的參數(shù)個數(shù),圈復雜度[2]等。工具有: ESLint[3],CSS Lint[4]等。代碼改動后,必須通過工具檢查通過后,才允許提交。用代碼格式化工具,可以自動修復有代碼風格問題的代碼。工具有 Prettier[5] 等。
這階段最難的就是命名了。好的命名是“看其名而知其意”,是直白的,有意義的。推薦使用故宮命名法[6]。了解更多命名的技巧見這里[7]。
第 2 個階段: 可重用的代碼(Reusability)
這階段的代碼是可重用的代碼。這個階段代碼的特點:
- 單一職責。每個模塊都只有一個職責。
- 不必要的重復代碼很少。重復代碼會導致一處有問題,要改多處。但如果過度追求沒有重復,也會導致可讀性差,不靈活的問題。
- 模塊間是低耦合,高內(nèi)聚的。
如何達到
要達到這個階段需要在做代碼設計的時候,設計好模塊之間的邊界和 API,做到職責清晰,高內(nèi)聚,低耦合。達到這個階段的建議:
- 多寫代碼。對之前寫的代碼做復盤。
- 多讀優(yōu)秀代碼,學習借鑒好的地方。
- 學習設計原則,設計模式。
- 學習一些具體的技術:函數(shù)式編程,響應式編程,面向領域編程等等。
第 1 個階段: 可重構的代碼(Refactorability)
這階段的代碼是可重構的。這意味著,當你重構某塊代碼(不修改對外的API),不改其他代碼,其他代碼仍能正常工作。這個階段的代碼一定是低耦合的。模塊之間的連接就像樂高。
如何達到
要達到這個階段需要:
- 隔離副作用。
- 測試。
- 靜態(tài)類型。
- 下面具體來說。
隔離副作用
副作用指修改模塊外的數(shù)據(jù)。例如:修改全局變量,修改 DOM等。
在模塊代碼中,混入副作用代碼會導致如下的問題:
- 副作用讓代碼變得難以測試。當模塊依賴的外部數(shù)據(jù)發(fā)生變化后,模塊的返回值可能會變化。這讓模塊的返回變得不穩(wěn)定。
- 副作用會導致模塊間的耦合。如果多個模塊都依賴某個外部數(shù)據(jù),那這幾個外部模塊之間是耦合的。多個模塊改都可以改外部數(shù)據(jù),數(shù)據(jù)流很混亂。
- 副作用讓我們的系統(tǒng)變得不可預測。如果一個模塊改了外部數(shù)據(jù),可能會影響整個系統(tǒng)。
如何隔離副作用?答案是在統(tǒng)一的地方管理應用的全局數(shù)據(jù)。比如用 Redux[8] 或 Vuex[9]。
測試
這邊的測試指的是白盒測試。測試可以保證代碼的改動不會影響測試覆蓋部分的功能。
對前端來說,需要寫單元測試,端到端測試。每次提交代碼,所有測試都需要跑過。
靜態(tài)類型
使用靜態(tài)類型可以規(guī)避很多低級的語法和邏輯錯誤,比如參數(shù)少傳了。目前前端靜態(tài)類型主流是用 TypeScript[10]。
參考資料
[1]3Rs 軟件架構: https://github.com/ryanmcdermott/3rs-of-software-architecture
[2]圈復雜度: http://eslint.cn/docs/rules/complexity
[3]ESLint: https://eslint.org/
[4]CSS Lint: http://csslint.net/
[5]Prettier: https://prettier.io/
[6]故宮命名法: https://juejin.cn/post/6844903913892610061
[7]這里: https://www.yuque.com/fegogogo/fe/wup00n
[8]Redux: https://redux.js.org/
[9]Vuex: https://vuex.vuejs.org/zh/guide/
[10]TypeScript: https://www.typescriptlang.org/