软件架构被高估,简单设计被低估

图片

我们为您提供Gergel Oros职位的翻译,该职位担任Uber工程经理。 在其中,他基于自己在Uber和Microsoft的实践经验,分享了他对大型系统设计的看法。 结合对Hacker News的评论,这些评论增加了重要的反议并补充了作者的观点,他的文章已成为本周最有趣的帖子之一。 本文使用术语“代码设计”与传统的“体系结构”进行比较-有关更多信息,请参见此处

我在设计和创建大型系统方面有足够的经验。 我参与了Uber的分布式支付系统的重写,在Xbox One上设计并发布了Skype,并发布了由Uber创建的可公开使用的移动架构RIBs。 所有这些系统都经过了深思熟虑的设计,经过了多次迭代,并且在白板上举行了许多会议以及其他讨论。 然后,设计提出了一个设计文档,该文档分发给其他开发人员以收集其他反馈,该文档一直持续到我们继续进行开发为止。

所有这些系统都是大规模的:成百上千的开发人员创建了它们-或他们在设计中使用了它们-如今,他们打动了每天有数百万人使用的系统。 而且,这些项目并不是从头开始创建的。 支付系统原本应该替换数十个其他系统和数十个团队使用的其他两个现有支付系统,而这一切都不会损害业务。 重写Uber应用程序是数百名工程师同时从事的一个项目-包括将所有现有功能移植到新架构中。

让我从听起来可能意外的事情开始。 首先,我们从未使用标准的软件体系结构规划工具来进行这些系统的设计。 我们既没有使用UML ,也没有使用4 + 1模型,也没有使用ADR ,也没有使用C4 ,也没有使用依赖图 。 我们绘制了许多图表,但没有一个遵循任何严格的规则。 所需要的只是好的旧矩形和箭头-我们收到的与此图类似的图描述了信息流 ,另一幅图描述了类的结构以及组件之间的关系 。 同一设计文档中的两个图表通常具有不同的样式,因为它们通常是由不同的人添加或编辑的。

其次,我们没有拥有该设计的建筑师。 既没有IT架构师,也没有企业架构师 。 的确如此-Uber或Skype / Mircrosoft都没有软件架构师的专职职位。 仍然希望高级工程师(例如,“人事工程师”职位的工程师)定期编写代码。 我们所有的项目都有经验丰富的工程师-但是,并非只有一个人独自拥有建筑或设计。 尽管经验丰富的工程师是设计过程的推动力,但其他开发人员也参与了讨论,甚至包括绿色的“六月”。此外,他们经常挑战其他人的决定并提出了其他讨论方案。

第三,我们几乎从未提到过常见的架构模式和其他普遍接受的行话,这些行话在诸如Martin Fowler的手册之类的有关软件架构的流行文献中使用 。 没有提及微服务,无服务器架构, 应用程序边界事件驱动的架构或其他任何内容。 其中一些术语在集思广益会议期间浮出水面; 但是,我们无需在设计文档中自行引用它们。

技术公司和初创公司的软件设计


那么我们如何处理一切呢? 为什么我们不遵循通用的软件架构方法呢?

我与其他技术公司的其他工程师(包括FANG规模(Facebook,Amazon,Netflix,Google)和小型创业公司)讨论了此问题。 大多数团队和项目(无论规模大小)都采用类似的方法进行设计和实施:

  1. 从业务任务开始。 我们要解决什么问题? 我们试图创造什么产品,为什么? 我们如何衡量其成功?
  2. 为选择的“方法”集思广益。 与团队聚在一起,在几个环节中找到可行的解决方案。 在此阶段不要过分延迟。 从最高级别开始,然后逐渐降低至以下级别。
  3. 在黑板上画出你的方法。 聚集团队,让你们中的一个描述团队所采用的方法。 您应该能够在电路板的帮助下清楚地说明您的系统/应用程序的体系结构-从最高级别开始,如有必要,请从最低层开始逐步降低。 如果您在解释上有困难或对同事还不够清楚,那么您需要更好地制定决策的细节。
  4. 根据您先前对白板的解释,以带有简单图表的简单文档的形式对其进行修复 。 尽量避免使用专业术语:您甚至希望大三学生都可以理解所讲的内容。 在描述中使用清晰易懂的语言 。 在Uber,我们使用基于简单模板的类似RFC的文档。
  5. 讨论权衡和选择 。 良好的软件设计和良好的体系结构是折衷的正确选择。 就其本身而言,没有一个设计选择是坏的还是好的:这一切都取决于上下文和目标。 您的体系结构分为不同的服务吗? 提到为什么您决定不提供一项大型服务,而这可能还有其他优势,例如更简单,更快的部署。 您是否决定使用新功能扩展模块或服务? 相反,请权衡开发单独的服务或模块的可能性,以及此方法的优缺点。
  6. 在团队/组织内分发设计文档并收集反馈。 以前,在Uber, 我们将软件的所有设计文档发送给我们的所有工程师 -直到我们的员工人数增长到2,000人为止。 现在我们已经发展到如此规模,我们仍在努力吸引尽可能多的听众-但与此同时,我们已开始确保信息噪声级别不超过允许的限制。 鼓励其他人提出问题并提出替代方案。 讨论反馈问题并在必要时将其包括在文档中的时间限制要切合实际。 可以立即,快速地应用特定的愿望,而最好的详细反馈是亲自与他人分解。

为什么我们的方法与软件体系结构文献中通常提到的方法不同? 实际上,我们的方法与体系结构手册中的描述从根本上没有什么不同。 几乎所有手册都建议从业务任务开始,以及描述解决方案和权衡取舍-我们也这样做。 我们不做的是不使用许多建筑师和建筑学书籍提倡的更复杂的工具。 我们使用最简单,最明显的工具(例如Google Docs或Office 365)使设计尽可能简单。

我认为,我们方法的主要区别在于不同公司的工程文化。 高度自治和最小化层次结构是现代技术公司和初创公司共同的特点。 对于更传统的公司而言,事实并非总是如此。 这也是为什么在这些地方他们经常求助于“基于常识的设计”而不是基于具有严格规则的流程的设计的原因。

我知道银行和汽车公司会积极地鼓励开发人员不要做出任何架构决定,而不必上链,他们会从更高级别的建筑师那里获得批准,这些建筑师负责监督多个团队。 这使过程变慢,并且在有大量请求的情况下,架构师变得超负荷。 因此,这些架构师使用您熟悉的文献中介绍的所有工具,希望创建更加正式的文档,以期使系统变得更加易于理解。 这些文档以自上而下的方法进行备份,因为它以一种令人生畏的方式对工程师起作用-毕竟,它们不是建筑师,并且不应质疑或质疑决策,因为它们已经使用不熟练的正式方法进行了文档记录。 因此,他们通常不这样做。 坦率地说,这些公司这样做是为了使开发人员具有可互换的资源-因为这使他们可以在短时间内将人员从一个项目转移到另一个项目。 不同的工具更适合于不同的环境,这可能不足为奇。

简单的软件设计,无需术语,而无需架构模式


系统设计的目标应该是简单。 系统越简单,就越容易理解-以及在其中发现和实施问题也就越容易。 描述它的语言越清晰,其设计就越容易获得。 避免使用团队中每个成员都不会理解的行话-即使您最没有经验的同事也应该能够理解其他人所面临的风险。

简洁的设计就像简洁的代码:易于阅读和理解。 有很多很棒的方法可以编写干净的代码。 但是,您经常会听到有人建议从对代码应用“四人一组”设计模式开始。 干净的代码从全权负责,清楚的名称和易于理解的约定开始。 这些原则同样适用于纯体系结构。

那么架构模式的作用是什么? 我发现它们很有用-就像代码设计模式一样有用。 他们可以为您提供有关如何改进代码或体系结构的想法。 采取代码设计模式:当我发现代码中有一个单例时,我会为自己注意到-当我看到一个行为类似于facade的类时,我会抬起我的眉毛,并进行更深入的研究,但实际上它只是进行调用。 但是,当我想到“ 抽象工厂只是在这里要它”的日子还没有到来。 实际上,我花了很长时间才弄清楚这种模式的作用以及在它突然出现之前。 理解是由于依赖注入的辛勤工作的结果, 依赖注入 这种模式广泛且极其有用的少数领域之一。 我还承认,尽管我花了很多时间阅读和理解“四人组”设计模式,但是它们对我作为程序员的专业发展的影响要比我从其他开发人员收到的有关我的代码的反馈要少得多。

同样,了解通用的架构模式也是一件好事:它有助于减少与以相同方式理解它们的人进行讨论的时间。 但是体系结构模式不是目标,并且它们不会替代更简单的系统设计选项。 在设计系统时,您可能会突然意识到您不小心应用了某些通用模式-这很好,因为以后您可以更轻松地引用所使用的方法。 但是,您永远不应采用一种或多种图案并将其用作锤子,因为它们总是会钉住钉子。

当工程师提请注意以下事实时,便会出现架构模式:在某些情况下,就设计及其实现做出类似的决定是有意义的。 随着时间的流逝,这些决定获得了名称,并由公众记录和讨论。 体系结构模式是在找到解决方案之后出现的工具,希望这将有助于使其他人的生活更轻松。 作为工程师,您应该将独立寻求问题的解决方案作为目标,并在此过程中学习,而不是采用“炒作”的架构模式,以期希望能够解决您的问题,这是您的目标。

如何学习如何更好地设计系统


人们经常向我征求意见:如何在系统的体系结构和设计中“抽水”? 经验丰富的工程师通常建议阅读有关体系结构模式的知识,以及有关软件体系结构的书籍。 我完全支持建议尽可能多地阅读-特别是书籍,因为它们使您可以比短篇幅更深入地研究该主题-但是,我有一些更实用的建议。

  • 与团队成员之一互动,并一起做白板。 在板上画出您正在做什么,并解释图像的含义。 确保您的同事理解所讲的内容。 当您最终理解后,请寻求反馈。
  • 在一个简单的文档中描述您的设计,并与您的团队分享,请他们提供反馈。 您正在执行的任务多么简单或复杂都没有关系-它可以是小型重构也可以是大型项目-您应该简要地总结一下。 这样做的方式使您对本文档有意义,而对于其他文档则可以理解。 灵感- 这是Uber如何做到的示例。 与您的团队以允许发表评论的格式共享此文档,例如,使用Google Docs,Office 365或类似工具。 要求其他人以他们的想法和问题来补充它。
  • 创建两个不同的设计并进行对比。 当我们大多数人设计架构时,它们通常采用一种方式:一种突然出现的方式。 但是,建筑不是黑白的。 提出第二种架构设计选项,也可以在您的情况下使用。 对比两种设计并解释为什么一个比另一个更好。 指出您已经考虑第二个选择已有一段时间了,并说明您为什么做出不利于他的决定的决定。
  • 确定您准备要做出的妥协 -了解为什么接受这些妥协以及您希望在它们的帮助下实现的目标。 明确建立您必须考虑的现有限制。
  • 对其他人的设计进行审查。 并明智地做到这一点。 如果您的公司具有共享设计的文化,人们可以使用白板,会议或文档共享设计,则可以从中获取更多信息。 通常,在审阅过程中,人们将其他人的代码设计视为观察员。 相反,请针对您不太了解的部分提出澄清问题。 询问他们考虑了哪些替代方案。 询问他们做出了哪些妥协以及他们考虑了哪些限制。 成为魔鬼的拥护者,并提出另一个可能更简单的替代方法(即使这并不比他们的解决方案更好),并询问他们对您的建议有何看法。 即使您与提出设计的人相比,对设计的想法还不够好,但是您的讨论仍然可以带来一些新的东西,并帮助您更好地了解自己的工作。

最好的软件设计简单易懂。 下次启动新项目时,不用考虑问题“ 我将如何设计该系统,在战斗中应使用哪种模式,以及应以哪种正式方法进行记录? ”,思考-“ 我怎样才能做出最简单的设计-任何人都容易理解的设计?

软件架构的最佳实践,企业应用程序的架构模式,描述系统的正式方法都是有用的工具,因为有一天它们可能对您非常有用。但是,在设计系统时,值得从一个简单的系统开始,并继续保持它尽可能的简单。尝试避免复杂的架构和形式化工具不可避免地给您的系统带来的复杂性。

这篇文章引起了业界工人的热烈讨论,他们分享了他们对软件体系结构的经验和态度。您可以在Hacker NewsLobste.rsReddit上阅读这些讨论

, , , « », « »; — 20 « », 300 IT- , — API, 5000 7000 .

Source: https://habr.com/ru/post/zh-CN467997/


All Articles