第27期如何保障前端项目的代码质量

Posted 前端指南

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第27期如何保障前端项目的代码质量相关的知识,希望对你有一定的参考价值。

作者| 任侠
本文由任侠授权进行分享,文章略长,请耐心阅读


对于中大型前端项目,项目规范与代码质量尤为重要。当功能需求变更或需要重构时,随心所欲的(糟糕的)代码可能带来比重新开发还麻烦的问题。


1.前端项目代码中常见的问题


凌乱的书写风格,阅读体验差


这个问题不用作过多阐述,想必接手过他人代码的同学,多少都有些体会。简单来说,太过随意的代码会让强迫症患者难以容忍,难以阅读理解的代码有时甚至不如推倒重来。


低质量的编码,bug 不断


什么样的代码是低质量或高质量的?好的代码可能会让你如读小说一般被吸引,糟糕的代码会让你看一眼就不想继续、甚至看半天而不知所云。


有人可能认为初级程序员才会有这种问题,其实不然,一些工作经验两三年的同学写的代码依然如此。对于一些个人自学意识不够积极、没有团队规范性指引的同学,很容易习惯成“学习半年、然后重复三年无长进”的情况。


拿出来你可能不太愿意相信,下面这些例子即来源于真实项目。你能尽可能地找出其中存在的各种问题吗?


图1


【第27期】如何保障前端项目的代码质量

图2


【第27期】如何保障前端项目的代码质量

图3


【第27期】如何保障前端项目的代码质量

图4


【第27期】如何保障前端项目的代码质量

图5


【第27期】如何保障前端项目的代码质量

图6


图7


以上只是截取的一些很简短的列子,那么涉及大块复杂逻辑的地方会是怎样的,试试发挥一下你的想象力。


1.3 功能不分离,逻辑糅合,难以阅读和理解

这种问题其实是非常普遍的。一个函数几百行、一个文件数千行、一个类几十个方法、方法参数定义随意、没有任何注释、方法与变量命名无明确的语义、数据修改与变更穿插在各种方法中等等。 这样的编码方式,你要去理解它的逻辑往往真的很难,一般只能一块块一行行的去做阅读理解(可能还会开启边看边骂娘模式)。


这主要原因在于开发者个人的基础知识能力、编码经验和意识等的不足。

其实针对这种情况,常见的开源的编码规范都会有所提及。我的建议是这些同学应该好好温习一下面向对象编程、函数式编程、数据结构、常见设计模式,看一看各种开源的编码规范并尝试去真正的理解它们。当你回顾一个月前的代码时,发现可以改进或重构使得编码逻辑更为简洁清晰,说明你是在成长与进步的。


经常看到各种社区中都会有同学问这类问题:新项目正在选型,Vue.js、React、Angular 三大框架哪个合适?其实团队开发成员对这些都比较有经验,哪种都可以;如果团队成员前端开发经验大都不是太丰富或人员不够稳定,选择 Vue.js 最适合,为什么?因为它更简单简洁,容易上手。Vue.js 通过 prop、data、computed、method、watch 等各种钩子,一定程度上限定了编码方式与风格,使得初级开发者写出来的代码也不会太难看,这也是它越来越受社区推崇的原因之一。


2 保障前端项目编码质量的方法


如何保障前端项目的编码质量呢?依我看来可以从这几个角度考虑:制定编码规范、开发工作流 lint 风格强制检查、定期 Code Review、单元测试。


制定项目编码规范


团队协作项目中,编码规范尤为重要。对于初级程序员,因经验欠缺,编码规范的要求可以避免许多低级问题的产生;对于多人团队来说,风格一致的编码约定,在协作开发、代码移交等时,可以在很大程度上降低风险和成本。

那么编码规范应当如何制定?


没有最好的风格,只有团队认同的一致性约定。一般来说可以由团队负责人牵头制定,成员提意见补充,最后落地成团队规范并严格执行。业界有很多优秀前端团队开源的规范可供参考。如:


  • 参考 Angular 编码风格指南 | 中文

  • 参考 Airbnb javascript Style Guide | 中文参考

  • 参考 Code Guide by @imweb

  • 参考 fex-team/styleguide

  • 参考 es6-code-style-guide

  • 参考 idiomatic.js - 书写具备一致风格、通俗易懂 JavaScript 的原则

  • 参考 JSDoc 中文文档

  • 参考 es6 编程风格

  • 参考 Vue.js 风格指南

  • 参考 Vue.js 组件编码规范


学习编码规范约定是有必要的,但你能在看完后并真正的理解它们吗?


在开发工作流中配置 lint 风格检查与修正


在开发工作流中引入工具辅助,可以强制性地实现编码书写和提交过程中的 lint 校验。可以怎么做?条条大道通罗马,下面以当前流行的 Git Hook 方案举例供参考。


开发编辑器及 lint 工具配置

我们在项目中配置 TSLint 插件以校验 typeScript;配置 styleLint 插件以校验 CSS/LESS。

我们约定团队开发均采用 vscode 编辑器,并至少安装以下插件辅助开发:

  • TSLint

  • stylelint

  • Document This

  • EditorConfig for VS Code

  • Prettier - Code formatter

  • Debugger for Chrome


添加 .editorconfig 文件

由于不同开发者可能使用的编辑器不同,但各种编辑器基本都支持 .editorconfig, 故每个项目都应当包含 .editorconfig,用来统一配置编辑器的换行、缩进存储格式。

配置参考:

# http://editorconfig.orgroot = true[*]
indent_style = space                    # 输入的 tab 都用空格代替indent_size = 2                         # 一个 tab 用 2 个空格代替# end_of_line = lf                      # 换行符使用 unix 的换行符 \ncharset = utf-8                         # 字符编码 utf-8trim_trailing_whitespace = true         # 去掉每行末尾的空格insert_final_newline = true             # 每个文件末尾都加一个空行[*.md]
trim_trailing_whitespace = false        # .md 文件不去掉每行末尾的空格复制代码


配置 Git Hook 强制执行编码风格检测与修正

借助 Git Hook,可以在提交代码时执行风格检测与修正,当存在无法通过的内容时,提交会被 block,从而实现编码规范的强制性执行。

可以利用以下几个工具来实现这个流程:


  • husky 它会安装一系列 git hook 到项目的 .git/hook 目录中,这些钩子可以检测 package.json 中的 scripts 脚本命令配置,并在代码提交时执行它(我们这里利用 pre-commit 钩子)

  • lint-staged 可以取得所有被提交的文件并依次执行配置好的任务命令

  • styleLint/TSLint/ESlint 各种 lint 校验工具,可以配置到 lint-staged 的任务中

  • prettier 配置到 lint-staged 的任务中,可以实现修正可自动格式化的编码风格


package.json 中的相关配置信息参考:

{  "scripts": {    "precommit": "lint-staged",
  },  "lint-staged": {    "*.ts": [      "tslint --fix",      "prettier --parser typescript --single-quote --print-width 120 --write",      "git add"
    ],    "*.less": [      "stylelint --fix",      "prettier --parser less --print-width 120 --write",      "git add"
    ]
  },  "devDependencies": {    "husky": "^0.14.3",    "prettier": "^1.13.5",    "prettier-stylelint": "^0.4.2",    "stylelint-config-standard": "^18.2.0",    "stylelint": "^9.4.0",    "stylelint-config-prettier": "^4.0.0"
  }
}复制代码


.prettierrc 配置文件参考:

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


.stylelintrc 配置配置参考:

{
  "extends": [
    "stylelint-config-prettier",
    "stylelint-config-standard",
    "./node_modules/prettier-stylelint/config.js"
  ],
  "rules": {
    // 定义一些适合团队约定的规则
  }
}复制代码


通过以上配置,当代码提交时,会在 pre-commit 阶段执行 .git/hook/precommit 钩子,该钩子会查找并执行 scrpits 中的 precommit 命令,于是 lint-staged 定义的任务会被逐个执行。这套方案也是当前比较流行的做法,在很多开源项目中都有所应用。


拓展阅读:

  • 用 husky 和 lint-staged 构建超溜的代码检查工作流

  • 怎样提升代码质量

  • 重构 - 代码优化技巧



执行 Code Review


编码规范与 lint 检查只能让大家的编码风格保持一致性,却无法避免低质量输出的问题。而这种问题对团队和产品来说往往却是致命的。


低质量的代码不仅仅只是会制造各种低级 bug,让测试同学测到没脾气,对产品来说,可能很小的需求改动却需要代码有巨大的变动,导致产品迭代周期被潜在地延长。另外,当大家的精力总是聚焦于需求开发和 bug 修复时,产品设计的细节就顾不了那么多了(别跟我说什么精益求精,赶时间解决完 bug 就烧香拜佛了),这对产品体验来说也是很要命的。


什么样的代码是好的,什么样的代码是不好的?这来源于知识的学习运用和开发经验的日积月累。低质量的编码说到底还是经验不同、水平存在差异。对于个人来说要通过不断的学习积累自我提升,对于团队来说进行 Code Review 评审是有必要的。


那么 Code Review 应当如何进行?


Code Review 的形式可以多种多样。如 GitHub 上许多流行项目采用 PR(Pull Request) 工作流的方式,一个 PR 至少经过三人次 review 通过才能合入,这能从流程上较好地保障项目代码质量。在有的开发团队或企业,会引入 gerrit 这种代码审核平台,过程与此大致相似。但对许多快速迭代的业务产品开发团队来说,这种需要多人评审通过的模式都不太适合:人力有限、时间紧迫、顾不了那么多了,于是即使 gerrit 也流于形式,编码质量只能落到开发人员个人的肩膀上。


相比较而言,定期进行小组讨论形式,问题的提出可以得到快速反馈和总结,这会让大家更有动力一些。


一般来说团队内有新人入职,基本的 Code Review 是有必要的,这时候编码规范与风格是 review 的重点。当大家对常见的基本问题都有了比较一致且明确的认识后,探讨交流学习则会逐渐成为 Code Review 的主要内容。


对于内部交流氛围浓厚的团队,可以鼓励成员之间互相审阅提交的编码。对大多数团队来说,可以这么来做:主要负责人以抽查浏览的形式快速审阅成员提交的代码,发现有问题的地方提出并打回改进(问题较多的同学的代码应重点关注);团队定期(可以是每周)以例会讨论的形式,对一周提交的代码进行抽样和总结式评审,学习好的编码方式、探讨不好的编码的理由,甚至进而沉淀出适合团队的编码约定。


另外注意一点,Review 过程的操作方式和表达用语非常重要,应当是轻松的沟通交流学习的方式,不要把 Code Review 执行成了批判会。


拓展阅读:

  • Code Review 都是怎么做的?遇到过哪些问题?

  • 【译】如何用人类的方式进行 Code Review


编写单元测试


前端项目写单元测试,对很多人来说是不愿意的,因为编写过程太过复杂。但基本的单元测试是可以写的,公共方法和组件的修改可能会为某些调用模块制造潜在的 BUG,良好的单元测试可以在出现问题时快速反馈出来。

我们当前对项目单元测试的基本要求是这样的:


  • 公共方法、服务类必须写单元测试

  • 公共组件应当书写单元测试,应尽可能覆盖到各种功能点

  • 业务组件可以书写简单的测试

  • 注意测试代码质量,应当反复通过测试覆盖率评估和改进测试代码


Vue.js/React/Angular 三大框架都有完善的单元测试实现体系,在项目中引入单元测试的成本并不高,高的是测试代码编写的过程。在某些情况下我认为这种“高成本”是值得的。另外需注意,单元测试的执行一定要与 CI 集成,才能真正发挥它实时性反馈问题的作用。


其他


使用静态检查语言 TypeScript / Flow

JavaScript 是一种语法简单使用灵活的弱数据类型语言,而正是这种过于灵活的特性,使得开发者能够任性地书写,但任性是需要成本和代价的。


有时会看到一些后端同学会说,前端看上去也没那么难嘛,我只学了一天就开始上手撸代码了。他们或许说的没错,但是有经验的前端同学去看一下他们此时产出的代码,往往都会表示不忍直视。许多前端开发的同学并非计算机相关专业出身,没有太多相关的基础理论知识作为背景,刚开始干活时在代码输出上“随心所欲任意妄为”的情况更为普遍。


TypeScript 和 Flow 近两年来越来越火热,几乎当前流行的前端开源产品都在转向使用它们,这足以体现它们存在的重要价值。静态检查语言在编码阶段即可检测并提示出潜在的类型引用风险,可以在很大程度上避免许多因粗心、误用带来的逻辑 bug。良好的类型定义会使得项目模块逻辑结构更为清晰可控。借助编辑器强大的类型提示功能,代码编写甚至无需看详细文档即可快速了解用法。特别是中大型的复杂项目,选用它们绝对是利大于弊。


  • TypeScript TypeScript Github

  • Flow Flow Github


构建页面埋点统计平台


对于产品质量而言,监控体系是非常重要的一部分。对于前端来说,可以通过设计网站埋点统计平台来收集页面信息,如脚本报错、页面性能卡顿等问题,基于统计信息回溯分析问题根源,进而进行问题修复和代码改进。当然统计数据的作用绝不止这些,这里不作过多的扩展讲述。


拓展阅读:

  • 教你如何打造出一个前端可视化监控系统

  • 基于指令和混合的前端通用埋点方案

  • (MZ)数据平台网站埋点统计实现原理与应用[PPT]

  • badjs-report -- 前端日志上报与JS异常监控

  • sentry - cross-platform application monitoring, with a focus on error reporting


3相关参考


关于前端编码质量,你有哪些经验体会呢?欢迎来一起探讨交流。


  • Angular 编码风格指南 中文

  • Airbnb JavaScript Style Guide 中文参考

  • Code Guide by @imweb

  • fex-team/styleguide

  • es6-code-style-guide

  • idiomatic.js - 书写具备一致风格、通俗易懂 JavaScript 的原则

  • JSDoc 中文文档

  • es6 编程风格

  • Vue.js 风格指南

  • Vue.js 组件编码规范

  • 用 husky 和 lint-staged 构建超溜的代码检查工作流

  • 怎样提升代码质量

  • 重构 - 代码优化技巧

  • Code Review 都是怎么做的?遇到过哪些问题?

  • 【译】如何用人类的方式进行 Code Review

  • TypeScript | TypeScript Github

  • Flow | Flow Github

  • 教你如何打造出一个前端可视化监控系统

  • 基于指令和混合的前端通用埋点方案

  • (MZ)数据平台网站埋点统计实现原理与应用[PPT]

  • badjs-report -- 前端日志上报与JS异常监控

  • sentry - cross-platform application monitoring, with a focus on error reporting

  • lzw.me/a/fed-code-…



往期精彩回顾:







以上是关于第27期如何保障前端项目的代码质量的主要内容,如果未能解决你的问题,请参考以下文章

前端项目代码质量保障秘藉

前端代码质量保障之代码review

第512期提高代码质量:如何编写函数

167期Stylelint 在提升企业微信 CSS 代码质量上的实践

如何提高UI自动化测试的质量

第717期gulp & webpack整合,鱼与熊掌我都要!