<audio id="audio" title="16丨代码“规范”篇用户答疑" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/82/cf/82d412f26635fb7622b3e1932660cfcf.mp3"></audio>

更到这一篇的时候，意味着专栏第一模块“代码规范”篇已经更新完毕了。在更新的时候，非常感谢同学的积极踊跃地留言，提出了很多独到的见解，也给专栏增色了许多。

今天，我来解答一下留言里的一些疑问。其实有很多问题，我们已经在留言区里讨论了。这里，我们就挑选一些还没有解决掉的问题，深入讨论一下。

@大於一：回归测试其实怎么测? 不懂。

答：InfoQ有一篇文章《[回归测试策略概览](https://www.infoq.cn/article/regression-testing-strategies)》我觉得写得不错。你可以找来看看。

我想要补充的一点是，要想发挥回归测试的最大作用，要把回归测试自动化。只需要简单的操作，就可以启动回归测试。比如使用“make test”命令行，或者其他集成工具的触发配置。这样，我们做的每一个更改，哪怕只是修改了一行代码，都可以跑一遍回归测试。

@一一：高质量的代码，依赖于高质量的流水线，那么问题来了，如何建立中小企业的高质量的代码流水线呢？

答：回答这个问题之前，我们先看看一些公开的数据。

Java SE的安全，是由OpenJDK的Security组负责的，评审一般通过Security-Dev@Openjdk.java.net的邮件列表进行。根据OpenJDK的登记数据，Security组总共有过13人，其中包括离职的，退休的。现存的团队，也就八九个人的样子。

这八九个人要做多少东西呢？下面是一个不完全的简要的列表：

1. Java平台安全（platform  security, Java language）
1. 密码学 （Cryptography，JCA）
1. 认证和授权（Authentication and Access Control，JAAS）
1. 安全通信（Secure Communications，JSSE/JGSS/SASL）
1. 公开密钥基础设施（Public Key Infrastructure (PKI)）

其中任何一个模块，如果没有多年的经验积累，都很难做好。如果你观察Security-Dev邮件列表，就会注意到每一个模块的话题，参与活跃的也就两三人。这就是说，如果把一个模块看作一个虚拟的团队，这个团队也就两三人而已。

我想通过这个例子告诉你，大公司的研发团队，也可以是一个小团队；团队里的成员，也不是什么都懂的。

这样的团队和中小企业的研发团队有什么区别呢？我觉得数量上的区别可能不是很大，两三人的团队，八九人的团队，中小企业的团队规模大抵也是这样的，甚至更大。质量上的差别呢？我觉得这没有可比性，你的团队不一定需要密码学的专家。能够满足产品目标的团队就是一个质量好的团队。

我们来看看我们在专栏里提到的流水线，有哪一道关卡是中小企业做不了的？其实都做得了，但是没有养成这么做事的习惯。

首先，程序员是最重要的关卡，决定着整个流水线的运转效率。专栏里有一篇文章，我们讨论了优秀的程序员是什么样的。我们要做的就是，让自己成为这样的程序员，找到这样的程序员做同事，帮助同事成为这样的程序员。建立这样的氛围确实不容易。比如，我们讨论的编写代码允许犯错误，允许反复地犯错误，这一点很多中小企业很难做到。杀一个程序员祭天，简单粗暴，还能发泄愤怒，大家都喜欢这样的方式。有时候，要求程序员有责任心，有主人翁意识，要知错就改，就是一种看起来正确无比，其实没有什么意义的做法。

在编译器这道关中，其实我们大都使用相同的编译器。区别可能在于我们对于编译器警告的处理态度。我们可以忽视编译器警告，也可以认真分析每一个编译器警告，甚至消除每一个编译器警告。这样做，谁不会花费很多时间呢？刚开始，一个程序员写的代码，可能有很多警告，然后他试图弄清楚这些警告，消除掉这些警告。通过这个过程，他成为一个更好的程序员，下一次写代码，就不会出现这么多警告了。随着他越来越清楚警告的来源和解决办法，他的程序越来越好，花的时间越来越少。如果他把所有的警告都忽视掉，无论多长时间，他都掌握不了解决这些警告的方法，无法保证代码质量。我们小时候，算1加2等于几，都要掰掰手指头。长大后，这样的计算，根本都不需要思考。每个程序员，都有掰着手指头学习的阶段。这一点，我觉得大企业和小企业，没有太大的区别。

回归测试这道关，其实就是把研发流程中的测试，规范化出来。我们写程序，都要测试，都要有测试代码。把测试代码独立出来，形成测试案例，然后每次代码变更时，把所有测试案例都跑一遍，就是回归测试了。如果回归测试通不过，就说明代码变更可能有潜在的问题，需要修改。这里面的难点，就是要坚持写测试代码。这些代码，测试人员要写，研发人员也要写。如果写测试代码是一个硬条件的话，一个公司就不能寄希望于程序员的责任心这种幻象。更有效的做法是，如果一个变更没有测试代码，就不允许提交代码。如果允许意外，程序员必须清楚地解释为什么没有测试代码。比起写个测试代码，解释起来大都是很费劲的。这个小制度的安排，就可以帮助我们养成写测试代码的好习惯。习惯了之后，我们很快就会发现，写测试代码，使用回归测试，其实是帮助我们节省时间、减少错误的。这时候，我们一般就会喜欢上写测试代码了。这一点，我觉得大企业和小企业，没有太大的区别。

代码评审这道关，其实是误解最深的一道关。第一个误解是，公司没有牛人，没办法评审。其实，评审做重要的，就是多几双眼睛看着，防范我们个人难以避免的错误。不是说做评审的，就一定要比被评审的专业、见识多。即便是刚毕业的大学生，也能够看到我们自己无法完全克服的错误，比如说我们在文章里提到的"goto fail"错误。在OpenJDK社区，谁都可以评审，谁都可以发表不同的意见，提出改进的建议。如果评审依赖牛人，牛人就是最大的瓶颈。第二个误解是，代码评审太浪费时间，耽误功夫。代码评审，确实需要付出时间。可是这只是表象，代码评审可以减少错误，提高代码质量，减少代码返工，帮助积累经验，这些都是节省时间的。如果我们看的角度稍微大一点，就会有不同的结论。这一关的难点，就是要坚持代码评审。这同样不能依赖于我们脆弱的责任心和主人翁精神，而要依靠小制度的安排。比如没有经过评审的代码，就不能提交代码。这一点，我觉得大企业和小企业，没有太大的区别。

代码分析这道关，其实相对来说，比较简单。找到相关的工具，坚持定期检测，检查分析结果就行了。没什么玄妙的东西。这一点，我觉得大企业和小企业，也没有太大的区别。

我们该怎么把这个流水线搭建起来呢？我认为最重要的就是要启动代码评审这个环节。这个环节启动了，其他的环节，顺势就建立起来了。这个环节没有，其他环节也不能很好地执行。

1. 使用Git或者Mercurial这样成熟的版本控制工具，以及像Bugzilla，Phabricator，Jira这样的bug管理工具。
1. 找一个工具，可以生成可视化的代码变更页面。比如OpenJDK的webrev，或者像 Phabricator这样的集成工具。
1. 找到一个集中的地方，可以让所有人都看到代码变更页面，都可以方便地提意见。比如，OpenJDK使用cr.openjdk.java.net展示，使用邮件列表讨论。GitHub和Phabricator这样的集成工具也有类似展示窗口。
1. 制定小制度，没有经过评审的代码，不能提交。OpenJDK的提交，是用过检查Reviewed-by这样的提交描述字段，来自动判断的。Phabricator这样的集成工具，也有类似的强制设置。
1. 制定代码评审的通过准则，比如不规范的代码，没有通过测试的代码，以及没有测试代码的变更，不能提交。如果允许例外，提交者要解释清楚。
1. 把测试归拢起来，找一个自动化的工具，可以执行回顾测试。比如说使用“make test”命令行，就可以执行所有的回归测试。类似Phabricator这样的集成工具，也有类似的测试执行功能。
1. 定期执行代码分析，并且把分析结果记录下来，检查、分析、改进。这个分析工具可以是SpotBugs，或者其他的商业软件。
1. 把需求分析、架构设计、接口设计，也当作bug管理，纳入到评审的过程中来。
1. 改进激励标准。程序员的评价标准不要狭隘在编写了多少行代码上，还要看看参与了多少评审，发现了多少问题。
1. 鼓励内部推广软件开发经验，比如说什么样的插件可以编写规范的代码，什么样的代码容易出现安全问题，什么样的代码效率比较高。有了成熟的经验后，就总结下来，推广出去，形成团队的重要共识和财富。

这些工具用起来，各个流程衔接起来，就是一个可以运转的流水线了。随着大家越来越习惯这样的工作方式，流水线的效率就会越来越高。而且流水线本身就是一个好老师，可以促进交流，加快每个参与者的成长。当然，从无到有，去适应这个流水线需要一段时间。

如果对比大公司和小公司，也许有没有现成的流程，算是区别吧。由于丰富的开源软件以及云服务，工具本身的区别，其实很小了。

拎着一挺AK47去战斗，总不如赤手空拳、手抓子弹来得陶醉，更别提使用飞机大炮了。我们尽可以耻笑电视里的画面，“拿着手枪，算什么英雄！” 但是轮到我们自己去战斗时，最好有飞机大炮航空母舰。

@轻歌赋：想问问老师，如何在身边没有其他评审的情况下，提供一些自己检查代码逻辑bug的方法呢？而且对业务分析不熟悉，经常会出现建表少了某个字段的情况，请问老师有没有什么相对系统化的设计方面的知识可以学习呢？

答：对于业务分析，你可以参考下使用UML或者思维导图这样的工具。画画图，有助于我们加深对业务的理解，找出业务的逻辑甚至问题。我自己做需求分析的入门书籍，是《软件工程》（Roger S. Pressman或者Ian Sommerville的，我忘记自己当初学的是那一本了）和《软件需求》（Karl E. Wiegers）。

我们应该都过了面向对象设计的门槛了，有三本书，可以让我们接触优秀的设计理念和最佳时间。一本是《Unix程序设计艺术》（Eric S. Raymond）。另一本是《设计模式》（Erich Gamma， Richard Helm, Ralph Johnson, John Vlissides）。学设计模式，千万不要固化了思维，所以我建议一定要仔细阅读每一个设计模式的“意图”“动机”“适用性”这几方面的内容。另外一本书，就是《Effective Java》（Joshua Bloch），Java程序员应该人手一本，像是使用字典一样使用这本书，先看一遍，然后时刻备查。

以上就是答疑篇的内容。从下一篇文章起，我们就要开始“代码经济篇”的学习了。如果你觉得这篇文章对你有所帮助，欢迎点击“请朋友读”，把这篇文章分享给你的朋友或者同事。


