Software Engineering at Google 笔记(一)

这个是这本书的读书笔记,这本书总共有四个部分。

第一部分只有一章,所以可以水一篇,开心。

第一部分:论题

什么是软件工程

软件工程是随着时间的推移不停地对代码进行集成(Programming integrated over time),这本书将软件项目分成两种,一种是 programming,一种是 software engineering,具体的区别:

  • programming 指短期任务,比如一次性的脚本,一次性的算法题目,学校里的项目等等;一种是 software enginnering,要考虑你的项目要长期存活,所以要认真地考虑“时间”这个要素对软件本身的影响。
  • SE 核心要考虑的是项目的能力,即修改的能力、升级的能力等等,即使你不去做变动,也应该有这些能力。programming 不需要考虑这些。
  • programming 一般都是一些单人任务,而 software engineering 是团队作战。
  • SE 要考虑项目的可持续性,比如各种重复劳动(repeated work)的可扩展(scale)问题,不能让你的项目的开发维护人员随着请求数/用户数增长而线性增长。
  • 如果有一些影响未来项目扩展的决定,这些决定的原因应该被记录下来,比如写在文档里,这些都是未来要解决的技术债。

Google 上新项目,默认这些项目都会存活十年以上,所以一般也会按照这个持续时间进行相关的设计。

有很多工作十年的老码农,从来没设计过存活一年~两年以上的系统。存活时间很长的系统,需要考虑升级的便利性,有些公司可能在一些依赖项的升级的时候吃了大亏(比如某司的 mysql 升级大故障),得出我们再也不升级的结论,但这样的决定会让你陷入未来的安全漏洞无法修复,性能提升无法享受的尴尬境地。

海拉姆定律(Hyrum's rule),人们会依赖所有你的 API 的可被观测到的特性,即使这些特性不是你文档里承诺的特性。这里有个很好的例子,程序员们会依赖 hash table 的输出顺序,显然这样是不应该的。有些语言会额外地对 hash table 的输出做随机化,但你可能就想不到会有人依赖这种随机化。只要是可能会被用户观测到的 API 的规律,都可能会被用户依赖。

在探讨扩展性时,特意提到了 build 系统的扩展性,不能让开发者把时间浪费在等待 build 上。Google 建立了自己的分布式 build 系统。

业界当前的老项目/lib 做 deprecation 的时候,一般作者是不管用户的升级的,不过 Google 会要求 inf 和原始库的开发团队专门来负责升级这件事情,并且给 Deprecation 专门做了相关的系统。各种子系统的升级问题被当成 subproblem,由升级的熟手们挨个儿解决。

基于分支开发的业界实践很普遍,不过分支开发经常会由于排队排得比较靠后导致合入主干代码时引入大量的修改,所以最后反而大家更不愿意频繁进行代码合并了,这本书也给出了解决分支研发的这种麻烦的解决方案。

在升级的时候,可能会碰到破坏了应用功能的情况,这种情况说明 CI 里的测试写的不完整,需要应用侧补全,如果碰到了这种问题,不能把锅甩给执行升级任务的团队。

Google 内部建立了问题的复盘文化,都是对事不对人。对于大家畏惧的升级,只要经常做,就不会再产生畏惧了。前面说到的 Hyrum's rule,因为经常升级,所以那些文档里没有承诺的特性如果被用户依赖了,用户也能尽快地发现。

Google 做的生产力方面的事情,除了提升效率之外,都是尽量提升开发者的体验(万恶的资本主义啊)。

在版本控制方面,不建议使用 fork,而是全局使用相同的版本,Google 自己建设了一套叫 Piper 的代码管理系统,在版本管理的章节中会有具体的说明。这本书的作者认为一致性相比 fork 的灵活性有更大的价值。在 monorepo 中,一个库的版本一定是固定在某一个版本的。

用数据驱动自己的开发与决策。

勇于承认过往的决策错误,这样的人会受人尊敬。

第一部分没什么重要内容~

Xargin

Xargin

If you don't keep moving, you'll quickly fall behind
Beijing