生成式AI领域的最新成果都在这里!抢 QCon 展区门票 了解详情
写点什么

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

  • 2019-09-29
  • 本文字数:4059 字

    阅读完需:约 13 分钟

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

软件架构最佳实践、企业架构模式以及系统描述的正式方法都是非常重要且实用的工具,总会有合适的场景让它们发挥作用。但在设计系统时,请从简单始、以简单终,尽可能避免一切会无谓提高复杂度的架构与正式工具。


我的职责是设计和构建大型系统。我参与重写了 Uber 的分布式支付系统,设计并交付了 Skype on Xbox One,开源了 Uber 的移动架构框架RIBs。所有这些系统都进行了彻底的设计,经过多次迭代和大量讨论。然后,这些设计被记录到设计文档中,在我们开始构建之前分发出去,从而获得更多的反馈。


所有这些系统的规模都很大:有数百名开发人员在构建它们——或者以它们为基础进行构建——并且它们支撑着每天数百万人使用的系统。它们不仅仅是绿地项目。重写的支付系统就是用于替换两个已有的支付系统,有几十个系统、数十个团队在使用它们,但所有这些都没有对业务产生任何影响。重写 Uber App 是一个由数百名工程师同时参与的项目,他们将现有的功能移植到一个新的架构中。


让我先说些可能会让你觉得吃惊的事。首先,这些设计都没有使用任何标准的软件架构规划工具。我们没有使用UML,没有使用4+1模型,没有使用ADR,也没有使用C4依赖关系图。我们创建了大量的图表,但是没有遵循任何严格的规则。只是使用了普通的方框和箭头,类似于这个描述信息流的图或这个概括类结构和组件之间关系的图。同一个设计文档中的两个图经常会有不同的布局,并且经常由不同的工程师添加和修改。


其次,负责设计的团队中没有架构师。没有IT架构师企业架构师。没错,Uber 和 Skype/微软都没有袖手旁观的软件架构师职位。级别较高的工程师和普通工程师一样,仍然需要定期编写代码。对于所有的项目,我们都有经验丰富的工程师参与。然而,没有人专门负责架构或设计。经验丰富的开发人员确实推动了设计过程。不过,即使是最初级的成员也在设计过程中进行了输入,他们经常会挑战决策,并提供其他可供讨论的替代方案。


第三,我们实际上没有引入常见的架构模式以及常见的软件架构文献中引用的其他术语,比如Martin Fowler的架构指南。没有提到微服务、无服务器架构、应用程序边界、事件驱动架构等。其中一些在头脑风暴时确实提到过,但是,没有必要在设计文档中引用它们。

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

那么,我们是如何完成任务的呢?为什么我们不遵循著名的软件架构方法所建议的方法呢?


我曾与其他科技公司(Facebook、亚马逊、Netflix、谷歌)以及规模较小的初创公司的同行们讨论过这个问题。大多数团队和项目无论大小,都采用类似的设计和实现方法:


  1. 从业务问题入手。我们要解决什么问题?我们要设法构建什么产品?为什么?我们如何度量成功?

  2. 通过头脑风暴找出方法。与团队一起,通过多次会议,找出可行的解决方案。务必保证这些头脑风暴的规模要小。从高层开始,逐步下降到较低的层次上。

  3. 借助白板说明方法。把团队聚集在一起,让一个人绘制出团队趋向于采用的方法。你应该能够在白板上清楚地解释你的系统/应用程序的架构,从高层开始,根据需要逐步深入。如果你觉得解释有困难或者不够清楚,就需要在细节上做更多的工作。

  4. 根据你在白板上的解释,使用简洁的文档和图表详细描述设计。尽量少用术语:要让初级工程师也明白它的意思。用清晰易懂的语言写下来。在 Uber,我们使用一个带有基本模板的类似 RFC 的文档。

  5. 讨论权衡可选方案。良好的软件设计和架构重点在于做出正确的权衡。设计选择本身没有好坏之分:它完全取决于上下文和目标。架构是否要划分为不同的微服务?说明一下为什么你决定不使用单体架构,它可能有其他一些好处,比如部署更简单更快速。你是否选择使用新功能扩展服务或模块?权衡构建单个服务或模块的选项,以及这种方法的优缺点。

  6. 在团队/组织内分发设计文档并获得反馈。在 Uber,我们曾经把所有的软件设计文档发给所有的工程师,直到我们的工程师人数达到大约 2000 名。现在我们的人数更多了,我们仍然广泛地分发设计文档,但是我们已经开始更多地平衡信噪比。我们鼓励人们提出问题并提供替代方案。要根据实际情况设定合理的反馈时间限制,讨论反馈意见,并根据需要加以采纳。简单明了的反馈可以现场快速处理,而更复杂的反馈现场处理也可能会更快。


为什么我们的方法与软件架构文献中经常提到的方法不同?实际上,我们的方法与大多数架构指南在原则上并没有太大的不同。几乎所有的指南都建议从业务问题开始,概述解决方案并进行权衡:我们也是这样做的。我们没有使用许多架构师或架构书籍提倡的更复杂的工具。我们使用最直接的工具(如谷歌 Docs 或 Office365)尽可能简单地记录设计。


我认为,在这些公司中,我们的方法的主要区别在于工程文化。自主性高和层级少是科技公司和初创企业的共同特点:对于更传统的公司来说,有时并非如此。这也是为什么这些地方使用更严格的规则进行更多的“基于常识的设计”,而不是流程驱动的设计。


我知道一些银行和汽车公司,它们的开发人员在没有得到高层架构师的批准之前,不愿做出任何架构决策,而这些架构师负责管理多个团队。这会是一个比较缓慢的过程,架构师可能会被许多请求淹没。因此,这些架构师创建了更正式的文档,希望通过更多地使用常见文献中介绍的工具使系统更清晰。这些文档还强化了自上向下的方法,因为对于非架构师工程师来说,质疑或挑战已经用正式方法记录下来的、他们不是很熟悉的决策更令人生畏。所以他们通常不会这么做。公平地说,这些公司常常希望使开发人员成为更容易替换的资源,以便他们可以在短时间内重新分配人员从事不同的项目。不同的工具在不同的环境中可以更好地发挥作用,这应该不足为奇。

简单、无术语的软件设计胜过架构模式

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


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


那么,架构模式的作用是什么?我认为它们与编码设计模式同样有用。它们可以为你提供关于如何改进代码或架构的思路。对于编码模式,当我看到一个单例模式时,我就会注意到它;当我看到一个类仅充当执行调用的外观时,我就会扬起眉毛,深入研究。但我还没有想到“这需要一个抽象工厂模式”。事实上,在处理了大量依赖注入之后,我花了很多时间来理解这个模式的作用,并且终于在某个时刻恍然大悟——这实际上是这个模式非常常见并且非常有用的少数几个领域之一。我还得承认,虽然我花了很多时间阅读和理解 GoF 设计模式,但与我从其他工程师那里得到的代码反馈相比,它们对于我成为一名更好的程序员的影响要小得多。


类似地,了解常见的架构模式是一件好事:它有助于缩短与他人讨论的时间,他们和你一样理解那些模式。但是架构模式并不是我们的目标,它们也不能代替更简单的系统设计。在设计系统时,你可能会无意中应用了一个众所周知的模式:这是一件好事。后续你要参照这个方法就更容易了。但是,你最不希望看到的是使用一个或多个架构模式,把它当成一把锤子,为了用它而到处找钉子。


工程师们观察到,人们在某些情况下会做出类似的设计选择,并且这些选择的实现方式也非常类似,于是,就诞生了架构模式。然后,这些选择被命名、记录,并被广泛地讨论。架构模式是在制定解决方案后出现的工具,目的是简化工程师的工作。作为一名工程师,你的目标应该更多地是制定解决方案并从中学习,而不是选择一个闪亮的架构模式,希望它能解决你的问题。

如何更好地设计系统?

我听到许多人询问如何更好地架构和设计系统。一些有经验的人会推荐你阅读架构模式和软件架构方面的书籍。我肯定也推荐阅读——尤其是书籍,因为它们比一篇短文更有深度——但我还是有一些建议,这些建议比单纯的阅读更具实践性。


  • 拉过一名同事,在白板上写下你的设计方法。写出你在做什么,为什么要这么做。确保他们能理解。当他们能理解的时候,征求他们的意见。

  • 将你的设计详细记录在一个简单的文档中,并与你的团队分享,寻求反馈。不管你正在处理的事情多么简单或复杂,可能是较小的重构,也可能是大型项目,总结一下。采用一种对你而言有意义的方式,一种别人能理解的方式。为了帮你寻找灵感,我在这里分享了我在 Uber 看到的做法。与团队共享时采用一种可以评论的格式,如谷歌文档、Office365 等。让人们添加他们的想法和问题。

  • 设计两种方案,并进行对比。大多数人在设计架构时都只采用一种方法,就是突然出现在他们脑海中的方法。然而,架构并不是非黑即白的。提出第二个同样可行的设计。对比两者,解释为什么一个比另一个更好。简要列出第二种设计作为备选方案,并说明为什么决定不用它。

  • 要清楚你所做的权衡,为什么要做这些权衡,以及你优化了哪些东西。要清楚存在的约束,并且必须考虑到这些约束。

  • 评审别人的设计,并取长补短做到更好。假设你们有这样一种文化,人们通过白板、会议或文档来分享他们的设计,那么你就能从评审意见中了解到更多的东西。在评审过程中,大多数人只是试着接受一些东西,成为单向的观察者。我们不能局限于此。相反,对于不清楚的部分要通过提问来弄清楚。询问他们考虑过的其他选项。问他们做了哪些权衡,假设了哪些约束条件。要唱反调,提出另一个可能更简单的选项——即使不是更好的选项——问问他们对你的建议有何看法。即使你没有像设计展示者那样思考得那么深入,你仍然可以带来很多有价值的东西并学到更多的东西。


最好的软件设计是简单易懂的设计。下次启动一个新项目时,不要想着“我将如何构建这个系统,我应该使用哪些经过实战检验的模式,以及我应该使用哪些形式化的方法来记录它?”,而是要想一想“我怎么才能想出一种任何人都很容易理解的、最简单的设计?”


原文链接:Software Architecture is Overrated, Clear and Simple Design is Underrated


2019-09-29 13:464344
用户头像

发布了 686 篇内容, 共 395.4 次阅读, 收获喜欢 1498 次。

关注

评论 1 条评论

发布
用户头像
说出了真话
2019-09-30 09:39
回复
没有更多了
发现更多内容

25年,初心未改。

澳鹏Appen

人工智能 机器学习 训练数据 数据训练

Token机制相对于Cookie机制的优势

郑州埃文科技

数据库 IP Token API

艾瑞发布《2021 年全球互联网通信云行业研究报告》,融云持续领跑市场

融云 RongCloud

物联网之智慧农业应用分析&大数据之数据挖掘技术的应用

亚马逊云科技 (Amazon Web Services)

人工智能 云计算 大数据 物联网

模型黑盒|机器学习模型的“可解释性”研究

索信达控股

神经网络 机器学习 神经网络模型

直播连麦的人工智能回声消除技术探索

融云 RongCloud

项目开发架手架规划

hasWhere

在线JSON转Mongoose工具

入门小站

工具

【架构师训练营】模块三作业

樰巳-堕~Horry

架构实战营 「架构实战营」

58 K8S之集群日志系统

穿过生命散发芬芳

k8s 28天写作 12月日更

多因子认证是什么意思?与双因子认证有什么区别?

行云管家

身份认证 双因子认证 账户安全

恒源云(GPUSHARE)_有关【图像平滑】的论文小记

恒源云

深度学习 CV 图像处理

百度APP视频播放中的解码优化

百度开发者中心

视频 解码技术

深入Java线程池:从设计思想到源码解读

Ayue、

线程池

基于DataX的数据同步(上)-DataX介绍以及安装

恒生LIGHT云社区

MySQL 数据库 数据同步 DataX

从了解洞态 IAST 到加入开源社区

火线安全

DevSecOps IAST

2021年终总结

hasWhere

实现一个javaagent需要几步?

BUG侦探

Java javaagent IAST

Linux之find命令

入门小站

Linux

☕【权限设计系列】「认证授权专题」史上最全的权限认证服务的权限模型大全

洛神灬殇

架构设计 12月日更 权限设计 功能设计

风云再起之国产数据库风云榜-2021年12月

墨天轮

数据库 opengauss TiDB 国产数据库

【网络安全】针对 HTTP/2 协议的HTTP Desync攻击

H

网络安全 信息安全 漏洞

有没有好用的低代码平台,支持本地私有化部署的?

优秀

低代码 私有化部署

泉州有几家正规等保测评公司?在哪里?叫什么名字?

行云管家

网络安全 等保 等级保护 等保测评

2022年之前,你不得不了解的一些 DevOps 趋势

SoFlu软件机器人

Linux中如何设置SSH密钥提升登陆安全性

恒生LIGHT云社区

Linux SSH

遥遥无期

Tiger

28天写作

Orillusion | 第一个WebGPU中文社区

Orillusion

WebGL 渲染 元宇宙 Metaverse webgpu

白帽近距离|TimeLine Sec安全团队威猛先生

火线安全

大数据埋点如何实现、验证和管理

融云 RongCloud

融云荣获“2021 数字化服务创新成长企业”奖

融云 RongCloud

软件架构被高估,清晰简单的设计被低估_文化 & 方法_Gergely Orosz_InfoQ精选文章