如何保證前端項(xiàng)目代碼質(zhì)量
What
什么是代碼本身的質(zhì)量?
代碼本身的質(zhì)量: 包括復(fù)雜度, 重復(fù)率, 代碼風(fēng)格等。
復(fù)雜度: 項(xiàng)目代碼量,模塊大小,耦合度等
重復(fù)率: 重復(fù)出現(xiàn)的代碼區(qū)塊占比,通常要求在5%以下(借助平臺(tái)化工具如Sonar)
代碼風(fēng)格: 代碼風(fēng)格是否統(tǒng)一(動(dòng)態(tài)語言代碼如JS, Python風(fēng)格不受約束)
代碼質(zhì)量下降惡性循環(huán)
常見的代碼質(zhì)量下降的原因:
破罐破摔: 在爛代碼上迭代代碼罪惡感比較小
傳染性: 不在意代碼質(zhì)量, 只關(guān)注業(yè)務(wù)的產(chǎn)出
心有余而力不足
常見的導(dǎo)致惡性循環(huán)的場(chǎng)景:
-
業(yè)務(wù)壓力太大
爛代碼產(chǎn)生的常見原因是業(yè)務(wù)壓力大,導(dǎo)致沒有時(shí)間或意愿講究代碼質(zhì)量。因?yàn)橄驑I(yè)務(wù)壓力妥協(xié)而生產(chǎn)爛代碼之后,開發(fā)效率會(huì)隨之下降,進(jìn)而導(dǎo)致業(yè)務(wù)壓力更大,形成一種典型的惡性循環(huán)。
-
通過增加人力解決業(yè)務(wù)壓力
為了應(yīng)對(duì)業(yè)務(wù)壓力,常見的做法就是向項(xiàng)目中增加人力,但是單純地增加人力的話,會(huì)因?yàn)轱L(fēng)格不一致、溝通成本上升等原因?qū)е聽€代碼更多。
那么我們應(yīng)該如何解決呢?
這是一個(gè)長(zhǎng)期堅(jiān)持的過程。
代碼質(zhì)量管控四個(gè)階段
-
規(guī)范化
建立代碼規(guī)范與Code Review制度
1. [airbnb](https://github.com/airbnb/javascript)
2. [standard](https://github.com/standard/standard)
3. [node-style-guide](https://github.com/felixge/node-style-guide)
4. [google javascript style guide](https://google.github.io/styleguide/jsguide.html)
5. [google html/css style guide](https://google.github.io/styleguide/htmlcssguide.html)
6. [Vue風(fēng)格指南](https://cn.vuejs.org/v2/style-guide/)
7. 我覺得統(tǒng)一項(xiàng)目目錄結(jié)構(gòu)也是規(guī)范化的一種(比如我們用腳手架創(chuàng)建項(xiàng)目模板), 一個(gè)規(guī)范化的目錄結(jié)構(gòu)大大降低新人的上手成本。
-
自動(dòng)化
使用工具(linters)自動(dòng)檢查代碼質(zhì)量。
-
流程化
將代碼質(zhì)量檢查與代碼流動(dòng)過程綁定。
質(zhì)量檢查與代碼流動(dòng)綁定后的效果:
備注:
1. 編輯時(shí)候: 通過編輯器插件, 實(shí)時(shí)查看質(zhì)量檢查
2. 可以利用CI(Jekins/Travis)把構(gòu)建發(fā)布過程搬到線上, 先跑代碼掃描, 測(cè)試代碼等, 然后沒有錯(cuò)誤再進(jìn)行build, build成功通過ssh推到服務(wù)器。
-
中心化
以團(tuán)隊(duì)整體為視角,集中管理代碼規(guī)范,并實(shí)現(xiàn)質(zhì)量狀況透明化。
當(dāng)團(tuán)隊(duì)規(guī)模越來越大,項(xiàng)目越來越多時(shí),代碼質(zhì)量管控就會(huì)面臨以下問題:
1. 不同項(xiàng)目使用的代碼規(guī)范不一樣
2. 部分項(xiàng)目由于放松要求,沒有接入質(zhì)量檢查,或者存在大量未修復(fù)的缺陷
3. 無法從團(tuán)隊(duì)整體層面上體現(xiàn)各個(gè)項(xiàng)目的質(zhì)量狀況對(duì)比
為了應(yīng)對(duì)以上問題,需要建設(shè)中心化的代碼質(zhì)量管控體系,要點(diǎn)包括:
代碼規(guī)范統(tǒng)一管理。通過腳手架命令垂直管理代碼掃描配置規(guī)則集, 自動(dòng)安裝,不在本地寫規(guī)則。一個(gè)團(tuán)隊(duì)、一類項(xiàng)目、一套規(guī)則。
* * *
* [待定] <u>使用統(tǒng)一的持續(xù)集成服務(wù)(Jekins/Travis等)。質(zhì)量檢查不通過的項(xiàng)目不能上線。</u>
* [待定]<u> 建立代碼質(zhì)量評(píng)分制度(借助Sonar)。讓項(xiàng)目與項(xiàng)目之間能夠橫向?qū)Ρ?,?xiàng)目自身能夠縱向?qū)Ρ龋⑶疫M(jìn)行匯總反饋。</u>
Why
代碼質(zhì)量是團(tuán)隊(duì)技術(shù)水平和管理水平的直接體現(xiàn)。
看代碼的時(shí)間遠(yuǎn)遠(yuǎn)多于寫代碼的時(shí)間
目前前端項(xiàng)目出現(xiàn)的問題
-
書寫風(fēng)格不統(tǒng)一, 閱讀體驗(yàn)差
-
維護(hù)性差, 復(fù)用性差(Code Review互相進(jìn)步)
-
容易出現(xiàn)低質(zhì)量代碼, 代碼返工率高
-
git commit不規(guī)范
How
通過哪些手段來保證代碼質(zhì)量
EditorConfig
[EditorConfig]( https://editorconfig.org/)在多人協(xié)作開發(fā)項(xiàng)目時(shí)候, 支持跨編輯器, IDE來支持維護(hù)一致的編碼樣式(文件格式)。
VSCode插件EditorConfig for VS Code提供一鍵生成.editorconfig。
查看[實(shí)例](https://editorconfig.org/#example-file)。
TypeScript
- [官網(wǎng)介紹](https://www.typescriptlang.org/
)。
- [中文awesome-typescript](https://github.com/semlinker/awesome-typescript)
- [TypeScript體系調(diào)研報(bào)告](https://juejin.im/post/59c46bc86fb9a00a4636f939)
- [2018年度JS趨勢(shì)報(bào)告](https://2018.stateofjs.com/javascript-flavors/overview/)
Git Hooks
Git能在特定的重要?jiǎng)幼靼l(fā)生時(shí)觸發(fā)自定義腳本。有兩組這樣的鉤子:客戶端的和服務(wù)器端的。客戶端鉤子由諸如提交和合并這樣的操作所調(diào)用,而服務(wù)器端鉤子作用于諸如接收被推送的提交這樣的聯(lián)網(wǎng)操作, 我們目前使用的大多數(shù)是客戶端鉤子。
通過[husky](https://github.com/typicode/husky)集成[git hooks](https://git-scm.com/book/zh/v2/%E8%87%AA%E5%AE%9A%E4%B9%89-Git-Git-%E9%92%A9%E5%AD%90), 如果對(duì)git想有更全面的理解推薦閱讀[GIt文檔](https://git-scm.com/book/zh/v2)。
husky會(huì)安裝一系列的git hook到項(xiàng)目的.git/hook目錄中。
下面兩張圖分別對(duì)比沒有安裝husky與安裝了husky的git目錄區(qū)別:
當(dāng)你用 git init 初始化一個(gè)新版本庫時(shí),Git 默認(rèn)會(huì)在這個(gè)目錄中放置一些示例腳本(.sample結(jié)尾的文件)。
pre-commit
pre-commit 鉤子在鍵入提交信息前運(yùn)行。它用于檢查即將提交的快照,你可以利用該鉤子,來檢查代碼風(fēng)格是否一致(運(yùn)行類似 lint 的程序。
- [lint-staged](https://github.com/okonet/lint-staged): 可以獲取所有被提交的文件并執(zhí)行配置好的任務(wù)命令,各種lint校驗(yàn)工具可以配置好lint-staged任務(wù)中。
- [prettier](https://prettier.io/): 可以配置到lint-staged中, 實(shí)現(xiàn)自動(dòng)格式化編碼風(fēng)格。
- [stylelint](https://github.com/stylelint/stylelint)
- [eslint](https://cn.eslint.org/)
- [tslint](https://github.com/palantir/tslint)
- [eslint-plugin-vue](https://github.com/vuejs/eslint-plugin-vue): Vue.js官方推薦的lint工具
關(guān)于[為什么選擇prettier, 以及eslint 與prettier區(qū)別?](https://zhuanlan.zhihu.com/p/62542268)。
關(guān)于[prettier配置](https://prettier.io/docs/en/configuration.html)。
關(guān)于[stylelint配置](https://stylelint.io/user-guide/configuration/)。
關(guān)于[eslint配置](https://cn.eslint.org/docs/user-guide/configuring)。
commit-msg
[commitlint](https://github.com/conventional-changelog/commitlint)。
commit-msg 可以用來在提交通過前驗(yàn)證項(xiàng)目狀態(tài)或提交信息, 使用該鉤子來核對(duì)提交信息是否遵循指定的模板。
關(guān)于git hooks在package.json配置:
測(cè)試
unittest
- - [Jest](https://jestjs.io/
- )
- - [Mocha](https://mochajs.org/
- )
e2e
- - [Nightwatch](http://nightwatchjs.org/
- )
- - [Cypress](https://www.cypress.io/
- )
CHANGELOG
更新日志, [standard-version](https://github.com/conventional-changelog/standard-version)。
Code Review
* [待定] Review制度,我們目前公司在代碼merge時(shí)候多人審核才通過。
如何快速落地到當(dāng)前業(yè)務(wù)
前端腳手架(xx-cli)
采用中心化集中管理代碼掃描配置文件的思路, 把code lint配置文件做成一個(gè)npm包發(fā)到內(nèi)網(wǎng), 然后擴(kuò)展腳手架命令一鍵執(zhí)行下發(fā)遠(yuǎn)程配置文件到本地項(xiàng)目, 并且把新增的package.json依賴打進(jìn)來, 大家后面再安裝新的依賴即可。
所謂中心化管理: 所有項(xiàng)目代碼配置文件以遠(yuǎn)程配置文件為準(zhǔn), 如果你本地有同名配置會(huì)被刪除, 這樣方便后續(xù)我們更新配置文件比如(增加vw/vh適配), 以及所有業(yè)務(wù)同步問題。
```
目前只有基于vue.js項(xiàng)目的lint腳本命令, 后續(xù)有別的項(xiàng)目, 考慮通過
xx-cli lint -- vue
xx-cli lint -- node
擴(kuò)展
```
demo演示
demo演示如何在舊項(xiàng)目中植入代碼質(zhì)量檢測(cè)?
由于這部分是在內(nèi)網(wǎng)演示就不發(fā)不出來了。
至于腳手架可以參考我之前的demo[easy-cli](https://github.com/NuoHui/easy-cli)。這是比較全的demo。
Future
J ekins自動(dòng)化
[Sonar](https://www.sonarqube.org/)
[Github:](https://github.com/SonarSource/sonarqube)
SonarQube 是一款領(lǐng)先的持續(xù)代碼質(zhì)量監(jiān)控平臺(tái),開源在github 上,可以輕松配置在內(nèi)網(wǎng)服務(wù)器,實(shí)時(shí)監(jiān)控代碼,幫助了解提升提升團(tuán)隊(duì)項(xiàng)目代碼質(zhì)量。通過插件機(jī)制,SonarQube可以繼承不同的測(cè)試工具,代碼分析工具,以及持續(xù)集成工具。
與持續(xù)集成工具(例如 Hudson/Jenkins 等)不同,SonarQube 并不是簡(jiǎn)單地把不同的代碼檢查工具結(jié)果(例如 FindBugs,PMD 等)直接顯示在 Web 頁面上,而是通過不同的插件對(duì)這些結(jié)果進(jìn)行再加工處理,通過量化的方式度量代碼質(zhì)量的變化,從而可以方便地對(duì)不同規(guī)模和種類的工程進(jìn)行代碼質(zhì)量管理。
行業(yè)內(nèi)提到"代碼質(zhì)量管理, 自動(dòng)化質(zhì)量管理", 一般指的都是通過Sonar來實(shí)現(xiàn)。
用Sonar能夠?qū)崿F(xiàn)什么?
- 技術(shù)債務(wù)(sonar根據(jù)"規(guī)則"掃描出不符合規(guī)則的代碼)
- 覆蓋率(單元測(cè)試覆蓋率)
- 重復(fù)(重復(fù)的代碼, 有利于提醒封裝)
- 結(jié)構(gòu)
- …
sonarjs
sonar支持多種編程語言, 其中包括JavaScript. 如[sonarjs](https://www.sonarsource.com/products/codeanalyzers/sonarjs.html).