如何制定有效的Lint规范

在我们的项目中,lint工具总是提示着各种各样的error、warning,但是我们共同维护的代码库里依然有着各种不同风格的实现,为此很多时候我们只能不断的修改我们的lint规则,防止魔法代码的提交,但为此我们提出了更多的lint规则,到最后我们lint规则配置的繁琐而又不起作用。

在社区中,大家也越来越推崇用严格的lint规则来避免不断的浪费时间去设定、争论lint规则是否合理,但是我认为我们确实不应该花费太多的精力去争论这些没有意义的事情,但是我也不赞同使用一些较流行的严格的lint规则,在我们选择这些严格的lint规范的时候,我觉得我们是为了避免一个问题而引入了另一个问题,使用团队成员都不熟悉的lint规范,会让效率大大降低不说,还可能导致很多时候为了避免报error,而书写一些魔法代码。比如,我们如果配置了禁止在 componentDidMount 中调用 setState,那么很多时候,我们的实现都会发生报错,或者为了避免报错,把setState放在一个定时器里,这样是避免了lint报错,但是这个实现是在让人捉急。

那么我们怎么去制订一个不仅可以提高项目质量又可以保持大家效率的lint规则呢?

我觉得我们可以从以下几个方面出发:

一、禁止让人理解困难的代码

这一条算是比较好理解的,在多人/长期维护的项目中不要写一些让人摸不到头脑的“炫技”代码,比如位运算,如果我在项目中写了如下代码let a = ~~num;,这可能在一些经验丰富或者计算机基础扎实的工程师眼里根本不算什么,但是还是让很多人费解他要表达什么,但是我如果使用let a = parseInt(num);这样的话是不是就很理解了,其实大多数位运算都有更易于理解的实现,而且并不见的性能有啥损耗或者文件会增大多少字节,所以我们在lint中需要禁止一些让人理解困难的代码风格。

二、团队内推广最佳实践

我们首先需要明确一件事,那就是:lint不是万能的。所以我们怎么样让我们的项目保持一个高可维护的状态呢?我觉得我们还需要不断推广各种最佳实践,在 wiki 或设计指南里分享有用的知识,把各种最佳实践梳理出文档或工具,通过一条命令或者一键就可以生成我们需要的目录/代码结构,我觉得比我们去设置按字母序排列之类的规则有用的多,这样我们在多个项目中切换,或者多个文件中查看代码,都可以预期知道哪里会有我们需要的代码,或者哪里会出现解决问题的地方,这回让我们的效率更高,让规范在项目的每个角落落地,

三、让可修复的问题自动修复

在开发过程中你完全不需要一个工具告诉你得在这加一个空格,而且很多提示都可以通过使用 Prettier 或 Exlint —fix来修复问题,我们可以在项目/编辑器中配置自动执行来修复一些规则提示,提供效率。

四、提高代码设计能力

不论多少缩进或按字母序排列,都不能修复糟糕的设计,所以我们需要提高代码设计能力,如何行之有效的设计代码?这是一个很大的话题,不便展开来讲,在《代码大全》还有《重构——改善既有代码的设计》中已经提到了很多好的代码设计原则,而且业界比较出名的设计原则,我们可以坚持,比如:

  • 不要重复自己原则,系统的每一个功能都应该有唯一的实现。也就是说,如果多次遇到同样的问题,就应该抽象出一个共同的解决方法,不要重复开发同样的功能。
  • 你不会需要它原则,指的是你自以为有用的功能,实际上都是用不到的。
  • 单一职责原则,大到一个系统、模块的职责边界划分,小到一个类、一个方法的职责。清晰的划分类、方法的职责,保持其单一、稳定的功能,能够有效的降低日后代码越来越臃肿时带来的维护成本增加。
  • 开放封闭原则,对扩展开放,对修改关闭。也就是在程序需要进行拓展的时候,不能去修改原有的代码,实现一个热插拔的效果。
  • 最少知道原则,就是说:一个实体应当尽量少的与其他实体之间发生相互作用,使得系统功能模块相对独立。
  • 合成复用原则,简言之:要尽量使用组合/聚合关系,少用继承。

还有很多好的设计规范我们可以在开发中不断实践,去追求实现的代码模块都能达到高内聚、低耦合、易扩展、易替换的优秀设计。

五、对一些规则追问:这条规则有帮我们找到过 bug 吗

我们不应该假设每一条规则都会提供给我们有效的建议,我们应该把团队内的成员组织到一起,逐条过一遍lint规则,把没有用的规则剔除出去,让我们的规则就是风格指南,一眼就可以明白哪些实现方式或者书写格式是合理的,是行之有效让编码风格一致的。

六、组内使用统一lint的规范

我觉得这最后一条也算是团队合作比较核心的一条——使用统一的lint规范,只有大家都是用统一的lint规范,在不同的项目间切换开发的时候才能保持一致的编程体验,降低“过敏反应”!