“软件架构师”这个职位在全球众多最佳职位列表中名列前茅。然而,当读者查看这些清单上的其他工作(如执业护士或财务经理)时,就会发现他们有一条清晰的职业道路。为什么软件架构师却没有定义呢?
首先,业界对软件架构本身并没有很好的定义。当我们教授基础课程时,学生们经常要求对软件架构师的工作进行简明定义,而我们坚决拒绝给出。我们不是唯一的。在著名的白皮书“Who Needs an Architect ?”中,著名的马丁.福勒同样拒绝尝试定义它,而是求助于名言:
架构是关于重要的东西……不管那是什么。
——拉尔夫·约翰逊
我们创建了图 1-1 中所示的思维导图,该图非常不完整,但表明了软件架构的范围。事实上,我们很快就会提供我们对软件架构的定义。
其次,如思维导图中所示,软件架构师的角色体现了大量和不断扩大的责任范围。十年前,软件架构师只处理架构的纯技术方面,例如模块化、组件和模式。然后,由于利用更广泛功能(如微服务)的新架构风格,软件架构师的角色得到了扩展。我们在第 13 页的“架构与……的交集”中介绍了架构与组织其余部分的许多交集。
图 1-1 软件架构师的职责包括技术能力、软技能、操作意识和许多其他职责
第三,由于软件开发生态系统的快速发展,软件架构是一个不断变化的目标。今天的任何定义都将在几年后无可救药地过时。维基百科对软件架构的定义提供了一个合理的概述,但许多陈述已经过时,例如“软件架构是关于做出基本的结构选择,一旦实施,改变成本很高。”然而,架构师设计了微服务等现代架构风格,并采用了增量内置的思想——在微服务中进行结构更改不再昂贵。当然,这种能力意味着与其他问题的权衡,例如耦合。许多关于软件架构的书籍将其视为静态问题;一旦解决,我们就可以安全地忽略它。然而,我们在整本书中都认识到软件架构的内在动态特性,包括定义本身。
第四,很多关于软件架构的材料只有历史相关性。维基百科页面的读者一定会注意到令人眼花缭乱的缩写词和对整个知识领域的交叉引用。然而,其中许多首字母缩略词代表了过时或失败的尝试。即使是几年前完全有效的解决方案现在也行不通了,因为环境已经改变了。软件架构的历史充斥着架构师尝试过的东西,只是为了实现破坏性的副作用。我们在本书中涵盖了其中的许多课程。
为什么现在要一本关于软件架构基础的书?软件架构的范围并不是开发世界中不断变化的唯一部分。新技术、新技术、新能力……事实上,找到过去十年没有变化的东西比列出所有变化更容易。软件架构师必须在这个不断变化的生态系统中做出决策。因为一切都在变化,包括我们做出决策的基础,架构师应该重新检查一些核心公理,这些公理为早期关于软件架构的著作提供了信息。例如,早期有关软件架构的书籍没有考虑 DevOps 的影响,因为在编写这些书籍时它还不存在。
在学习架构时,读者必须牢记,就像许多艺术一样,它只能在上下文中理解。架构师做出的许多决策都是基于他们所处环境的现实情况。例如,20 世纪晚期架构的主要目标之一包括最有效地利用共享资源,因为当时所有的基础设施都是昂贵且商业化:操作系统、应用进程服务器、数据库服务器等。想象一下走进 2002 年的数据中心并告诉运营主管“嘿,我有一个革命性架构风格的好主意,其中每个服务都在自己独立的机器上运行,有自己的专用数据库(描述我们现在所知道的微服务)。所以,这意味着我需要 50 个 Windows 许可证、另外 30 个应用进程服务器许可证和至少 50 个数据库服务器许可证。”在 2002 年,尝试构建像微服务这样的架构将是难以想象的昂贵。然而,随着开源在其间几年的出现,加上通过 DevOps 革命更新的工程实践,我们可以合理地构建所描述的架构。读者应该记住,所有架构都是其上下文的产物。
1.1 定义软件架构
整个行业一直在努力准确定义“软件架构”。一些架构师将软件架构称为系统蓝图,而另一些架构师则将其定义为开发系统的路线图。这些通用定义的问题在于理解蓝图或路线图实际包含的内容。比如架构师分析一个架构,分析什么?
图 1-2 说明了一种思考软件架构的方法。在这个定义中,软件架构由系统结构(表示为支持架构的粗黑线)、系统必须支持的架构特征(“-ilities”)、架构决策和最终的设计原则组成。
图 1-2 架构由结构与架构特征(“-ilities”)、架构决策和设计原则相结合组成
如图 1-3 所示,系统的结构是指实现系统的架构样式类型(例如微服务、分层或微内核)。仅通过结构来描述架构并不能完全阐明架构。例如,假设要求架构师描述一个体系结构,而该架构师回答“这是一个微服务体系结构”。在这里,架构师只谈论系统的结构,而不是系统的架构。还需要了解架构特征、架构决策和设计原则,才能充分理解系统的架构。
图 1-3 结构是指系统中使用的体系结构样式的类型
架构特征是定义软件架构的另一个维度(见图 1-4)。架构特征定义了系统的成功标准,通常与系统的功能正交。请注意,列出的所有特征并不需要了解系统的功能,但它们是系统正常运行所必需的。架构特征非常重要,我们在本书中专门用了几章来理解和定义它们。
图 1-4 架构特性是指系统必须支持的“能力”
定义软件架构的下一个因素是架构决策。架构决策定义了如何构建系统的规则。例如,架构师可能会做出一个架构决策,即只有分层架构中的业务和服务层可以访问数据库(参见图 1-5),从而限制表示层进行直接数据库调用。体系结构决策构成了系统的约束,并指导开发团队确定什么是允许的,什么是不允许的。
图 1-5 架构决策是构建系统的规则
如果由于某些条件或其他约束而无法在系统的一部分中实施特定的体系结构决策,则可以通过称为方差的东西来打破该决策(或规则)。大多数组织都有架构审查委员会 (ARB) 或首席架构师使用的方差模型。这些模型形式化了寻找特定标准或架构决策的差异的过程。特定架构决策的异常由 ARB(如果不存在 ARB 则为首席架构师)进行分析,并根据理由和权衡予以批准或拒绝。
架构定义的最后一个因素是设计原则。设计原则与体系结构决策的不同之处在于,设计原则是指导方针,而不是硬性规定。例如,图 1-6 中所示的设计原则指出,开发团队应该利用微服务架构中服务之间的异步消息传递来提高性能。架构决策(规则)永远无法涵盖服务间通信的所有条件和选项,因此可以使用设计原则为首选方法(在本例中为异步消息传递)提供指导,以允许开发人员选择更多给定特定情况的适当通信协议(例如 REST 或 gRPC)。
图 1-6 设计原则是构建系统的准则
1.2 架构师的期望
定义软件架构师的角色与定义软件架构一样困难。它的范围可以从专家进程员到为公司定义战略技术方向。我们建议不要将时间浪费在定义角色的傻事上,而是关注架构师的期望。
无论给定的角色、头衔或工作描述如何,对软件架构师都有八项核心期望:
- 做出架构决策
- 持续分析架构
- 了解最新趋势
- 确保遵守决定
- 多样化的接触和经验
- 拥有业务领域知识
- 具备人际交往能力
- 理解和驾驭政治
软件架构师角色的有效性和成功的第一个关键取决于理解和实践这些期望中的每一个。
1.2.1 做出架构决策
架构师需要定义用于指导团队、部门或整个企业内的技术决策的架构决策和设计原则。
指南是第一个期望中的关键词。架构师应该指导而不是指定技术选择。例如,架构师可能会决定使用 React.js 进行前端开发。在这种情况下,架构师正在做出技术决策,而不是有助于开发团队做出选择的架构决策或设计原则。相反,架构师应该指导开发团队使用基于反应式的框架进行前端 Web 开发,从而指导开发团队在 Angular、Elm、React.js、Vue 或任何其他基于反应式的 Web 之间做出选择构架。
通过架构决策和设计原则来指导技术选择是很困难的。做出有效的架构决策的关键是询问架构决策是否有助于指导团队做出正确的技术选择,或者架构决策是否为他们做出了技术选择。也就是说,架构师有时可能需要做出特定的技术决策,以保留特定的架构特征,例如可伸缩性、性能或可用性。在这种情况下,它仍将被视为架构决策,即使它指定了特定技术。架构师经常为找到正确的路线而苦恼,因此第 19 章完全是关于架构决策的。
1.2.2 持续分析架构
架构师需要不断分析架构和当前技术环境,然后推荐改进解决方案。
架构师的这种期望指的是架构活力,它评估了三年或更多年前定义的架构在业务和技术发生变化的情况下在今天的可行性。根据我们的经验,没有足够多的架构师将精力集中在持续分析现有架构上。因此,大多数架构都会经历结构衰退的因素,这种情况发生在开发人员进行编码或设计更改会影响所需的架构特征(例如性能、可用性和可伸缩性)时。
架构师经常忘记的这种期望的其他被遗忘的方面是测试和发布环境。代码修改的敏捷性有明显的好处,但如果团队需要数周的时间来测试变更和数月的发布,那么架构师就无法在整体架构中实现敏捷性。
架构师必须全面分析技术和问题域的变化,以确定架构的健全性。虽然这种考虑很少出现在职位发布中,但架构师必须满足这种期望才能保持应用进程的相关性。
1.2.3 紧跟最新趋势
架构师应该跟上最新的技术和行业趋势。
开发人员必须跟上他们每天使用的最新技术,以保持相关性(并保住工作!)。架构师有一个更重要的要求,即了解最新的技术和行业趋势。架构师做出的决定往往是持久的并且难以改变。了解并遵循主要趋势有助于架构师为未来做好准备并做出正确的决定。
跟踪趋势并跟上这些趋势是很困难的,尤其是对于软件架构师而言。在第 24 章中,我们讨论了有关如何执行此操作的各种技术和资源。
1.2.4 确保遵守决定
架构师应确保遵守架构决策和设计原则。
确保合规性意味着架构师不断验证开发团队是否遵循架构师定义、记录和传达的架构决策和设计原则。考虑架构师决定将对分层架构中的数据库的访问限制为仅业务和服务层(而不是表示层)的场景。这意味着表示层必须遍历架构的所有层才能进行最简单的数据库调用。出于性能原因,用户界面开发人员可能不同意此决定并直接访问数据库(或持久层)。但是,架构师出于特定原因做出该架构决策:控制变更。通过关闭层,可以在不影响表示层的情况下进行数据库更改。如果不确保遵守架构决策,就会发生这样的违规行为,架构将无法满足所需的架构特征(“-ilities”),并且应用进程或系统将无法按预期工作。
在第 6 章中,我们将更多地讨论使用自动化适应度函数和自动化工具来衡量合规性。
1.2.5 多样化的经验
架构师应该接触多种多样的技术、框架、平台和环境。
这种期望并不意味着架构师必须是每个框架、平台和语言的专家,而是架构师至少必须熟悉各种技术。现在大多数环境都是异构的,架构师至少应该知道如何与多个系统和服务进行交互,而不管这些系统或服务是用什么语言、平台和技术编写的。
掌握这种期望的最好方法之一是让架构师扩展他们的舒适区。只关注单一技术或平台是一个安全的避风港。一个有效的软件架构师应该积极寻找机会获得多种语言、平台和技术的经验。掌握这种期望的一个好方法是关注技术广度而不是技术深度。技术广度包括你知道的东西,但不是在详细的层次上,结合你知道很多的东西。例如,对于架构师来说,熟悉 10 种不同的缓存产品以及每种产品的优缺点比只精通其中一种产品更有价值。
1.2.6 拥有业务领域知识
架构师应该具有一定水平的业务领域专业知识。
有效的软件架构师不仅了解技术,而且了解问题空间的业务领域。没有业务领域知识,就很难理解业务问题、目标和需求,从而难以设计出满足业务需求的有效架构。想象一下,你是一家大型金融机构的架构师,不了解平均方向指数、随机合约、利率上涨甚至非优先债务等常见金融术语。没有这方面的知识,架构师就无法与利益相关者和业务用户沟通,并且很快就会失去信誉。
我们所知道的最成功的架构师是那些拥有广泛的实践技术知识以及对特定领域的深厚知识的人。这些软件架构师能够使用这些利益相关者知道和理解的领域知识和语言与 C 级主管和业务用户进行有效的沟通。这反过来又增强了人们对软件架构师知道他们在做什么并且有能力创建有效且正确的架构的信心。
1.2.7 具备人际交往能力
架构师应具备出色的人际交往能力,包括团队合作、促进和领导能力。
对于大多数开发人员和架构师来说,拥有卓越的领导能力和人际交往能力是一项艰难的期望。作为技术专家,开发人员和架构师喜欢解决技术问题,而不是人的问题。然而,正如杰拉尔德·温伯格 (Gerald Weinberg) 的名言,“无论他们告诉你什么,这始终是人的问题。”架构师不仅要为团队提供技术指导,还要带领开发团队完成架构的实施。领导技能至少是成为有效软件架构师所需技能的一半,无论架构师的角色或头衔如何。
这个行业充斥着软件架构师,他们都在争夺有限数量的架构职位。拥有强大的领导能力和人际交往能力是架构师从其他架构师中脱颖而出并脱颖而出的好方法。我们认识许多软件架构师,他们是优秀的技术专家,但由于无法领导团队、指导和指导开发人员以及有效地交流想法和架构决策和原则,因此成为低效的架构师。不用说,这些架构师很难保住职位或工作。
1.2.8 理解和驾驭政治
架构师应该了解企业的政治气候并能够驾驭政治。
在一本关于软件架构的书中谈论谈判和驾驭办公室政治似乎很奇怪。为了说明协商技巧的重要性和必要性,请考虑以下场景:开发人员决定利用策略模式来降低特定复杂代码片段的整体圈复杂度。谁真正在乎?人们可能会为开发人员使用这样一种模式而喝彩,但在几乎所有情况下,开发人员都不需要为这样的决定寻求批准。
现在考虑这样一个场景:负责大型客户关系管理系统的架构师在控制来自其他系统的数据库访问、保护某些客户数据以及更改任何数据库模式时遇到问题,因为太多其他系统正在使用 CRM 数据库。因此,架构师决定创建所谓的应用进程孤岛,其中每个应用进程数据库只能从拥有该数据库的应用进程访问。做出这个决定将使架构师更好地控制客户数据、安全性和变更控制。然而,与之前的开发人员场景不同的是,这一决定还将受到公司中几乎所有人的质疑(当然,CRM 应用进程团队可能除外)。其他应用进程需要客户管理数据。如果这些应用进程不再能够直接访问数据库,它们现在必须向 CRM 系统请求数据,这需要通过 REST、SOAP 或其他一些远程访问协议进行远程访问调用。
要点是架构师做出的几乎每一个决定都会受到挑战。由于成本增加或涉及的工作量(时间)增加,架构决策将受到产品所有者、项目经理和业务利益相关者的挑战。认为自己的方法更好的开发人员也会对架构决策提出挑战。在任何一种情况下,架构师都必须驾驭公司的政治并运用基本的谈判技巧来获得大多数决策的批准。这个事实可能会让软件架构师非常沮丧,因为作为开发人员做出的大多数决定不需要批准甚至审查。代码结构、类设计、设计模式选择,有时甚至语言选择等编程方面都是编程艺术的一部分。然而,现在终于能够做出广泛而重要的决策的架构师必须为几乎每一个决策辩护并为之奋斗。谈判技巧,如领导技巧,是如此重要和必要,以至于我们在本书中用了整整一章来理解它们(见第 23 章)。
1.3 架构的交汇点
在过去的十年中,软件架构的范围已经扩大到包含越来越多的责任和观点。十年前,架构和运营之间的典型关系是合同和正式的,有很多官僚主义。大多数公司试图避免托管自己的运营的复杂性,经常将运营外包给第三方公司,并承担服务级别协议的合同义务,例如正常运行时间、规模、响应能力和许多其他重要的体系结构特征。现在,微服务等架构可以自由地利用以前仅供操作关注的问题。例如,弹性扩展曾经痛苦地内置到架构中(参见第15章),而微服务通过架构师和 DevOps 之间的联络来处理它不那么痛苦。
历史:Pets.com 以及我们拥有弹性架构的原因
软件开发的历史包含丰富的经验教训,有好的也有坏的。我们假设当前的功能(如弹性架构)只是某一天出现,因为一些聪明的开发人员,但这些想法往往是从惨痛的教训中诞生的。 Pets.com 代表了一个吸取惨痛教训的早期例子。 Pets.com 出现在互联网的早期,希望成为宠物用品的 Amazon.com。幸运的是,他们有一个出色的营销部门,该部门发明了一个引人注目的吉祥物:一个带有麦克风的袜子木偶,会说些不敬的话。吉祥物成为了超级巨星,出现在公众游行和全国体育赛事中。
不幸的是,Pets.com 的管理层显然把所有的钱都花在了吉祥物上,而不是基础设施上。一旦订单开始涌入,他们就没有准备好。网站速度慢、交易丢失、交货延迟等等……几乎是最坏的情况。事实上,这家公司在经历了灾难性的圣诞节高峰后不久就关门大吉,把唯一剩下的有价值的资产(吉祥物)卖给了竞争对手。
公司需要的是弹性规模:根据需要启动更多资源实例的能力。云提供商将此功能作为一种商品提供,但在互联网的早期,公司必须管理自己的基础设施,许多公司成为以前闻所未闻的现象的受害者:太多的成功会扼杀企业。 Pets.com 和其他类似的恐怖故事促使工程师开发架构师现在喜欢的框架。
以下部分深入探讨了架构师角色与组织其他部分之间的一些较新的交集,强调了架构师的新功能和职责。
1.3.1 工程实践
传统上,软件架构与用于创建软件的开发过程是分开的。存在数十种流行的方法来构建软件,包括瀑布和许多风格的敏捷(如 Scrum,极限编程,精益和 Crystal),这些方法大多不会影响软件架构。
然而,在过去几年中,技术进步将流程问题推到了软件架构上。将软件开发过程与工程实践分开很有用,通过流程,我们指的是如何组建和管理团队、如何进行会议以及工作流程组织;它指的是人们如何组织和互动的机制。另一方面,软件工程实践是指与过程无关的实践,这些实践已经说明了可重复的好处。例如,持续集成是一种经过验证的工程实践,不依赖于特定流程。
从极限编程到持续交付的路径
极限编程 (XP) 的起源很好地说明了过程和工程之间的区别。在 1990 年代初期,以 Kent Beck 为首的一群经验丰富的软件开发人员开始质疑当时流行的数十种不同的开发过程。根据他们的经验,似乎他们都没有创造出可重复的好结果。 XP 的一位创始人说,选择一个现存的流程“并不比掷硬币更能保证项目成功”。他们决定重新考虑如何构建软件,并于 1996 年 3 月启动了 XP 项目。为了告知他们的过程,他们拒绝了传统智能,而是专注于过去导致项目成功的实践,并将其推向了极致。
他们的理由是,他们在之前的项目中看到了更多测试与更高质量之间的相关性。因此,XP 的测试方法将实践发挥到了极致:进行测试先行的开发,确保所有代码在进入代码库之前都经过测试。
XP 被归入其他具有相似观点的流行敏捷过程,但它是为数不多的包含工程实践(如自动化、测试、持续集成和其他具体的、基于经验的技术)的方法之一。继续推进软件开发的工程方面的努力在《Continuous Delivery》(Addison-Wesley Professional)一书中继续进行——许多 XP 实践的更新版本——并在 DevOps 运动中取得成果。在许多方面,DevOps 革命发生在操作采用最初由 XP 支持的工程实践时:自动化、测试、声明性单一事实来源等。
我们强烈支持这些进步,它们形成了渐进的步骤,最终将使软件开发成为一门合适的工程学科。
关注工程实践很重要。首先,软件开发缺乏更成熟的工程学科的许多特征。例如,土木工程师可以比软件结构的类似重要方面更准确地预测结构变化。其次,软件开发的阿喀琉斯之踵之一是估计——多少时间,多少资源,多少钱?这种困难的一部分在于过时的会计实践,无法适应软件开发的探索性,但另一部分原因是因为我们传统上不善于估计,至少部分原因是未知的未知数。
...因为正如我们所知,有已知的已知;有些事情我们知道我们知道。我们也知道有已知的未知数;也就是说,我们知道有些事情我们不知道。但也有未知的未知——那些我们不知道我们不知道的。
—— 美国前国防部长拉姆斯菲尔德
未知的未知是软件系统的克星。许多项目从已知的未知列表开始:开发人员必须了解的领域和他们知道即将到来的技术。然而,项目也会成为未知的未知的牺牲品:没有人知道会突然出现的事情却出乎意料地出现了。这就是为什么所有“预先大设计”软件的努力都会受到影响:架构师无法为未知的未知进行设计。引用马克(您的一位作者)的话:
由于未知的未知因素,所有架构都变得迭代,敏捷只是认识到这一点并更快地做到这一点。
因此,虽然过程在很大程度上与体系结构是分开的,但迭代过程更适合软件体系结构的性质。尝试使用 Waterfall 等过时流程构建现代系统(如微服务)的团队会发现,过时的流程会产生很大的摩擦,而这些流程忽略了软件如何组合在一起的现实。
通常,架构师也是项目的技术负责人,因此决定了团队使用的工程实践。正如架构师在选择架构之前必须仔细考虑问题域一样,他们还必须确保架构风格和工程实践形成共生网格。例如,微服务架构假设自动化机器供应、自动化测试和部署,以及大量其他假设。尝试使用陈旧的运营团队、手动流程和很少的测试来构建其中一种架构会产生巨大的摩擦和成功的挑战。正如不同的问题领域适用于特定的架构风格一样,工程实践也具有相同的共生关系。
从极限编程到持续交付的思想演变仍在继续。工程实践的最新进展允许架构中的新功能。 Neal 的最新著作 Building Evolutionary Architectures (O'Reilly) 重点介绍了思考工程实践和架构交叉点的新方法,从而可以更好地实现架构治理的自动化。虽然我们不会在这里总结那本书,但它提供了一个重要的新术语和思考架构特征的方法,这将渗透到本书的其余部分。 Neal 的书涵盖了构建随时间优雅变化的架构的技术。在第 4 章中,我们将体系结构描述为需求和附加关注点的组合,如图 1-7 所示。
图 1-7 软件系统的体系结构由需求和所有其他体系结构特征组成
正如软件开发领域的任何经验所表明的那样,没有什么是一成不变的。因此,架构师可以设计一个系统来满足某些标准,但该设计必须在实施(架构师如何确保他们的设计被正确实施)和软件开发生态系统驱动的不可避免的变化中生存下来。我们需要的是一个进化的架构。
Building Evolutionary Architectures 引入了随着时间的推移使用适应度函数来保护(和管理)架构特征的概念。这个概念来自进化计算。在设计遗传算法时,开发人员可以使用多种技术来改变解决方案,迭代地演化出新的解决方案。在为特定目标设计这样的算法时,开发人员必须测量结果以查看它是否更接近或更远离最佳解决方案;该度量是一个适应度函数。例如,如果开发人员设计了一种遗传算法来解决旅行商问题(其目标是各个城市之间的最短路线),则适应度函数将查看路径长度。
Building Evolutionary Architectures 吸收了这个想法来创建架构适应性功能:对某些架构特征的客观完整性评估。这种评估可能包括各种机制,例如指标、单元测试、监视器和混沌工程。例如,架构师可能将页面加载时间识别为架构的重要特征。为了允许系统在不降低性能的情况下进行更改,该架构构建了一个适应度函数作为测试,用于测量每个页面的页面加载时间,然后将测试作为项目持续集成的一部分运行。因此,架构师总是知道架构关键部分的状态,因为他们有每个部分的适应度函数形式的验证机制。
我们不会在这里详细介绍健身功能。但是,我们将在适用的情况下指出方法的机会和示例。请注意适应度函数执行的频率与它们提供的反馈之间的相关性。您会发现,采用持续集成、自动机器配置和类似实践等敏捷工程实践可以更轻松地构建弹性架构。它还说明了架构如何与工程实践交织在一起。
1.3.2 运营/开发运营
随着 DevOps 的出现,架构与相关领域之间最明显的交集出现了,这是由对架构公理的一些重新思考所驱动的。多年来,许多公司都将运营视为独立于软件开发的职能;作为节省成本的措施,他们经常将业务外包给另一家公司。许多在 1990 年代和 2000 年代设计的架构都假定架构师无法控制操作,并且围绕该限制进行了防御性构建(有关这方面的一个很好的例子,请参见第 15 章中的基于空间的架构)。
然而,几年前,一些公司开始尝试将许多操作问题与架构结合起来的新形式的架构。例如,在 ESB 驱动的 SOA 等旧式架构中,该架构旨在处理诸如弹性扩展之类的事情,从而使流程中的架构变得非常复杂。基本上,由于外包操作的成本节约措施,架构师被迫围绕引入的限制进行防御性设计。因此,他们构建了可以在内部处理规模、性能、弹性和许多其他功能的架构。该设计的副作用是架构要复杂得多。
微服务架构风格的构建者意识到这些操作问题最好由操作来处理。通过在架构和操作之间创建联系,架构师可以简化设计并依靠操作来处理他们最擅长的事情。因此,意识到资源的滥用会导致意外的复杂性,架构师和运维人员联手创建微服务,我们将在第 17 章中详细介绍。
1.3.3 过程
另一个公理是软件架构在很大程度上与软件开发过程是正交的;您构建软件(过程)的方式对软件体系结构(结构)的影响很小。因此,虽然团队使用的软件开发过程对软件架构有一定影响(尤其是围绕工程实践),但从历史上看,它们大多被认为是独立的。大多数关于软件架构的书籍都忽略了软件开发过程,对诸如可预测性之类的事情做出似是而非的假设。然而,团队开发软件的过程对软件架构的许多方面都有影响。例如,由于软件的性质,过去几十年许多公司都采用了敏捷开发方法。敏捷项目中的架构师可以采用迭代开发,因此可以采用更快的决策反馈循环。这反过来又允许架构师更加积极地进行实验和其他依赖反馈的知识。
正如 Mark 先前的引述所言,所有架构都变得迭代;这只是时间问题。为此,我们将自始至终假设一个敏捷方法的基线,并在适当的时候指出异常。例如,由于年代久远、政治因素或其他与软件无关的缓解因素,许多单体架构使用较旧的流程仍然很常见。
架构中敏捷方法大放异彩的一个关键方面是重组。团队经常发现他们需要将架构从一种模式迁移到另一种模式。例如,一个团队从单体架构开始,因为它易于引导且快速,但现在他们需要将其迁移到更现代的架构。敏捷方法比计划繁重的过程更好地支持这些类型的变化,因为紧密的反馈循环和 Strangler 模式和功能切换等技术的鼓励。
1.3.4 数据
很大一部分严肃的应用进程开发包括外部数据存储,通常采用关系(或越来越多的NoSQL)数据库的形式。然而,许多关于软件架构的书籍只对架构的这一重要方面进行了简单的处理。代码和数据具有共生关系:一个没有另一个就没有用。
数据库管理员通常与架构师一起为复杂系统构建数据架构,分析关系和重用将如何影响应用进程组合。我们不会在本书中深入研究这种程度的专业细节。同时,我们不会忽视对外部存储的存在和依赖。特别是,当我们讨论架构和架构量子的操作方面时(请参阅第 92 页的“架构量子和粒度”),我们包括重要的外部问题,例如数据库。
1.4 软件架构法则
虽然软件架构的范围几乎不可能广泛,但确实存在统一的元素。作者首先也是最重要的是通过不断地偶然发现软件架构的第一定律:
软件架构中的一切都是一种权衡。
—— 软件架构第一定律
对于软件架构师来说,没有什么是好的、干净的。每一个决定都必须考虑到许多对立的因素。
如果架构师认为他们发现了一些不是权衡的东西,那么他们很可能还没有确定权衡。
—— 推论 1
我们根据结构脚手架、合并原则、特征等来定义软件架构。架构不仅仅是结构元素的组合,这反映在我们的软件架构第二定律中:
为什么比怎么做更重要。
——软件架构第二定律
当我们尝试保留学生在研讨会期间制作架构解决方案时所做练习的结果时,作者发现了这种观点的重要性。因为练习是定时的,所以我们保留的唯一工件是表示拓扑的图表。换句话说,我们捕捉到了他们是如何解决问题的,但没有捕捉到团队做出特定选择的原因。架构师可以查看他们不了解的现有系统,并确定其结构如何
架构有效,但很难解释为什么做出某些选择而不是其他选择。
在整本书中,我们强调了架构师为什么要做出某些决定并权衡利弊。我们还在“架构决策记录”中强调了捕获重要决策的好技术。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库