架构决策
对架构师的主要期望之一就是做出架构决策。架构决策通常涉及应用程序或系统的结构,但也可能涉及技术决策,尤其是当这些技术决策影响架构特征时。无论在什么情况下,一个好的架构决策是能够指导开发团队做出正确技术选择的架构决策。做出架构决策需要收集足够多的相关信息,证明决策的合理性,记录决策并将决策有效地传达给正确的利益相关者。
架构决策反模式
架构决策是一门艺术。不出意外的话,架构师在进行决策时会遇到几种架构反模式。程序员 Andrew Koenig 将反模式定义为:那些一开始看起来似乎是一个好主意,但却会带来麻烦的模式。反模式的另一个定义是:能够产生负面结果的可重复过程。在架构决策过程中,可能会(并且通常会)出现的三种主要架构反模式是
- “掩盖你的资产(Covering Your Assets)”
- “土拨鼠日( Groundhog Day)”
- “电子邮件驱动架构( Email-Driven Architecture)”
这三种反模式通常是一个循序渐进的过程:克服“掩盖你的资产”会导致“土拨鼠日”,而克服“土拨鼠日”则导致“电子邮件驱动架构”。做出有效而准确的架构决策需要架构师克服所有这三种反模式。
掩盖你的资产反模式
尝试做出架构决策时会出现的第一个反模式是掩盖你的资产。当架构师由于担心做出错误选择而避免或推迟做出架构决策时,就会发生这种反模式。
有两种方法可以克服这种反模式。第一种方法是等到最后的责任时刻( last responsible moment)再完成重要的架构决策。最后的责任时刻意味着一直等到你有足够的信息来证明和验证你的决策,但不能等待太久,以避免拖延开发团队或陷入分析瘫痪( Analysis Paralysis)反模式。第二种方法是持续地与开发团队协作,以确保你做出的决策能够按预期实现。这一点至关重要,因为作为一名架构师,你无法掌握特定技术的所有细节以及所有与之相关的问题。通过与开发团队紧密协作,架构师可以在出现问题时及时快速地改变架构决策。
为了说明这一点,假设架构师决定,对于所有与产品相关的参考数据(产品描述、重量和尺寸),依赖这些数据的所有服务实例都需要对它们进行复制并以只读的形式存放在自己的缓存当中,数据的主副本归商品目录服务所有。复制缓存意味着,如果产品信息有任何更改(或者有新产品被添加),商品目录服务将更新其缓存,然后需要通过某个复制(在内存中进行)缓存产品,将产品数据复制到需要该数据的所有其他服务当中。做出此决策的理由是减少服务之间的耦合,并有效共享数据,从而无须进行服务间调用。但是,执行此架构决策的开发团队发现,由于某些服务的一些可扩展性需求,该决策所需要的进程内存比可用内存更大。通过与开发团队紧密协作,架构师可以快速了解问题并调整架构决策来适应这些情况。
土拨鼠日反模式
一旦架构师克服了掩盖你的资产反模式并开始做出决策,就会出现第二个反模式:土拨鼠日反模式。当人们不知道为什么要做出某个决策时,就会发生土拨鼠日反模式,因此它不断地被反复讨论。土拨鼠日反模式是从比尔·默里( Bill Murray)的电影《土拨鼠日》中得名的,影片中每一天都是 2 月 2 日。
发生土拨鼠日反模式的原因是架构师做出了某个架构决策,但无法为该决策提供理由(或无法提供一个完整的理由)。在论证架构决策时,为决策提供技术和业务辩护是非常重要的。例如,架构师可以决定将单体应用分解为多个单独的服务,将应用程序的功能解耦,从而使应用的每个部分使用较少的虚拟机资源,并且可以进行单独维护和部署。虽然这是技术合理性的,但是缺少业务合理性。换句话说,企业为什么要在这种架构重构上花钱?本例中,一个好的业务合理性可能是:更快地交付新的业务功能,从而缩短产品上市时间;另一个可能是减少开发和发布新功能的成本。
ps:经常有人在讨论我想在我们家尝试DDD,但是得不到研发团队支持。我想拆分微服务,但是产品经理不理解balabala......你当然可以为你的“技术冒险”找一个理由,但最好的方式是解决问题出发。
论证决策对业务的价值对于任何架构决策都至关重要。这也是一个首先确定是否应该做出架构决策的试金石。如果某个架构决策不能带来任何业务价值,那么它可能不是一个好的决策,应该重新考虑。
四个最常见的业务合理性包括成本、上市时间、用户满意度和战略定位。当着眼于这些常见的业务合理性时,考虑对业务利益相关者来说紧要的事情就变得很重要。如果业务利益相关者较少关注成本,而更关注上市时间,此时仅依据节省成本来证明特定的决策可能是不正确的。
电子邮件驱动架构反模式
一旦架构师做出了一系列决策并充分证明了这些架构决策的合理性,就会出现第三个架构反模式:电子邮件驱动架构反模式。电子邮件驱动架构反模式是指因遗弃、忘记或者甚至不知道已经做出的架构决策而无法实现该架构决策。这个反模式讲的就是要有效地沟通架构决策。电子邮件是一种很好的交流工具,但它并不是一个好的文档存储库系统。
提高架构决策沟通有效性的方法有很多,通过它们可以很好地避免电子邮件驱动架构反模式。沟通架构决策的第一条规则就是不要在电子邮件正文中包含架构决策,因为这会为该决策创建多个系统记录。很多时候,重要的细节(包括合理性)都不会包含在电子邮件当中,因而会重新陷入土拨鼠日反模式。而且,如果该架构决策被更改或取代,如何让人们收到修订后的决策呢?更好的方法是仅在电子邮件正文中提及决策的性质和上下文,并提供架构决策和相应详细信息的单个系统记录链接(无论它是一个 wiki 页面还是文件系统中的文档)。
有效的架构决策沟通的第二条规则是只通知真正关心架构决策的人。一种有效的方法是编写如下的电子邮件:
“嗨,Sandra,我对服务间的通信做了一个重要的决策,它会直接影响到你。请使用以下链接查看这个决策……”
请注意第一句话中的措辞:“对服务间的通信做了一个重要的决策。”这里交代了决策的上下文,而不是决策本身。第一句话的第二部分更为重要:“它会直接影响到你。”如果某个架构决策不会直接影响这个人,为什么要就这个架构决策打扰人家呢?这是一个很好的试金石,用来确定应该将架构决策直接通知给哪些利益相关者(包括开发人员)。第二句话提供了架构决策的链接,因而保证架构决策仅存储在一个地方,是决策的单一系统记录。
具备架构意义
许多架构师认为,如果架构决策涉及任何特定技术,那它就不是一个架构决策,而是技术决策。事实上并非总是如此。如果架构师因某技术可以支持特定的架构特征(如性能或可扩展性)而决定使用该技术,那么这就是架构决策。
Release It!( Pragmatic Bookshelf 出版社)的作者,著名的软件架构师 Michael Nygard, 通过创造术语“具备架构意义”,解决了架构师应该负责哪些决策(以及什么是架构决策)的问题。Michael 认为,具备架构意义的决策是那些会影响结构、非功能特性、依赖项、接口或构建技术的决策。
结构是指影响架构模式或风格的决策。例如,在一组微服务之间共享数据的决策。该决策影响微服务的界限上下文,并因此影响应用程序的结构。
非功能特性是对正在开发或维护的应用程序或系统很重要的架构特征。如果使用某个技术会影响性能,而性能是该应用程序的一个重要方面,那么使用该技术就是一个架构决策。
依赖项是指系统内组件或服务之间的耦合点,影响整体的可扩展性、模块化、敏捷性、可测试性、可靠性等。
接口是指访问并编制服务和组件的方式,实现方式通常有网关、集成集线器、服务总线、API 代理。接口通常涉及合约的定义,包括合约的版本控制和弃用策略。接口会影响第三方如何使用该系统,因此具备架构意义。
构建技术指的是关于平台、框架、工具甚至流程的决策,尽管这些决策本质上是技术性的,但可能会影响架构的某些方面。