我在设计和构建大型系统方面获得了公平的份额。我参与了重写Uber的 分布式支付系统 ,在Xbox One上设计和发布Skype以及开源 RIB ,Uber的移动架构框架。所有这些系统都经过了彻底的设计,经历了多次迭代,并进行了大量的白板和讨论。然后,这些设计归结为一份设计文件,在我们开始建造之前,该文件已经传阅以获得更多反馈。
所有这些系统规模都很大:数百名开发人员构建它们 - 或者在它们之上 - 它们为每天数百万人使用的系统提供支撑。他们也不只是绿地项目。支付系统重写必须取代现有的两个支付系统,由数十个系统和数十个团队使用,所有这些系统都没有任何业务影响。重写Uber应用程序是一个项目,几百名工程师同时工作,将现有功能移植到新架构。
让我先从一些可能听起来令人惊讶的事情开始。首先,这些设计都没有使用任何标准软件架构规划工具。我们没有使用 UML ,也没有使用 4 + 1模型 , ADR , C4 也没有使用 依赖关系图 。我们创建了大量的图表,但没有一个遵循任何严格的规则。只是简单的旧框和箭头,类似于 描述信息流 或 这一个概述类结构和组件之间的关系 。同一设计文档中的两个图表通常具有不同的布局,并且经常由不同的工程师添加和修改。
其次,拥有该设计的团队中没有架构师。没有 IT架构师 或 企业架构师 。没错,优步和Skype /微软都没有放手软件架构师的职位。高级工程师,如工程师,预计仍会定期编码。对于所有项目,我们确实有经验丰富的工程师参与。但是,没有人拥有该架构或设计。虽然这些经验丰富的开发人员推动了设计过程,但即使是最初级的团队成员也参与其中,通常会挑战决策并提供其他讨论的替代方案。
第三,我们几乎没有参考常见的架构模式和常见软件架构文献中引用的其他术语,例如 Martin Fowler的架构指南 。没有提到微服务,无服务器架构,应用程序边界,事件驱动架构等等。其中一些确实在头脑风暴期间出现。但是,没有必要在设计文档中引用它们。
科技公司和创业公司的软件设计
那我们怎么做的呢?为什么我们不遵循众所周知的软件架构方法所建议的方法?
我和其他科技公司FANG(Facebook,亚马逊,Netflix,谷歌)以及小型初创公司的同行工程师进行了讨论。大多数团队和项目 - 无论大小 - 都采用了类似的设计和实施方法:
为什么我们的方法与软件架构文献中通常提到的方法不同?实际上,对于大多数架构指南而言,我们的方法原则上并没有那么不同。几乎所有指南都建议从业务问题开始,概述解决方案和权衡:这也是我们的工作。我们不做的是使用许多架构师或架构书籍所倡导的许多更复杂的工具。我们使用最简单的工具:Google Docs或Office365等工具,尽可能简单地记录设计。
(banq注:如果文字可以简单记录设计,那么需要那么多单词字母干啥?文学作品干嘛能写那么多废话?文字的问题在于其琐碎细节,图形的区别在于其抽象,协助理解。这么做的危害是无法让新人更快加入复杂的项目,因为一地鸡毛啊,太难了。这大概也是Uber裁员的一个原因,人员冗余,新人加入无法形成生产力。)
我认为我们方法的主要区别归结为这些公司的工程文化。高度自治和层次分明是科技公司和初创公司所共有的特质:对于更传统的公司而言,有时候不那么真实。这也是这些地方在流程驱动设计中采用更严格的规则进行更多“基于常识的设计”的原因。
我知道银行和汽车公司,开发人员在没有进入链条的情况下积极劝阻他们做出任何架构决策,从几个级别的架构师那里获得签约,他们正在监督几个团队。这成为一个较慢的过程,架构师可能会被许多请求所淹没。因此,这些架构师使用常见文献中描述的更多工具,创建更正式的文档,希望使系统更加清晰。这些文件也强化了一种自上而下的方法,因为对于不是架构师的工程师来说,使用正式方法质疑或挑战已经记录的决策更加令人生畏,他们并不精通。所以他们通常不会这样做。公平起见,这些公司经常希望优化开发人员更多的可交换资源,允许他们在短时间内重新分配人员来处理不同的项目。不同的工具在不同的环境中工作得更好也就不足为奇了。
简单,无框架的软件设计超过架构模式
设计系统的目标应该是简单。系统越简单,理解起来就越简单,找到问题就越简单,实现它就越简单。描述的语言越清晰,设计就越容易理解。避免使用团队中每个成员都不理解的术语:经验最少的人应该能够同样清楚地理解事物。
(banq注:DDD统一语言,不要形成不同人的行话,如果有行话就要统一定义)
干净的设计类似于干净的代码:它易于阅读且易于理解。编写干净代码有很多好方法。但是,您很少会听到有人建议您开始在您的代码中应用 Gang of four设计模式 。清洁代码从单一责任,明确命名和易于理解的约定开始。这些原则同样适用于清晰的架构。
(banq注:好像还是注重架构设计,清洁架构 单一职责属于软件架构,只是用代码替代文档说话,但是图形化的文档还是有作用的,有利于新的设计师快速掌握原有系统的设计路径,发现方向性问题,否则会形成一个自闭的自以为是的软件架构,软件架构只要你编写代码就会自然形成,关键是如何更容易让别人理解)
那么架构模式的作用是什么?我认为它们在编码设计模式方面同样有用。他们可以为您提供有关如何改进代码或架构的想法。对于编码模式,当我看到一个 模式 时,我会注意到一个 单例模式, 当我看到一个充当 外观 的类时,我会抬起眉毛并深入挖掘,只进行调用。但我还没有想到“这需要一个 抽象的工厂模式 ”。事实上,我花了很多时间来理解这个模式的作用并且让我的“啊哈!” 在使用大量依赖注入之后 - 这是少数几个领域之一,这种模式 实际上很常见且很有用 。我也承认,虽然我花了很多时间阅读和理解四人帮设计模式,但他们对成为一名更好的编码器的影响要小于我从其他工程师那里得到的反馈。
同样,了解常见的架构模式也是一件好事:它有助于缩短与人们的讨论,他们以与您相同的方式理解他们。但架构模式不是目标,它们不能替代更简单的系统设计。在设计系统时,您可能会发现自己意外地应用了一个众所周知的模式:这是一件好事。之后,您可以更轻松地参考您的方法。但你要做的最后一件事就是采用一种或多种架构模式,将其用作锤子,寻找钉子来使用它。
在工程师观察到在某些情况下如何进行类似的设计选择之后,架构模式就诞生了,并且这些设计选择也是使用类, 然后选择命名,记录下来,并进行广泛讨论。架构模式是解决方案解决后出现的工具,希望能让其他人的生活更轻松(如何更容易让别人理解)。作为一名工程师,您的目标应该是更多地解决解决方案并通过它们进行学习而不是选择闪亮的架构模式,希望这将解决您的问题。
更好地设计系统
我听说很多人都在寻求有关在架构和设计系统方面做得更好的建议。一些有经验的人会建议阅读有关架构模式和阅读有关软件架构的书籍。虽然我绝对建议阅读 - 特别是书籍,因为它们提供的内容比短篇帖更深 - 我有一些建议,更多的是动手而不仅仅是阅读。
最好的软件设计简单易懂。下次你开始一个新项目,不是思考:“我将如何构建这个系统,我应该使用哪些经过实战考验的模式以及我应该用哪种正式方法记录它?” ,想想“我怎么能以一种容易让任何人理解的方式提出最简单的设计?”。(banq注:模式与架构正是让别人理解的通用解决方案,如果你采取特殊的解决方案,那更不容易让别人理解,需要理解你的方案与通用模式方案的区别,你自己都没有发现区别,别谈别人了)
软件体系结构最佳实践,企业体系结构模式以及描述系统的形式化方法都是有用的工具,有朝一日可能会派上用场。但是在设计系统时,请从简单开始,尽可能保持简单。尽量避免更复杂的架构和正式工具本身引入的复杂性。(banq注:从简单开始是天性,没有谁愿意一开始为难自己,但是危险在于,自以为从简单开始就是正确的,坚持从简单开始,最后搞复杂了,如果复杂情况可以被人的强迫症改变,世界上就真简单了)