前端進(jìn)階(3) - 怎樣提升代碼質(zhì)量

怎樣提升代碼質(zhì)量

盡管寫了多年的代碼悬嗓,但是始終有一件事不敢確定,就是自己的代碼究竟寫得好不好?這個問題很難有確切的答案舟肉,因?yàn)檫@個跟風(fēng)格修噪、規(guī)范有很大關(guān)系,而風(fēng)格路媚、規(guī)范很難說好還是不好黄琼。

但我覺得好的代碼,一定是能讓別人閱讀起來有一種爽心悅目的感覺整慎。

1. 開發(fā)規(guī)范

不管是團(tuán)隊(duì)協(xié)作還是個人獨(dú)立開發(fā)脏款,遵循一定的開發(fā)規(guī)范都是很有必要的。就團(tuán)隊(duì)協(xié)作來說裤园,可能每個人的風(fēng)格迥然不同撤师,如果沒有規(guī)范的約束的話,團(tuán)隊(duì)之間的協(xié)作會大打折扣的拧揽。而就個人獨(dú)立開發(fā)來說剃盾,很難說一年后的你回頭看今天自己寫的代碼是滿意的。

js 開發(fā)規(guī)范

一般前端開發(fā)的主要工作都要 js 部分强法,所以一般前端開發(fā)規(guī)范都是對 js 而言的万俗。

認(rèn)可度比較高的有:

css 開發(fā)規(guī)范

認(rèn)可度比較高的有:

2. 使用工具檢查、自動矯正與優(yōu)化

盡管有規(guī)范可循饮怯,但其實(shí)開發(fā)的時候并不知道自己的代碼是否是符合規(guī)范的闰歪,所以就需要工具來檢查與矯正代碼。

2.1 檢查與自動矯正

認(rèn)可度比較高的有:

  1. eslint:檢查 js 語法(包括 jsx 語法)蓖墅,然后最大程度的矯正不符合規(guī)范的代碼库倘;
  2. stylelint:檢查 css 語法(包括 less, scss 語法),然后最大程度的矯正不符合規(guī)范的代碼论矾。

安裝

目錄文件

|-- root/                    // 項(xiàng)目根目錄
    |-- package.json
    |-- .eslintrc            // eslint 配置文件
    |-- .eslintignore        // eslint 忽略配置教翩,類似 .gitignore
    |-- .stylelintrc         // stylelint 配置文件
    |-- .stylelintignore     // stylelint 忽略配置,類似 .gitignore

package.json

"scripts": {
  "eslint": "eslint .",                             // 僅檢查
  "eslint:fix": "eslint . --fix",                   // 檢查之后自動矯正
  
  "stylelint": "stylelint \"./**/*.{css,less,sass,scss}\"",             // 僅檢查
  "stylelint:fix": "stylelint \"./**/*.{css,less,sass,scss}\" --fix"    // 檢查之后自動矯正
},
"devDependencies": {
  "eslint": "^4.19.1",                              // eslint 主文件
  "babel-eslint": "^8.2.5",                         // babel 轉(zhuǎn)碼器 for eslint
  "eslint-config-airbnb": "^17.0.0",                // airbnb eslint 規(guī)則
  "eslint-config-prettier": "^2.9.0",               // prettier eslint 規(guī)則
  "eslint-plugin-babel": "^5.1.0",                  // eslint 的 babel 轉(zhuǎn)碼插件
  "eslint-plugin-import": "^2.13.0",                // eslint 檢查模塊輸入輸出是否正確的插件
  "eslint-plugin-jsx-a11y": "^6.1.0",               // eslint jsx 語法檢查的一個插件
  "eslint-plugin-prettier": "^2.6.2",               // prettier eslint 插件
  "eslint-plugin-react": "^7.10.0",                 // eslint react 語法檢查插件
  
  "stylelint": "^9.3.0",                            // stylelint 主文件
  "stylelint-config-prettier": "^3.3.0",            // prettier stylelint 規(guī)則
  "stylelint-config-standard": "^18.2.0"            // standard stylelint 規(guī)則
},

.eslintrc

{
  "parser": "babel-eslint",
  "extends": ["airbnb", "prettier"],
  "env": {
    "browser": true,
    "node": true,
    "es6": true,
    "mocha": true,
    "jest": true,
    "jasmine": true
  },
  "rules": {
    ... // 更多自己定義的規(guī)則
  }
}

.stylelintrc

{
  "extends": ["stylelint-config-standard", "stylelint-config-prettier"],
  "rules": {
    ... // 更多自己定義的規(guī)則
  }
}

運(yùn)行命令

npm run eslint           // 檢查項(xiàng)目中的 js(jsx) 語法
npm run eslint:fix       // 檢查項(xiàng)目中的 js(jsx) 語法贪壳,并最大程度的矯正

npm run stylelint        // 檢查項(xiàng)目中的 css(less,scss) 語法
npm run stylelint:fix    // 檢查項(xiàng)目中的 css(less,scss) 語法饱亿,并最大程度的矯正

2.2 代碼優(yōu)化

eslintstylelint 在對代碼做檢查和自動矯正時,只保證代碼的語法是符合一定的規(guī)范闰靴,并不對代碼的格式做任何優(yōu)化彪笼,所以,自動矯正后的代碼可能格式會不太好蚂且,閱讀性不太高配猫。

所以,一般會在對代碼檢查與自動矯正之后做代碼格式優(yōu)化杏死。

使用比較多的:prettier.

安裝

目錄文件

|-- root/                    // 項(xiàng)目根目錄
    |-- package.json
    |-- .prettierrc          // prettier 配置文件
    |-- .prettierignore      // prettier 忽略配置泵肄,類似 .gitignore

package.json

"scripts": {
  // 對 js,jsx,css,less,md,json 文件進(jìn)行優(yōu)化
  "prettier": "prettier --write \"./**/*.{js,jsx,css,less,md,json}\""
},
"devDependencies": {
  "prettier": "^1.13.7"
},

.prettierrc

{
  "singleQuote": true,
  "trailingComma": "es5",
  "printWidth": 120,
  "overrides": [
    {
      "files": ".prettierrc",
      "options": { "parser": "json" }
    }
  ]
}

運(yùn)行命令

npm run prettier

2.3 強(qiáng)制對代碼進(jìn)行檢查捆交、自動矯正與優(yōu)化

盡管定好了規(guī)范與工具命令,但開發(fā)人員完全可以跳過這些步驟腐巢,這尤其是在團(tuán)隊(duì)開發(fā)中很難強(qiáng)制其他組員會去做代碼檢查品追、自動矯正與優(yōu)化。

所以系忙,使用工具強(qiáng)制開發(fā)人員對代碼進(jìn)行檢查诵盼、自動矯正與優(yōu)化惠豺,就顯得很有必要了银还。

使用比較多的:

  • husky:對 git 進(jìn)行 hook,可以在 git 操作之前做一些操作洁墙;
  • lint-staged:對當(dāng)前 git 提交的代碼進(jìn)行一些操作蛹疯。

package.json

"scripts": {
  "precommit": "npm run lint-staged",     // 在 git 提交之前運(yùn)行 lint-staged 命令
  "lint-staged": "lint-staged",           // 對 git 將要提交的代碼做操作
},
"devDependencies": {
  "husky": "^0.14.3",
  "lint-staged": "^7.2.0",
},
"lint-staged": {
  "**/*.{js,jsx}": [
    "eslint --fix",                      // 對 js,jsx 文件進(jìn)行 eslint 檢查、自動矯正 
    "prettier --write",                  // 然后 使用 prettier 進(jìn)行代碼格式優(yōu)化
    "git add"                            // 最后重新添加
  ],
  "**/*.{css,less}": [
    "stylelint --fix",                   // 對 css,less 文件進(jìn)行 stylelint 檢查热监、自動矯正
    "prettier --write",                  // 然后 使用 prettier 進(jìn)行代碼格式優(yōu)化
    "git add"                            // 最后重新添加
  ],
  "**/*.{md,json}": [
    "prettier --write",                  // 使用 prettier 進(jìn)行代碼格式優(yōu)化
    "git add"                            // 最后重新添加
  ]
},

這樣捺弦,在每次 git commit 之前,都會對將要提交的文件進(jìn)行檢查孝扛、自動矯正與優(yōu)化列吼,如果其中有一項(xiàng)發(fā)生錯誤,本次提交都會失敗苦始。然后開發(fā)人員調(diào)整代碼之后再進(jìn)行提交寞钥,只有每項(xiàng)任務(wù)都是沒問題的,才能提交成功陌选。

這樣理郑,便可使每個開發(fā)人員都是按照一定的規(guī)范與風(fēng)格寫代碼的。

3. 編輯器配置:.editorconfig

有了規(guī)范咨油,也加上了工具做自動化代碼檢查您炉、矯正與優(yōu)化,但還有一點(diǎn)需要提及一下役电,就是在團(tuán)隊(duì)協(xié)作中赚爵,每個開發(fā)人員可能使用的編輯器不一樣,編輯器的配置也不一樣法瑟,這就導(dǎo)致工具在做格式優(yōu)化的時候冀膝,不同的開發(fā)人員中輸出的代碼不一樣。

這就需要配置文件 .editorconfig 去統(tǒng)一每個開發(fā)人員的編輯器配置瓢谢。

目錄文件

|-- root/                    // 項(xiàng)目根目錄
    |-- .editorconfig        // 編輯器配置文件

.editorconfig

# http://editorconfig.org
root = true

[*]
indent_style = space                    # 輸入的 tab 都用空格代替
indent_size = 2                         # 一個 tab 用 2 個空格代替
end_of_line = lf                        # 換行符使用 unix 的換行符 \n
charset = utf-8                         # 字符編碼 utf-8
trim_trailing_whitespace = true         # 去掉每行末尾的空格
insert_final_newline = true             # 每個文件末尾都加一個空行

[*.md]
trim_trailing_whitespace = false        # .md 文件不去掉每行末尾的空格

更多的編輯器配置規(guī)則畸写,可以查看 http://editorconfig.org.

4. 業(yè)務(wù)邏輯優(yōu)化

上面提到的這些只是風(fēng)格、規(guī)范氓扛、語法上的優(yōu)化枯芬,但對編碼質(zhì)量的評估更多的是在業(yè)務(wù)邏輯具體實(shí)現(xiàn)這一塊论笔。

一般來說,業(yè)務(wù)邏輯實(shí)現(xiàn)的優(yōu)化離不開下面幾個方向:

  1. 模塊化:
    • js 的模塊化已經(jīng)很成熟了千所,目前使用最多的是 commonjs 模塊化規(guī)范和 es6 模塊狂魔;
    • css 的模塊化也一直在探索中,之前也專門寫了一篇 CSS 模塊化淫痰,可以參考下最楷;
    • html 沒有模塊化,但是可以將一個很長的 html 文件進(jìn)行分塊待错,參考 html-loader籽孙。
  2. 組件化:當(dāng)項(xiàng)目變大、變多火俄,很多公共的代碼需要復(fù)用或者跨項(xiàng)目使用的時候犯建,組件化就變得很必要了,之前也專門寫了一篇 組件化瓜客,可以參考下适瓦;
  3. 邏輯解耦:把一個復(fù)雜的邏輯,分割成多個子邏輯谱仪,然后將子邏輯串起來玻熙,或者把多個交叉邏輯的公共部分拆出來,然后再挨個串起來疯攒;
  4. 功能分塊:細(xì)化一個一個的功能為單獨(dú)的模塊嗦随。

5. 邏輯解耦

邏輯解耦就是把一個復(fù)雜的邏輯,分割成多個子邏輯卸例,或者把多個交叉邏輯的公共部分拆成單個邏輯称杨。這樣做的目的是降低應(yīng)用的復(fù)雜度,更據(jù)閱讀性筷转。

比如姑原,3 個串行的 ajax 請求,可以分割成多個子邏輯:

$.getJSON(url1, data1, res1 => {
  // do something with res1
  
  $.getJSON(url2, data2, res2 => {
    // do something with res2
    
    $.getJSON(url3, data3, res3 => {
      // do something with res3
    });
  });
});

邏輯解耦之后:

const request1 = () => {
  $.getJSON(url1, data1, res1 => {
    // do something with res1
    
    request2();
  }
};
const request2 = () => {
  $.getJSON(url2, data2, res2 => {
    // do something with res2
    
    request3();
  }
};
const request3 = () => {
  $.getJSON(url3, data3, res3 => {
    // do something with res3
  }
};

request1();

再比如呜舒,在不同文件中需要依賴同一個 ajax 請求锭汛,可以把交叉邏輯的部分拆成單個邏輯:

# file1.js

$.getJSON(url, data, res => {
  // do something with res
}

# file2.js

$.getJSON(url, data, res => {
  // do something with res
}

邏輯解耦之后:

# request.js

module.exports = cb => {
  $.getJSON(url, data, res => {
    cb(res);
  }
};

# file1.js

const request = require('./request');
request(res => {
  // do something with res
});

# file2.js

const request = require('./request');
request(res => {
  // do something with res
});

6. 功能分塊

細(xì)化功能為單獨(dú)的模塊也是提升代碼質(zhì)量的一個方式。

比如袭蝗,將一個文件拆成多個文件(顆粱脚梗化):

# util.js

module.exports = {
  func1: args => { ... },
  func2: args => { ... },
  func3: args => { ... },
}; 

將功能分塊之后:

# util/func1.js

module.exports = args => { ... };

# util/func2.js

module.exports = args => { ... };

# util/func3.js

module.exports = args => { ... };

再比如,將一個大功能塊分割成多個小功能塊:

$.getJSON(url, data, res => {
  // 渲染頁面
  ...
  
  // 初始化組件
  ...
  
  // 裝載數(shù)據(jù)
  ...
  
  // 綁定模型
  ...
  
  // ...
  ...
}

一般這種情況下到腥,一個功能代碼塊就可能會很長朵逝,200 行都有可能,這個時候就需要將其分割成多個小代碼塊:

const renderPages = res => { ... };
const initComponents = res => { ... };
const fillData = res => { ... };
const bindModels = res => { ... };
...

$.getJSON(url, data, res => {
  // 渲染頁面
  renderPages();
  
  // 初始化組件
  initComponents();
  
  // 裝載數(shù)據(jù)
  fillData()
  
  // 綁定模型
  bindModels();
  
  // ...
  ...
}

7. 多閱讀

最后乡范,也是最重要的配名,就是多閱讀別人優(yōu)秀的代碼啤咽,閱讀永遠(yuǎn)是獲取知識最重要的途徑,沒有之一渠脉。

8. 后續(xù)

更多博客宇整,查看 https://github.com/senntyou/blogs

作者:深予之 (@senntyou)

版權(quán)聲明:自由轉(zhuǎn)載-非商用-非衍生-保持署名(創(chuàng)意共享3.0許可證

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市芋膘,隨后出現(xiàn)的幾起案子鳞青,更是在濱河造成了極大的恐慌,老刑警劉巖为朋,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臂拓,死亡現(xiàn)場離奇詭異,居然都是意外死亡潜腻,警方通過查閱死者的電腦和手機(jī)埃儿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來融涣,“玉大人,你說我怎么就攤上這事精钮⊥梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵轨香,是天一觀的道長忽你。 經(jīng)常有香客問我,道長臂容,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任脓杉,我火速辦了婚禮,結(jié)果婚禮上尿赚,老公的妹妹穿的比我還像新娘。我一直安慰自己蕉堰,他們只是感情好凌净,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布屋讶。 她就那樣靜靜地躺著,像睡著了一般皿渗。 火紅的嫁衣襯著肌膚如雪斩芭。 梳的紋絲不亂的頭發(fā)上没卸,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天,我揣著相機(jī)與錄音秒旋,去河邊找鬼。 笑死煤蚌,一個胖子當(dāng)著我的面吹牛细卧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播贪庙,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼止邮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起屈扎,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤撩匕,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后模蜡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扁凛,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年膝昆,在試婚紗的時候發(fā)現(xiàn)自己被綠了叠必。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡纬朝,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出判没,到底是詐尸還是另有隱情,我是刑警寧澤澄峰,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站绸硕,受9級特大地震影響魂毁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜席楚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一烦秩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧闻镶,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽岭皂。三九已至沼头,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間进倍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工陶因, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留垂蜗,地道東北人解幽。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓烘苹,卻偏偏與公主長得像,于是被迫代替她去往敵國和親霜定。 傳聞我的和親對象是個殘疾皇子捆探,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容