牺牲架构
2014年10月20日
你坐在会议室里,思考着你的团队过去几年一直在开发的代码。你已经决定,现在你能做的最好的事情就是扔掉所有这些代码,并基于全新的架构重建。你对那段注定要被抛弃的代码、你花费在它上面的时间以及你过去做出的所有决定有什么感受?
对于许多人来说,扔掉一个代码库是失败的标志,这可能是可以理解的,因为软件开发的本质是探索性的,但仍然是失败。
但通常情况下,你现在能写的最好的代码是你几年后会丢弃的代码。
我们通常认为优秀的代码是长寿的软件。我正在用一个可以追溯到 1980 年代的编辑器写这篇文章。关于软件架构的许多思考都是如何促进这种长寿。然而,成功也可以建立在早已被发送到/dev/null
的代码之上。
以 eBay 的故事为例,它是网络上最成功的几家大型企业之一。它始于 1995 年周末编写的一组 perl 脚本。1997 年,它被完全拆除,并用用 C++ 编写的系统替换,该系统建立在当时的 Windows 工具之上。然后在 2002 年,应用程序再次用 Java 重写。这些早期版本是错误的吗,因为它们被替换了?当然不是。eBay 是迄今为止网络上最成功的企业之一,但它的大部分成功都是建立在 90 年代被丢弃的软件基础上的。与许多成功的网站一样,eBay 经历了指数级增长——而指数级增长对架构决策并不友好。支持 1996 年 eBay 的架构不会是支持 2006 年 eBay 的正确架构。1996 年的架构无法处理 2006 年的负载,但 2006 年的版本对于 1996 年的需求来说过于复杂,无法构建、维护和演化。
事实上,这条准则可以融入组织的工作方式。在 Google,明确的规则是为当前需求的十倍设计一个系统,这意味着如果需求超过一个数量级,那么从头开始抛弃和替换通常更好[1]。子系统通常每隔几年就会被重新设计和抛弃。
事实上,人们经常看到有人进入一个成熟的代码库,贬低它缺乏性能或可扩展性。但在软件系统的早期阶段,你往往不太确定它真正需要做什么,因此,更重要的是将更多精力放在改变功能的灵活性上,而不是性能或可用性。之后,随着用户数量的增加,你需要改变优先级,但让太多用户使用一个性能不佳的代码库通常比反过来更好。Jeff Atwood 创造了“性能也是一种功能”这个词,有些人认为性能始终是第一优先级。但任何功能都是你必须选择的东西,而不是其他功能。这并不是说你应该忽略性能之类的东西——软件的速度和可靠性如果太低,可能会毁掉一个企业——但团队必须在其他需求之间做出艰难的权衡。这些通常更多是商业决策,而不是技术决策。
那么,故意选择牺牲架构意味着什么呢?本质上,这意味着现在接受,在几年后,你(希望)需要抛弃你目前正在构建的东西。这可能意味着接受你正在构建的东西的跨功能需求的限制。这可能意味着现在考虑一些可以使将来更容易替换的东西——软件设计师很少考虑如何设计他们的作品以支持其优雅的替换。这也意味着要认识到,在相对较短的时间内就被抛弃的软件仍然可以提供很多价值。
知道你的架构是牺牲性的并不意味着放弃软件的内部质量。通常,牺牲内部质量会比替换时间更快地咬你,除非你已经在着手退休代码库。良好的模块化是健康代码库的重要组成部分,模块化通常在替换系统时会有很大帮助。事实上,对系统早期版本最好的做法之一是探索最佳模块化结构,以便你可以在替换时利用这些知识。虽然在系统早期阶段牺牲整个系统是合理的,但随着系统的增长,牺牲单个模块更有效——只有在你有良好的模块边界时才能做到这一点。
在处理这个问题时,很容易被忽视的一件事是会计。是的,真的——我们遇到过一些情况,人们不愿替换一个明显不可行的系统,因为他们正在摊销代码库。这在大型企业中更有可能成为问题,但如果你生活在这个世界,不要忘记检查它。
你也可以将这个原则应用于现有系统中的功能。如果你正在构建一个新功能,明智的做法是让它只对一部分用户可用,这样你就可以获得关于它是否是一个好主意的反馈。为此,你最初可能以牺牲的方式构建它,这样你就不会在你不值得完全部署的功能上投入全部精力。
模块化可替换性是支持微服务架构的主要论据,但我对将其推荐用于牺牲架构持谨慎态度。微服务意味着分布式和异步,这两者都是复杂性的助推器。我已经遇到过几个项目,它们在没有真正需要的情况下选择了微服务路径——结果严重减慢了它们的特性管道。因此,单体通常是一个很好的牺牲架构,微服务可以在以后引入,以逐步将其拆分。
编写牺牲架构的团队是决定何时牺牲它的团队。这与一个新团队进来,讨厌现有的代码,并希望重写它不同。讨厌自己没有写的代码很容易,而且没有了解编写它的背景。有意识地牺牲自己的代码是一种非常不同的动态,知道你将要牺牲你即将编写的代码是对此的一种有用的变体。
致谢
与 Randy Shoup 的对话鼓励并帮助我形成了这篇文章,特别是描述了 eBay 的历史(以及 Google 的一些类似故事)。Jonny Leroy 指出了会计问题。Keif Morris、Jason Yip、Mahendra Kariya、Jessica Kerr、Rahul Jain、Andrew Kiellor、Fabio Pereira、Pramod Sadalage、Jen Smith、Charles Haynes、Scott Robinson 和 Paul Hammant 提供了有用的评论。
注释
1: 就像 Jeff Dean 所说,“为大约 10 倍的增长设计,但在大约 100 倍之前计划重写”。