软件架构最佳实践、企业架构模式以及系统描述的正式方法都是非常重要且实用的工具,总会有合适的场景让它们发挥作用。但在设计系统时,请从简单始、以简单终,尽可能避免一切会无谓提高复杂度的架构与正式工具。
我的职责是设计和构建大型系统。我参与重写了Uber的分布式支付系统,设计并交付了Skype on Xbox One,开源了Uber的移动架构框架RIBs。所有这些系统都进行了彻底的设计,经过多次迭代和大量讨论。然后,这些设计被记录到设计文档中,在我们开始构建之前分发出去,从而获得更多的反馈。
所有这些系统的规模都很大:有数百名开发人员在构建它们——或者以它们为基础进行构建——并且它们支撑着每天数百万人使用的系统。它们不仅仅是绿地项目。重写的支付系统就是用于替换两个已有的支付系统,有几十个系统、数十个团队在使用它们,但所有这些都没有对业务产生任何影响。重写Uber App是一个由数百名工程师同时参与的项目,他们将现有的功能移植到一个新的架构中。
让我先说些可能会让你觉得吃惊的事。首先,这些设计都没有使用任何标准的软件架构规划工具。我们没有使用UML,没有使用4+1模型,没有使用ADR,也没有使用C4和依赖关系图。我们创建了大量的图表,但是没有遵循任何严格的规则。只是使用了普通的方框和箭头,类似于这个描述信息流的图或这个概括类结构和组件之间关系的图。同一个设计文档中的两个图经常会有不同的布局,并且经常由不同的工程师添加和修改。
其次,负责设计的团队中没有架构师。没有IT架构师或企业架构师。没错,Uber和Skype/微软都没有袖手旁观的软件架构师职位。级别较高的工程师和普通工程师一样,仍然需要定期编写代码。对于所有的项目,我们都有经验丰富的工程师参与。然而,没有人专门负责架构或设计。经验丰富的开发人员确实推动了设计过程。不过,即使是最初级的成员也在设计过程中进行了输入,他们经常会挑战决策,并提供其他可供讨论的替代方案。
第三,我们实际上没有引入常见的架构模式以及常见的软件架构文献中引用的其他术语,比如Martin Fowler的架构指南。没有提到微服务、无服务器架构、应用程序边界、事件驱动架构等。其中一些在头脑风暴时确实提到过,但是,没有必要在设计文档中引用它们。
那么,我们是如何完成任务的呢?为什么我们不遵循著名的软件架构方法所建议的方法呢?
我曾与其他科技公司(Facebook、亚马逊、Netflix、谷歌)以及规模较小的初创公司的同行们讨论过这个问题。大多数团队和项目无论大小,都采用类似的设计和实现方法:
为什么我们的方法与软件架构文献中经常提到的方法不同?实际上,我们的方法与大多数架构指南在原则上并没有太大的不同。几乎所有的指南都建议从业务问题开始,概述解决方案并进行权衡:我们也是这样做的。我们没有使用许多架构师或架构书籍提倡的更复杂的工具。我们使用最直接的工具(如谷歌Docs或Office365)尽可能简单地记录设计。
我认为,在这些公司中,我们的方法的主要区别在于工程文化。自主性高和层级少是科技公司和初创企业的共同特点:对于更传统的公司来说,有时并非如此。这也是为什么这些地方使用更严格的规则进行更多的“基于常识的设计”,而不是流程驱动的设计。
我知道一些银行和汽车公司,它们的开发人员在没有得到高层架构师的批准之前,不愿做出任何架构决策,而这些架构师负责管理多个团队。这会是一个比较缓慢的过程,架构师可能会被许多请求淹没。因此,这些架构师创建了更正式的文档,希望通过更多地使用常见文献中介绍的工具使系统更清晰。这些文档还强化了自上向下的方法,因为对于非架构师工程师来说,质疑或挑战已经用正式方法记录下来的、他们不是很熟悉的决策更令人生畏。所以他们通常不会这么做。公平地说,这些公司常常希望使开发人员成为更容易替换的资源,以便他们可以在短时间内重新分配人员从事不同的项目。不同的工具在不同的环境中可以更好地发挥作用,这应该不足为奇。
系统设计的目标应该是简单。系统越简单,理解起来就越容易,就越容易发现问题,实现起来也就越简单。使用的描述语言越清晰,设计就越容易理解。避免使用团队中每个成员都不理解的术语:即时是经验最少的人也应该能够同样清楚地理解设计。
简洁的设计类似于简洁的代码:易于阅读和理解。有许多好方法可以编写出简洁的代码。然而,你很少听到有人一开始就建议将设计模式应用到你的代码中。简洁的代码从单一职责、清晰的命名和易于理解的约定开始。这些原则同样适用于简洁的架构。
那么,架构模式的作用是什么?我认为它们与编码设计模式同样有用。它们可以为你提供关于如何改进代码或架构的思路。对于编码模式,当我看到一个单例模式时,我就会注意到它;当我看到一个类仅充当执行调用的外观时,我就会扬起眉毛,深入研究。但我还没有想到“这需要一个抽象工厂模式”。事实上,在处理了大量依赖注入之后,我花了很多时间来理解这个模式的作用,并且终于在某个时刻恍然大悟——这实际上是这个模式非常常见并且非常有用的少数几个领域之一。我还得承认,虽然我花了很多时间阅读和理解GoF设计模式,但与我从其他工程师那里得到的代码反馈相比,它们对于我成为一名更好的程序员的影响要小得多。
类似地,了解常见的架构模式是一件好事:它有助于缩短与他人讨论的时间,他们和你一样理解那些模式。但是架构模式并不是我们的目标,它们也不能代替更简单的系统设计。在设计系统时,你可能会无意中应用了一个众所周知的模式:这是一件好事。后续你要参照这个方法就更容易了。但是,你最不希望看到的是使用一个或多个架构模式,把它当成一把锤子,为了用它而到处找钉子。
工程师们观察到,人们在某些情况下会做出类似的设计选择,并且这些选择的实现方式也非常类似,于是,就诞生了架构模式。然后,这些选择被命名、记录,并被广泛地讨论。架构模式是在制定解决方案后出现的工具,目的是简化工程师的工作。作为一名工程师,你的目标应该更多地是制定解决方案并从中学习,而不是选择一个闪亮的架构模式,希望它能解决你的问题。
我听到许多人询问如何更好地架构和设计系统。一些有经验的人会推荐你阅读架构模式和软件架构方面的书籍。我肯定也推荐阅读——尤其是书籍,因为它们比一篇短文更有深度——但我还是有一些建议,这些建议比单纯的阅读更具实践性。
最好的软件设计是简单易懂的设计。下次启动一个新项目时,不要想着“我将如何构建这个系统,我应该使用哪些经过实战检验的模式,以及我应该使用哪些形式化的方法来记录它?”,而是要想一想“我怎么才能想出一种任何人都很容易理解的、最简单的设计?”
原文链接:Software Architecture is Overrated, Clear and Simple Design is Underrated
领取专属 10元无门槛券
私享最新 技术干货