发布于 2026-01-06 5 阅读
0

软件架构:清晰简洁的设计被低估了 DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

软件架构:清晰简洁的设计被低估了

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

我在大型系统的设计和构建方面积累了丰富的经验。我参与了 Uber分布式支付系统的重写、Xbox One 版 Skype 的设计和发布,以及 Uber 移动架构框架RIBs的开源。所有这些系统都经过了详尽的设计,经历了多次迭代,并进行了大量的白板讨论。最终,设计方案被提炼成一份设计文档,并在正式开发之前分发给更多人征求意见。

所有这些系统规模都非常庞大:数百名开发人员构建或在其基础上进行开发,它们为每天数百万用户使用的系统提供支持。而且,它们并非全新的项目。支付系统的重写必须替换两个现有的支付系统,这两个系统被数十个系统和数十个团队使用,并且不能对业务造成任何影响。重写 Uber 应用是一个数百名工程师同时参与的项目,他们将现有功能移植到新的架构上。

首先,我想说几件可能令人惊讶的事情。首先,这些设计都没有使用任何标准的软件架构规划工具。我们没有使用UML4+1 模型ADRC4依赖关系图。我们绘制了大量的图表,但它们都没有遵循任何严格的规则。只是简单的方框和箭头,例如这张描述信息流的图表,或者这张概述类结构和组件之间关系的图表。同一份设计文档中的两张图表布局往往不同,而且经常由不同的工程师添加和修改。

其次,负责设计的团队中没有架构师。既没有IT架构师,也没有企业架构师。诚然,Uber和Skype/微软都没有完全放手的软件架构师职位。像高级工程师这样的资深工程师仍然需要定期编写代码。所有项目都有经验丰富的工程师参与。然而,并没有人负责架构或设计。虽然这些经验丰富的开发人员主导了设计流程,但即使是最初级的团队成员也参与其中,他们经常对决策提出质疑,并提出其他方案供讨论。

第三,我们几乎没有参考任何常见的架构模式和其他术语,这些术语在常见的软件架构文献中经常出现,例如Martin Fowler 的架构指南。微服务、无服务器架构、应用边界、事件驱动架构等等,统统都没有提及。虽然在头脑风暴阶段确实讨论过其中一些概念,但在设计文档中却完全没有必要引用它们。

科技公司和初创企业的软件设计

那么我们是如何完成工作的?为什么我们没有采用一些知名的软件架构方法所建议的方法?

我曾与在其他科技公司(包括FANG公司,即Facebook、亚马逊、Netflix和谷歌)以及一些小型创业公司工作的同行工程师讨论过这个问题。大多数团队和项目——无论规模大小——在设计和实现方面都采用了类似的方法:

  1. 首先要明确业务问题。我们试图解决什么问题?我们试图打造什么产品,为什么?我们如何衡量成功?
  2. 集思广益,探讨解决方案。与团队一起开会,通过多次讨论,找出可行的方案。每次集思广益的讨论都要从小处着手,从宏观层面入手,逐步深入到微观层面。
  3. 在白板上展示你的方案。召集团队成员,由一人将团队正在共同商定的方案绘制出来。你应该能够清晰地在白板上解释你的系统/应用程序架构,从高层级开始,并根据需要逐步深入。如果你在解释过程中遇到困难或不够清晰,则需要进一步完善细节。
  4. 根据你在白板上的讲解,用简单的文档和图表将其记录下来。尽量避免使用专业术语:你希望即使是初级工程师也能理解它的内容。使用清晰易懂的语言撰写。在 Uber,我们使用类似 RFC 的文档,并附带一个基本模板。
  5. 谈谈权衡取舍和替代方案。优秀的软件设计和架构的关键在于做出正确的权衡。任何设计选择本身并无好坏之分:一切都取决于具体情况和目标。你的架构是否拆分成不同的服务?请说明你为何放弃使用一个大型服务,尽管它可能具有其他优势,例如更直接、更快捷的部署。你是否选择为某个服务或模块添加新功能?请权衡一下构建一个独立的服务或模块的方案,并分析这种方法的优缺点。
  6. 在团队/组织内部传阅设计文档并收集反馈。在 Uber,我们过去会将所有软件设计文档发送给所有工程师,直到团队规模达到 2000 人左右。现在公司规模更大了,我们仍然会广泛分发文档,但会更加注重控制信息传递的效率。鼓励大家提问并提出替代方案。务实地设定合理的讨论和采纳反馈的时间限制,并在必要时进行调整。直接的反馈可以当场快速解决,而更详细的反馈可能需要当面讨论才能更快达成一致。

为什么我们的方法与软件架构文献中通常提到的方法不同?实际上,我们的方法在原则上与大多数架构指南并没有太大区别。几乎所有指南都建议从业务问题入手,然后概述解决方案和权衡取舍:这也是我们的做法。我们没有采用的是许多架构师或架构书籍所提倡的复杂工具。我们尽可能使用最简单易用的工具(例如 Google Docs 或 Office 365)来记录设计,力求简洁明了。

我认为我们方法上的主要差异归根结底在于这些公司的工程文化。高度自主和扁平化的层级结构是科技公司和初创企业的共同特征,而传统公司在这方面则往往有所欠缺。这也是为什么这些公司更倾向于采用“基于常识的设计”而非流程驱动的设计,并制定更严格的规则的原因之一。

我知道一些银行和汽车公司会积极阻止开发人员在没有向上汇报并获得几级架构师(他们负责多个团队)的批准之前做出任何架构决策。这会拖慢流程,架构师也可能被大量的请求压得喘不过气来。因此,这些架构师会创建更正式的文档,希望通过运用更多文献中描述的工具来使系统更加清晰。这些文档也强化了自上而下的方法,因为对于非架构师的工程师来说,质疑或挑战那些已经用他们并不熟悉的正式方法记录下来的决策会让他们感到畏惧。所以他们通常不会这样做。公平地说,这些公司通常希望优化开发人员的资源配置,使他们能够更灵活地将人员调配到其他项目中,即使时间很短。不同的工具在不同的环境中效果更好,这并不奇怪。

简洁、无术语的软件设计优于架构模式

系统设计的目标应该是简洁。系统越简洁,就越容易理解,越容易发现问题,也越容易实现。描述的语言越清晰,设计就越容易理解。避免使用团队成员难以理解的术语:即使是经验最少的人也应该能够同样清楚地理解。

简洁的设计与简洁的代码类似:易于阅读和理解。编写简洁代码的方法有很多,但你很少会听到有人建议一开始就将“四人帮”的设计模式应用到代码中。简洁的代码始于单一职责、清晰的命名和易于理解的约定。这些原则同样适用于清晰的架构。

那么架构模式的作用是什么呢?我认为它们的作用与编码设计模式类似。它们可以为你提供改进代码或架构的思路。对于编码模式,我看到单例模式就会注意到,看到一个只做调用传递的“门面”类时,我会竖起眉毛深入研究。但我至今还没想过“这需要用到 抽象工厂模式。事实上,我花了很长时间才理解这个模式的作用,直到大量使用依赖注入之后才恍然大悟——依赖注入是少数几个该模式非常常见且实用的领域之一。我也承认,虽然我花了很多时间阅读和理解“四人帮”的设计模式,但它们对我提升编码水平的影响远不如其他工程师对我的代码提供的反馈。

同样,了解常见的架构模式是件好事:它能帮助你缩短与那些理解相同的人的讨论时间。但架构模式并非最终目的,它们也无法替代更简洁的系统设计。在系统设计过程中,你可能会不经意间应用了某个知名的模式:这其实是件好事。之后,你可以更轻松地参考你的方法。但你最不希望看到的就是,把一个或多个架构模式当作锤子,到处寻找钉子来敲打。

架构模式的诞生源于工程师们观察到某些案例中相似的设计选择和实现方式。这些选择随后被命名、记录下来,并被广泛讨论。架构模式是解决方案解决出现的工具,旨在简化他人的工作。作为一名工程师,你的目标应该是解决实际问题并从中学习,而不是选择一个花哨的架构模式,寄希望于它能解决你的问题。

软件架构最佳实践、企业架构模式以及系统描述的形式化方法都是值得了解的工具,将来或许能派上用场。但在设计系统时,要尽可能从简单入手,并保持简洁。尽量避免更复杂的架构和形式化工具本身带来的复杂性。


本文最初发表于《实用工程师博客》,标题为“软件架构被高估了,清晰简洁的设计被低估了”,该文章包含一个关于如何更好地设计系统的技巧部分。

关于我:我是一名从工程师转型为工程经理的工程师,目前在硅谷和欧洲的初创公司及科技公司工作。欢迎关注我的博客和推特。我会在我的博客“务实工程师”(The Pragmatic Engineer)上发表关于软件工程的长篇论文。此外,我每月还会发送一份简讯,分享关于软件工程、技术领导力以及我思考的一些有趣话题。

文章来源:https://dev.to/gergelyorosz/software-architecture-clear-and-simple-design-is-undererated-2bj9