维护百万级别JavaScript代码量的项目是一种什么样的体验?

1,881 阅读3分钟
原文链接: www.zhihu.com

2016 年我在 Facebook 的 React team 实习,当时做的项目之一是 deprecate `React.createClass` 这个 API 在 FB 内部的使用。我用几周时间写了一个 codemod (reactjs/react-codemod) 自动重构了 15000 个左右的 React 文件,在开发这个 codemod 的过程中也读了很多产品端的 React 代码。从我的角度来看,学到的事情大概有如下几条:


1. 好的工程代码是自律 (disciplined) 的。

写这个 codemod 的过程中其实没有遇到什么困难。最大的原因大概是公司里的 React 代码长得都差不多。这其实是一件挺惊讶的事情:不同产品间要解决的问题、以及不同工程师的背景其实有很大的差别。但我在这些代码中并没有见到**过于**奇技淫巧的写法,如果你用高抽象一点的视角(语法树)去看,大家的代码读起来都是一个样子。甚至看久了会有些无聊。

这让重构维护的过程变得非常简单,因为我不需要花时间研究茴香豆的茴到底有几种写法。既然大家的代码都大体上如出一辙,那只要搞定常见的几种 pattern 就可以了。如果一个脚本都可以迅速理解大量的代码内容,那一个新加入 FB 的工程师也不会有什么 onboarding 的难度。

做完这个项目之后我就很少写 tricky 或者过于「聪明」的代码了。如果一段「炫酷」的代码反而会在未来增加工程成本,那它就没有很大的价值。


2. 好的工具需要更大的投资 (invest in tools)

在一个高速迭代的环境下,该怎样统一代码风格和质量呢?

高质量的静态分析工具。Flow 和 ESLint 在这个过程中帮我找到了大量错误。我很难想像在一个没有 static typing 的环境下高速迭代大量 JS 代码;在这个 UI 代码量大量增长的时代,Flow 或者 TypeScript 是必要的选择。

把代码放进 monorepo (single giant repository) 也是一个好的选择。如果各个小组都用不同的 repo 存储代码,那么每个小组都要单独花时间来设置和管理这些工具。随着时间的推移,每个 repo 的代码风格和质量也会开始分歧。用单一的工具版本和设置来管理所有代码是更好的方法。顺便推荐一下这个回答: quora.com/Why-does-Face

题外话,怎样防止一个 deprecated 的 API 出现在新的代码里?除了用 ESLint/Flow 在 commit-time 来警告之外……如果你有一些脚手架或 editor template 的话,别忘了更新这些地方的使用。所以这些脚手架或 editor template 也应该统一放在 repo 里来方便更新。

做这些事情的目的都是为了保证整个代码库的风格和质量能够得到最大的统一。有了这个指导思想,所有会导致代码 diverge 的行为都应该在早期被扑杀。比如如果你有三四个不同的 React 版本共存在代码库中,那无论工具还是工程师都会面临很头疼的问题。

还有一些有时间再来补充。


3. 高质量的 Code Review 非常重要

这个大概不需要解释了。严格的 reviewer/tech lead 们是工程团队里最重要的资产之一。不过集成好的工具到 CI 和 code review 是相辅相成的关系:静态分析工具可以抓到很多人们不容易看到的错误,同时我们也应该花时间改进这些工具来 programmatically 帮助大家写更好的代码。