前端进阶(3) - 怎样提升代码质量
怎样提升代码质量
尽管写了多年的代码,但是始终有一件事不敢确定,就是自己的代码究竟写得好不好?这个问题很难有确切的答案,因为这个跟风格、规范有很大关系,而风格、规范很难说好还是不好。
但我觉得好的代码,一定是能让别人阅读起来有一种爽心悦目的感觉。
1. 开发规范
不管是团队协作还是个人独立开发,遵循一定的开发规范都是很有必要的。就团队协作来说,可能每个人的风格迥然不同,如果没有规范的约束的话,团队之间的协作会大打折扣的。而就个人独立开发来说,很难说一年后的你回头看今天自己写的代码是满意的。
js
开发规范
一般前端开发的主要工作都要 js
部分,所以一般前端开发规范都是对 js
而言的。
认可度比较高的有:
css
开发规范
认可度比较高的有:
2. 使用工具检查、自动矫正与优化
尽管有规范可循,但其实开发的时候并不知道自己的代码是否是符合规范的,所以就需要工具来检查与矫正代码。
2.1 检查与自动矫正
认可度比较高的有:
- eslint:检查 js 语法(包括 jsx 语法),然后最大程度的矫正不符合规范的代码;
- stylelint:检查 css 语法(包括 less, scss 语法),然后最大程度的矫正不符合规范的代码。
安装
目录文件
|-- root/ // 项目根目录 |-- 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 转码器 for eslint "eslint-config-airbnb": "^17.0.0", // airbnb eslint 规则 "eslint-config-prettier": "^2.9.0", // prettier eslint 规则 "eslint-plugin-babel": "^5.1.0", // eslint 的 babel 转码插件 "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 规则 "stylelint-config-standard": "^18.2.0" // standard stylelint 规则 },
.eslintrc
{ "parser": "babel-eslint", "extends": ["airbnb", "prettier"], "env": { "browser": true, "node": true, "es6": true, "mocha": true, "jest": true, "jasmine": true }, "rules": { ... // 更多自己定义的规则 } }
.stylelintrc
{ "extends": ["stylelint-config-standard", "stylelint-config-prettier"], "rules": { ... // 更多自己定义的规则 } }
运行命令
npm run eslint // 检查项目中的 js(jsx) 语法 npm run eslint:fix // 检查项目中的 js(jsx) 语法,并最大程度的矫正 npm run stylelint // 检查项目中的 css(less,scss) 语法 npm run stylelint:fix // 检查项目中的 css(less,scss) 语法,并最大程度的矫正
2.2 代码优化
eslint 与 stylelint 在对代码做检查和自动矫正时,只保证代码的语法是符合一定的规范,并不对代码的格式做任何优化,所以,自动矫正后的代码可能格式会不太好,阅读性不太高。
所以,一般会在对代码检查与自动矫正之后做代码格式优化。
使用比较多的:prettier.
安装
目录文件
|-- root/ // 项目根目录 |-- package.json |-- .prettierrc // prettier 配置文件 |-- .prettierignore // prettier 忽略配置,类似 .gitignore
package.json
"scripts": { // 对 js,jsx,css,less,md,json 文件进行优化 "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" } } ] }
运行命令
npm run prettier
2.3 强制对代码进行检查、自动矫正与优化
尽管定好了规范与工具命令,但开发人员完全可以跳过这些步骤,这尤其是在团队开发中很难强制其他组员会去做代码检查、自动矫正与优化。
所以,使用工具强制开发人员对代码进行检查、自动矫正与优化,就显得很有必要了。
使用比较多的:
- husky:对 git 进行 hook,可以在 git 操作之前做一些操作;
- lint-staged:对当前 git 提交的代码进行一些操作。
package.json
"scripts": { "precommit": "npm run lint-staged", // 在 git 提交之前运行 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 文件进行 eslint 检查、自动矫正 "prettier --write", // 然后 使用 prettier 进行代码格式优化 "git add" // 最后重新添加 ], "**/*.{css,less}": [ "stylelint --fix", // 对 css,less 文件进行 stylelint 检查、自动矫正 "prettier --write", // 然后 使用 prettier 进行代码格式优化 "git add" // 最后重新添加 ], "**/*.{md,json}": [ "prettier --write", // 使用 prettier 进行代码格式优化 "git add" // 最后重新添加 ] },
这样,在每次 git commit
之前,都会对将要提交的文件进行检查、自动矫正与优化,如果其中有一项发生错误,本次提交都会失败。然后开发人员调整代码之后再进行提交,只有每项任务都是没问题的,才能提交成功。
这样,便可使每个开发人员都是按照一定的规范与风格写代码的。
3. 编辑器配置:.editorconfig
有了规范,也加上了工具做自动化代码检查、矫正与优化,但还有一点需要提及一下,就是在团队协作中,每个开发人员可能使用的编辑器不一样,编辑器的配置也不一样,这就导致工具在做格式优化的时候,不同的开发人员中输出的代码不一样。
这就需要配置文件 .editorconfig
去统一每个开发人员的编辑器配置。
目录文件
|-- root/ // 项目根目录 |-- .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 文件不去掉每行末尾的空格
更多的编辑器配置规则,可以查看 http://editorconfig.org.
4. 业务逻辑优化
上面提到的这些只是风格、规范、语法上的优化,但对编码质量的评估更多的是在业务逻辑具体实现这一块。
一般来说,业务逻辑实现的优化离不开下面几个方向:
模块化:
- js 的模块化已经很成熟了,目前使用最多的是
commonjs
模块化规范和es6
模块; - css 的模块化也一直在探索中,之前也专门写了一篇 CSS 模块化,可以参考下;
- html 没有模块化,但是可以将一个很长的 html 文件进行分块,参考 html-loader。
- js 的模块化已经很成熟了,目前使用最多的是
- 组件化:当项目变大、变多,很多公共的代码需要复用或者跨项目使用的时候,组件化就变得很必要了,之前也专门写了一篇 组件化,可以参考下;
- 逻辑解耦:把一个复杂的逻辑,分割成多个子逻辑,然后将子逻辑串起来,或者把多个交叉逻辑的公共部分拆出来,然后再挨个串起来;
- 功能分块:细化一个一个的功能为单独的模块。
5. 逻辑解耦
逻辑解耦就是把一个复杂的逻辑,分割成多个子逻辑,或者把多个交叉逻辑的公共部分拆成单个逻辑。这样做的目的是降低应用的复杂度,更据阅读性。
比如,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. 功能分块
细化功能为单独的模块也是提升代码质量的一个方式。
比如,将一个文件拆成多个文件(颗粒化):
# 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 => { // 渲染页面 ... // 初始化组件 ... // 装载数据 ... // 绑定模型 ... // ... ... }
一般这种情况下,一个功能代码块就可能会很长,200 行都有可能,这个时候就需要将其分割成多个小代码块:
const renderPages = res => { ... }; const initComponents = res => { ... }; const fillData = res => { ... }; const bindModels = res => { ... }; ... $.getJSON(url, data, res => { // 渲染页面 renderPages(); // 初始化组件 initComponents(); // 装载数据 fillData() // 绑定模型 bindModels(); // ... ... }
7. 多阅读
最后,也是最重要的,就是多阅读别人优秀的代码,阅读永远是获取知识最重要的途径,没有之一。
8. 后续
更多博客,查看 https://github.com/senntyou/blogs
版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)