刚刚大幅度裁员的Uber文章:软件架构被高估,清晰和简单的设计被低估 - Gergely Orosz


我在设计和构建大型系统方面获得了公平的份额。我参与了重写Uber的分布式支付系统,在Xbox One上设计和发布Skype以及开源RIB,Uber的移动架构框架。所有这些系统都经过了彻底的设计,经历了多次迭代,并进行了大量的白板和讨论。然后,这些设计归结为一份设计文件,在我们开始建造之前,该文件已经传阅以获得更多反馈。
所有这些系统规模都很大:数百名开发人员构建它们 - 或者在它们之上 - 它们为每天数百万人使用的系统提供支撑。他们也不只是绿地项目。支付系统重写必须取代现有的两个支付系统,由数十个系统和数十个团队使用,所有这些系统都没有任何业务影响。重写Uber应用程序是一个项目,几百名工程师同时工作,将现有功能移植到新架构。
让我先从一些可能听起来令人惊讶的事情开始。首先,这些设计都没有使用任何标准软件架构规划工具。我们没有使用UML,也没有使用4 + 1模型ADRC4也没有使用依赖关系图。我们创建了大量的图表,但没有一个遵循任何严格的规则。只是简单的旧框和箭头,类似于描述信息流这一个概述类结构和组件之间的关系。同一设计文档中的两个图表通常具有不同的布局,并且经常由不同的工程师添加和修改。
其次,拥有该设计的团队中没有架构师。没有IT架构师企业架构师。没错,优步和Skype /微软都没有放手软件架构师的职位。高级工程师,如工程师,预计仍会定期编码。对于所有项目,我们确实有经验丰富的工程师参与。但是,没有人拥有该架构或设计。虽然这些经验丰富的开发人员推动了设计过程,但即使是最初级的团队成员也参与其中,通常会挑战决策并提供其他讨论的替代方案。
第三,我们几乎没有参考常见的架构模式和常见软件架构文献中引用的其他术语,例如Martin Fowler的架构指南。没有提到微服务,无服务器架构,应用程序边界,事件驱动架构等等。其中一些确实在头脑风暴期间出现。但是,没有必要在设计文档中引用它们。

科技公司和创业公司的软件设计
那我们怎么做的呢?为什么我们不遵循众所周知的软件架构方法所建议的方法?
我和其他科技公司FANG(Facebook,亚马逊,Netflix,谷歌)以及小型初创公司的同行工程师进行了讨论。大多数团队和项目 - 无论大小 - 都采用了类似的设计和实施方法:

  1. 从业务问题开始。我们想要解决什么?我们试图建立什么产品?为什么?我们如何衡量成功?
  2. 头脑风暴的方法。与团队一起并通过多个会话,找出可行的解决方案。保持这些头脑风暴小。从较高的水平开始,降到较低的水平。
  3. 白板你的方法。让团队聚集在一起,让一个人制定团队融合的方法。您应该能够在白板上清楚地解释系统/应用程序的体系结构,从高层开始,根据需要深入探讨。如果你对这个解释有困难,或者说不够清楚,那么细节上还需要做更多的工作。
  4. 根据您在白板上的说明,通过简单的文档和简单的图表来编写它。将行话保持在最低限度:您甚至希望初级工程师了解它的含义。使用清晰易懂的语言书写。在优步,我们使用类似RFC的文档和基本模板。
  5. 谈论权衡和替代方案。良好的软件设计和良好的架构都是为了做出正确的权衡。没有设计选择本身的好坏:这一切都取决于背景和目标。您的架构是否分为不同的服务?提到为什么你决定不使用一个大型服务,这可能会带来一些其他好处,比如更直接,更快速的部署。您是否选择使用新功能扩展服务或模块?权衡构建单独服务或模块的选择,以及该方法的优缺点。
  6. 在团队/组织内传播设计文档并获得反馈。在优步,我们曾经向所有工程师发送所有软件设计文件,直到我们大约有2,000人。现在我们变得更大,我们仍然非常广泛地分发它们,但我们已经开始更多地平衡信号/噪声比。鼓励人们提问并提供替代方案。务实设定合理的时间限制来讨论反馈并将其纳入需要的地方。可以在现场快速解决直接的反馈,而更详细的反馈可能更快地在现场解决。

为什么我们的方法与软件架构文献中通常提到的方法不同?实际上,对于大多数架构指南而言,我们的方法原则上并没有那么不同。几乎所有指南都建议从业务问题开始,概述解决方案和权衡:这也是我们的工作。我们不做的是使用许多架构师或架构书籍所倡导的许多更复杂的工具。我们使用最简单的工具:Google Docs或Office365等工具,尽可能简单地记录设计。

(banq注:如果文字可以简单记录设计,那么需要那么多单词字母干啥?文学作品干嘛能写那么多废话?文字的问题在于其琐碎细节,图形的区别在于其抽象,协助理解。这么做的危害是无法让新人更快加入复杂的项目,因为一地鸡毛啊,太难了。这大概也是Uber裁员的一个原因,人员冗余,新人加入无法形成生产力。)

我认为我们方法的主要区别归结为这些公司的工程文化。高度自治和层次分明是科技公司和初创公司所共有的特质:对于更传统的公司而言,有时候不那么真实。这也是这些地方在流程驱动设计中采用更严格的规则进行更多“基于常识的设计”的原因。

我知道银行和汽车公司,开发人员在没有进入链条的情况下积极劝阻他们做出任何架构决策,从几个级别的架构师那里获得签约,他们正在监督几个团队。这成为一个较慢的过程,架构师可能会被许多请求所淹没。因此,这些架构师使用常见文献中描述的更多工具,创建更正式的文档,希望使系统更加清晰。这些文件也强化了一种自上而下的方法,因为对于不是架构师的工程师来说,使用正式方法质疑或挑战已经记录的决策更加令人生畏,他们并不精通。所以他们通常不会这样做。公平起见,这些公司经常希望优化开发人员更多的可交换资源,允许他们在短时间内重新分配人员来处理不同的项目。不同的工具在不同的环境中工作得更好也就不足为奇了。

简单,无框架的软件设计超过架构模式
设计系统的目标应该是简单。系统越简单,理解起来就越简单,找到问题就越简单,实现它就越简单。描述的语言越清晰,设计就越容易理解。避免使用团队中每个成员都不理解的术语:经验最少的人应该能够同样清楚地理解事物。
(banq注:DDD统一语言,不要形成不同人的行话,如果有行话就要统一定义)

干净的设计类似于干净的代码:它易于阅读且易于理解。编写干净代码有很多好方法。但是,您很少会听到有人建议您开始在您的代码中应用Gang of four设计模式。清洁代码从单一责任,明确命名和易于理解的约定开始。这些原则同样适用于清晰的架构。
(banq注:好像还是注重架构设计,清洁架构 单一职责属于软件架构,只是用代码替代文档说话,但是图形化的文档还是有作用的,有利于新的设计师快速掌握原有系统的设计路径,发现方向性问题,否则会形成一个自闭的自以为是的软件架构,软件架构只要你编写代码就会自然形成,关键是如何更容易让别人理解)

那么架构模式的作用是什么?我认为它们在编码设计模式方面同样有用。他们可以为您提供有关如何改进代码或架构的想法。对于编码模式,当我看到一个模式时,我会注意到一个单例模式,当我看到一个充当外观的类时,我会抬起眉毛并深入挖掘,只进行调用。但我还没有想到“这需要一个抽象的工厂模式 ”。事实上,我花了很多时间来理解这个模式的作用并且让我的“啊哈!” 在使用大量依赖注入之后 - 这是少数几个领域之一,这种模式实际上很常见且很有用。我也承认,虽然我花了很多时间阅读和理解四人帮设计模式,但他们对成为一名更好的编码器的影响要小于我从其他工程师那里得到的反馈。
同样,了解常见的架构模式也是一件好事:它有助于缩短与人们的讨论,他们以与您相同的方式理解他们。但架构模式不是目标,它们不能替代更简单的系统设计。在设计系统时,您可能会发现自己意外地应用了一个众所周知的模式:这是一件好事。之后,您可以更轻松地参考您的方法。但你要做的最后一件事就是采用一种或多种架构模式,将其用作锤子,寻找钉子来使用它。
在工程师观察到在某些情况下如何进行类似的设计选择之后,架构模式就诞生了,并且这些设计选择也是使用类, 然后选择命名,记录下来,并进行广泛讨论。架构模式是解决方案解决后出现的工具,希望能让其他人的生活更轻松(如何更容易让别人理解)。作为一名工程师,您的目标应该是更多地解决解决方案并通过它们进行学习而不是选择闪亮的架构模式,希望这将解决您的问题。

更好地设计系统
我听说很多人都在寻求有关在架构和设计系统方面做得更好的建议。一些有经验的人会建议阅读有关架构模式和阅读有关软件架构的书籍。虽然我绝对建议阅读 - 特别是书籍,因为它们提供的内容比短篇帖更深 - 我有一些建议,更多的是动手而不仅仅是阅读。

  • 拉队友在白板前面讨论你的设计方法。制定你正在做的事情以及为什么要做事。确保他们理解。当他们这样做时,请求他们的反馈。(banq注:白板确实可以快速形成设计结果,但是这样的设计结构能否经得起推敲,或者是否双方陷入一个坑而没有意识到,多年以后,人们寻找原因时,无法重新当年你们在白板面前决定这样设计的原因了,当然创业公司通常倒闭得快,没有多年以后的假设)
  • 将您的设计写在一个简单的文档中,并与您的团队分享,并征求反馈意见。无论你正在做多么简单或复杂的事情,可能是一个较小的重构或大型项目,总结一下。以对你有意义的方式和其他人可以理解的方式做到这一点 - 为了灵感,这就是我在Uber看到它的方式。以允许评论的格式与您的团队分享,例如Google文档,Office365或其他。让人们添加他们的想法和问题。(banq注:文档如果能简单就无法说清楚,如果说清楚了就无法简单,这是文字这种语言形式的缺陷,否则需要数学干嘛呢?)
  • 设计两种不同的方式,并对比两种设计。当大多数人设计一个架构时,他们采用一种方法:拍脑袋想出来的。但是,架构不是黑白的。请想出第二个可以工作的设计。对比这两者,解释为什么一个比另一个好。简要列出第二个设计作为考虑的替代方案,争论为什么决定反对。(banq注:短时间一天内能想出两个方案,这样的人是天才,不是普通人)
  • 明确你做出的权衡,为什么要做出这些权衡,以及你为之优化的内容。要明确存在的约束,并且必须考虑到这些约束。
  • 回顾其他人的设计。做的更好。假设您拥有一种文化,人们通过白板和会议或文档分享他们的设计,那么请从这些评论中获得更多。在评审期间,大多数人只是试图接受,成为单向观察者。因此,他们会要求澄清不清楚的部分的问题。向他们询问他们考虑过的其他替代方案。问他们他们采取了什么样的权衡以及他们假设的约束。扮演魔鬼的拥护者并提出另一个可能更简单的选择 - 即使它不是一个更好的选择 - 向他们询问他们对你的建议的看法。即使你没有像设计它那样考虑设计,你仍然可以增加很多价值并学到更多东西。(banq注:类似DDD事件风暴)

最好的软件设计简单易懂。下次你开始一个新项目,不是思考:“我将如何构建这个系统,我应该使用哪些经过实战考验的模式以及我应该用哪种正式方法记录它?” ,想想“我怎么能以一种容易让任何人理解的方式提出最简单的设计?”。(banq注:模式与架构正是让别人理解的通用解决方案,如果你采取特殊的解决方案,那更不容易让别人理解,需要理解你的方案与通用模式方案的区别,你自己都没有发现区别,别谈别人了)
软件体系结构最佳实践,企业体系结构模式以及描述系统的形式化方法都是有用的工具,有朝一日可能会派上用场。但是在设计系统时,请从简单开始,尽可能保持简单。尽量避免更复杂的架构和正式工具本身引入的复杂性。(banq注:从简单开始是天性,没有谁愿意一开始为难自己,但是危险在于,自以为从简单开始就是正确的,坚持从简单开始,最后搞复杂了,如果复杂情况可以被人的强迫症改变,世界上就真简单了)

相关文章:
uber/cadence:Cadence是一种分布式,可扩展,持久且高度可用的流程编排引擎
Cadence是一个好东西,可惜很多人认为学习曲线比较高,文档比较难理解,这大概就是Uber的特色