最近发现之前写过的很多项目,不管是 python/go/cpp 的,最终回看起来代码都变的很难看,尤其是多人合作的时候。
这是一个很头疼的问题。自己平时很在意这个,但是代码最终确都变成了 shit。

问题#

当一个人开发的时候,问题主要在于一个人的自律性不够强,不管是代码注释等都是随意写的,即使偶尔意识到了问题,但也难以保证能一直坚持下去。
而当人多的时候,问题经常处在多人风格的不同上。如果没有工具来强制大家遵守一定的规则,那么大家每个人自己的风格放在一起的时候,就成了垃圾代码。
避免代码变成 shit 的唯一方法,就是让大家写的代码看起来都一个样。而这个工作除了由开发人员的 Code Review 之外,还需要工具来约束。

解决方法#

CI/CD#

最开始接触 CI/CD,我只是认为它主要是用于部署方面的一个工具。现在发现,它对于代码质量的改进也是意义巨大的。所有代码通用规范上的约束,静态分析,复杂度分析等都可以通过自动化工具来执行。
一方面,我们可以组合尽可能多的代码静态分析工具,来约束提交代码的错误,提供代码改进的建议,形成统一的代码风格。另一方面,最于 Code Review 来说,不再需要关注基本的代码风格以及基础部分,而只用关注于具体的业务以及代码架构层面的问题。

静态分析#

Python 这样的代码,在多人合作的大型项目上,如果没有非常严格的代码约束,最终出来的项目时非常难以维护的。可能经常部署出来的代码连跑都跑不起来。相对来说,静态类型语言在这方面的优势是巨大的,编译器在编译代码阶段能发现大多数比较明显的问题,最终线上的问题一般都是需要人来参与分析的。

代码的静态分析是一个非常古老但是重视程度不够的技术。静态类型语言的代码分析技术能够极大地减少代码中可能存在的 bug,并给出很多的建议。以 Golang 为例,目前已经有几十款静态分析工具。
而像golangci-lint这样的工具,可以将多种分析工具结合起来,在各个层面给出代码改进的建议。比如:

  1. 代码的简化写法
  2. 可能的 bug
  3. Dead Code
  4. 未使用的或者被覆盖的变量

SonarQube 其实是类似的产品,只不过是 Client/Server 的架构,提供了诸如复杂度分析,单元测试覆盖率等指标。良好的 UI,以及插件式的架构,与普通的 cli 工具结合起来之后,对于代码质量的提高是非常有益的。

总之,工具能处理的事情越多,人的精力就更多的能去关注更上的层面和业务层面。

Code Review#

Code Review 虽然成为一个共识,但真正的效率确实难以保证的。莫名其妙的改动,形式化的 approve,现有工具的局限等等问题都造成了参与的人在这方面的低效率。所以总是需要有各种规范来指导人们如何进行 Code Review。一般来讲,我们可以将代码的改动拆分为三个问题

  1. Why? 为什么要做这个改动
  2. How? 怎么做这个改动
  3. What? 具体做了哪些改动。

这几个问题,工具能参与的只是What的一部分。其他的部分都需要人来 review。一般的 Code Review 提交的模板也都要求提交 PR 的人尽量说清楚 Why,通过文档 link 或者文字等形式。具体的 How 以及 What,则需要具体的人来参与 review。

单元测试#

曾经我对于单元测试是非常反感的,现在的仍然觉得它的作用有限,只是我们没有其他选择,只能继续用它。
它的作用主要在于:当我们添加代码时,能保证我们的代码不 break 已有的逻辑。为了这个目标,付出的代码是巨大的,庞大的单元测试框架以及体系,高昂的维护成本,以及可能对现有代码的侵入性,换来的是一种非常被动的 protection。

当然单元测试对于代码的反向的结构优化也是有意义的。在让代码结构变得可单元测试的过程中,代码也变得更加易维护以及模块化。希望以后有更简单的方式来达成这个目的而不用承受目前单元测试框架的沉重负担。

人的因素#

上面说了那么多,其实都只是为了保证代码的烂有一个下限,但代码仍然可能是 shit。问题的核心,不是技术,而是政治学(说的通俗点的就是管理问题。)
代码质量好的项目,这么几十年来,经验告诉我们,只有两种: 仁慈的独裁者(比如 Guido)和骂人的独裁者(比如 Linux)。这样最终多人的协作问题最终就变成了一个 leader 自身的品味问题。品味好的人虽然很少,但不是没有。

Linux 的脾气以及 RMS 的偏执,初看起来都很不近人情,但他们都在维护问题的核心:代码的质量以及软件的自由,任何其他的因素不管听起来多么冠冕堂皇,都是次要的,不应凌驾于核心之上。

这很像民主制度一样面临的问题。它防止了最坏的恶,但因为没法保证每个人都是精英,所以在协作的产出上总是低效和质量差的。而专制制度在牺牲了大多数的自由之后,如果有一个良好的领导者,则是目前已知的最有效的政治制度。毕竟,结果最重要。