image from pixabay

随着业务规模扩大、团队组成变复杂,如何降低项目实施风险,降低软件复杂度变得尤为关键。 我从 Martin Flower、Joel Spolsky(软件随想录 作者) 等巨匠智慧中寻找解决复杂工程之道,其中 Code Review 是行之有效手段。 我认同 Code Review 价值也是忠实执行者。

加入蚂蚁以后,我在所接触项目中都大力推广 Code Review。 感谢团队信任和支持,目前 CR 协作进展顺利, 项目 CR 从最早不主动,到现在形成基于模块 Owner 制度 CR 和 Peer Review。 我也曾经在 3 个月内处理完成 700 多个 Pull Request,并在 PR 讨论中中都留下一些有价值讨论。 这里我将自己对 Code Review 一些理解记录下来。

这一篇先讲讲进入 Code Review 之前需要做准备工作。

评估团队成熟度

image from pixabay

不管是在一个遗留系统上推广 Code Review,还是在一个新团队推广 Code Review, 起手式不是立马挽起袖子猛干,而是应当观察一下当前所处情况是否允许自己推动这个「艰巨」任务。 最需要观察的是团队成熟度。

我将团队成熟度粗略分为草台班子、成长型团队、成熟团队。 具体衡量指标可以有成员技术储备、团队成员信任度、团队负责人对工程管控力度。 相信集团内大部分团队处于成长型、成熟型团队。 但如果考虑到生态同学一起协作,或者临时因为紧急项目凑在一起,就比较容易成为「草台班子」。

如果还停留在草台班子,那就得先在团队内形成一定共识: 包括技术共识和合作模式的共识。 技术共识需要包括:技术栈共识、好代码定义、研发流程共识等。 合作模式共识需要包括:冲突解决机制、职责范围边界、决策机制等。 如果基本共识还没有形成就仓促进入 Code Review,那就容易将一件好事变成工程师战争。

并不是所有团队、项目都适合无差别引入 Code Review。这么几种情况建议暂缓 Code Review 推广:

  • 老板和同事都不支持甚至反对
  • 业务重要性低,或者团队都是特立独行高手
  • 创新业务需要快速上线,这时候适合将这类任务分发给配合度高老团队,或者给高手单兵作战

当条件不满足时也不用气馁。先成为一个布道师吧,探索一下团队中有没有相似想法的人,了解一下他们担心点和诉求点。 相信只要条件允许,没有人会拒绝提高工程质量。

构建「好代码」共识

image from pixabay

Code Review 核心产出物是代码,如何界定代码是好是坏就至关重要。 根据 Bjarne(「C++ Programming Language」作者)、Grady Booch(「面向对象分析与设计」作者)等人定义, 总结下来好代码有这么基本特征(via「Clean Code」):

  • 正确
  • 可测试
  • 不重复
  • 少且简单
  • 可读

深思一下这些基本特征背后道理:代码是人类和机器沟通工具,好代码也要利于人类阅读和再次书写。 人比机器更犯错,机器算力在成倍增长,因此简单易维护重要度逐步增高。 这些朴素道理也正是语言从低级语言进化到高级语言驱动力, 也是近几年高级语言语言特性主打点(类型系统、格式系统、面向人类同步思想异步设计)。

但上面这几条原则太底层了,无法成为实践标准。 因此行业基于这些公理衍生了不少实践定理,我将其分为工程规约和设计范式两类。

工程规约包含语言风格规约和应用工程规约。 语言风格规约比较容易理解,开源世界提供了很多选择。硅谷大厂 Google / Facebook / Uber 等都有不少规约提供。 国内还有极具价值的「阿里巴巴 Java 开发手册」,我称之为 50331 ;) (PS:「阿里巴巴 Java 开发手册」不仅有语言风格规约、也有应用工程规约和一部分设计规约)。 这里罗列了一些常见面向语言的 Style Guide。

应用工程规约关注点则更为落地:包括依赖管理、配置管理、应用层次结构、对外服务暴露约束,数据建模,文档注释,测试管理, 甚至包含中间件使用规约。 这些规约逐步从「如何表达代码」延展到到「如何管理工程」。 这块发挥空间比较大,中大规模团队会有应用框架组这样团队。 基于应用框架对使用方式方法约束。针对具体业务使用也会给出针对性建议。 这些定理总结出来往往以轻量 Best Practice 和重量级应用框架对外输出。

这里举两个例子说明一下应用工程规约应该讲清楚哪些问题。 第一个例子 alibaba/COLA 这个项目来说,它约束了整体工程结构,并且明确的通过 Archetype 帮助(约束)用户行为。 第二个例子是 RoR / Django 这类 RoR 框架,他们使用约定大于配置方式,基于 ActiveRecord 这种模式约束了用户如何使用框架, 从 Model、Controller 到 Router,对立面则是 Spring MVC / Flask 这类框架,几乎只提供纯技术特性,不约束开发者行为。

除了阿里 Java 开发手册,这里提供三个应用工程规范供参考:

比工程规约更难定义的是设计范式,核心点是解决「如何做架构决策」。 设计范式决策过程在系统架构设计和系分设计阶段就应当完成了。 如果设计范式差异性导致代码在 Code Review 阶段出现意见不一。 要么是这个团队过于草台班子,要么是这个项目架构师/负责人在前期设计做的工作太少了。

当一个团队遵循相近设计范式,意味着他们达到了同一级别技术储 备,并形成了统一自顶向下设计打法。 在 Code Review 过程中,一些范式使用完全可以将 GoF23 / S.O.L.I.D. / DDD 这些术语概念拎出来。 相信 Commiter 和 Reviewer 可以基于业务场景快速达成一致。

方法论贴在墙上是无法解决开发中中遇到设计问题,在代码中真刀真枪干,Show me the fuck code。

Code Review 沟通协作机制

image from pixabay

除了工程规约,还有一件事情往往会被忽略,如何解决冲突? 这个冲突不是指代码 Conflict,而是面对技术方案决策时候交流讨论。

文无第一武无第二,两个秀才在一起能吵到天翻地覆面红耳赤。 技术层面 Augue 容易陷入我说我有理你说你有理局面。这种情况如何解决? 没有一个好协作机制,会倒逼 Commiter 和 Reviewer 退缩,不能充分展开讨论。 这是我们不想看见。

很多时候技术决策就是在 40% 正确性 和 60% 正确性中间选择,看中长期收益和短期收益就可能导致结论不一样。 非黑既白反而不容易有争论。想要促进快速决策,一套冲突解决机制就不可缺少。 因此一定要在事前制定一套冲突解决机制。大部分冲突解决都可以使用这么一套逻辑:数据、逻辑、民主、独裁。 当需要进行某个技术或者产品决策时候,最优先方式是用数据来量化,证明自己观点。 当数据不充分时候,可以进行逻辑归纳推衍形成结论。 当形成逻辑不能服众众说纷纭时候,可以使用民主方式进行裁决。 当民主也无法生效,就需要 Owner / 一号位力排众议,进行独裁决策了。

CodeReview 有这么几种形式,同步离线、异步离线、同步在线。 处于同步形式 CodeReview 需要尽快处理掉 PR,这时候协作机制一定要干净利索,避免大家在 PR 反反复复来来回回讨论。 如果每个 PR 都要消耗数次来回沟通,我建议将 CR 形式升级到同步在线,拉个会议立刻将事情解决。

如果在一个实现方案上真无法决策,如果不涉及原则,那我建议使用搁置争议,使用 TODO @commiter what, how, when 方式先标记意见和处理时间,先行将工程开发往下推进。

一切准备好了,谢天谢地,终于可以进入 Code Review 阶段了。 我们下篇文章再来讲进入 Code Review 阶段的事情。


原文链接: 浅谈 Code Review 之事前准备 | Log4D

3a1ff193cee606bd1e2ea554a16353ee

欢迎关注我的微信公众号:窥豹

窥豹