[架构之路-88]:《程序员必读之软件架构》-3-软件需求与架构设计的关系

Posted 文火冰糖的硅基工坊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[架构之路-88]:《程序员必读之软件架构》-3-软件需求与架构设计的关系相关的知识,希望对你有一定的参考价值。

前言

这部分是关于设计软件的整个流程,特别是开始编码前真正需要思考的事情。

第 21 章 架构的驱动力:业务领域的需求

不管你采用哪种流程(传统和计划驱动,或者轻量和可适配的),都有一套常见的东西真正驱动、影响和塑造了最终的软件架构,这就是业务领域的需求。所有的软件架构都是为了满足特定的业务领域需求。

21.1 功能需求

为了设计软件,你需要了解要满足的目标。如果这听起来天经地义,那是因为确实如此。

话虽如此,但有的团队,打着敏捷的旗号,对软件应该向最终用户提供的特性需求还没有高层次理解,就设计甚至构建软件。有人可能会称之为敏捷,但我说这叫愚蠢。

特性或用户故事清单(比如Scrum产品订单1),即使粗糙短小,也是必不可少的。需求驱动架构。

不同的业务领域,功能性需求是不相同的。

21.2 质量属性

非功能需求代表的质量属性反映了服务等级,如性能、可伸缩性、可用性、安全性等。

这些属性主要是技术方面的,可以对最终的架构产生巨大影响,特别是如果你正在构建“高性能”系统,或者你想达到“谷歌级”的运行规模。实现非功能需求的技术解决方案通常是交叉的,因此,需要合并到你所构建系统的基础中。向已有的代码库加入高性能、可伸缩性、安全性、可用性等通常极其困难且耗时。

21.3 约束

我们生活在有约束的现实世界中。

例如,你任职的组织可能对技术选型、部署平台等有一系列细致的约束,能做什么,不能做什么

21.4 原则

约束通常是强加于你的,而原则是你为了将一致性和清晰度引入最终代码库而想采用的原则(例如编码规范、自动化测试的使用等)或架构的原则(如分层策略,架构模式等)。

21.5 理解明确需求对系统架构设计的重大影响

任何时候当你开始为一个新的软件系统工作或扩展已有的软件系统,在高层次上理解需求、约束和原则都至关重要。

为什么?简言之,要开始设计选型,这是你所需知识的基本水平

(1)缩小范围

首先,了解这些东西可以帮助减少摆在你面前的可选项,特别是如果你发现驱动力包括了复杂的非功能性需求或者像部署平台的限制之类的主要约束。T.S.艾略特(T.S.Eliot)说过:当被迫工作在一个严格的框架下,想象力被迫发挥到极限,迸发出丰富的点子。完全的自由可能会让工作变得杂乱无序。

(2)上下文语境

其次,也许是最重要的,那就是根据特定的目标和语境,做出“明智”的设计决策。如果不了解金融风险系统相关的性能(比如计算复杂度)、可伸缩性(比如数据量)、安全性和审计等需求,就开始为其设计解决方案,你设计出的解决方案很可能不符合目标

软件架构谈论的是重要的设计决策,其重要性以变动的成本来衡量。对于那些从根本上塑造了最终软件架构的重要决策而言,起点是在高层次上对需求、约束和原则的理解早些理解它们,将有助于避免将来昂贵的返工

第 22 章 质量属性(非功能需求)

当你收集需求时,人们会很乐意给你一个愿望清单,写满了他们想要软件系统完成的事;也有完善的方法以用户故事、用例、传统的需求规格书、验收标准等形式来捕捉这一信息。这些称为功能性需求。

那么,那些讨厌的“非功能性需求”呢?

非功能性需求通常被看作是“能力”,主要跟服务质量有关。按理说,比非功能性需求更好的说法是“系统特征”或“质量属性”,但不太常用。

哪些对你重要? 我们可以为自己的软件系统指定的质量属性有很多,但它们的重要性不尽相同。根据工作的环境和构建的软件系统的类型,有些质量属性比其他的更为适用。金融行业中基于Web的系统的质量属性可能就不同于电信行业使用的内部系统。我建议学习你的领域内常用的质量属性,在开始构建一个新系统或修改已有系统时,先关注这些常用的质量属性。

下面大致列出了常见的质量属性:

1. 性能

性能就是一个东西有多快,通常指响应时间或延迟

(1)响应时间:从发出请求到收到响应所用的时间,比如用户点击网页中的超链接或桌面应用程序中的按钮。

(2)延迟:消息从A点到B点,通过你的系统所用的时间。

就算构建的不是“高性能”软件系统,性能也可应用于Web应用程序、桌面应用程序、面向服务架构、消息系统等几乎所有你要构建的软件系统。如果用户说你的软件“太慢”,你就明白为什么有一些性能的概念很重要。

(3)吞吐量:单位时间处理的信息量

2. 可伸缩性

可伸缩性基本上就是软件处理更多用户、请求、数据、消息等的能力,是软件的拓展已有能力

可伸缩性和并发机制密不可分,因此能在相同的时间内处理更多的东西(比如每秒的请求)。

3. 可用性

可用性是软件对服务请求的可操作和可见程度。你常会看到用“9”来衡量或指代可用性,如99.99%(“四个9”)或99.999%(“五个9”)。这些数字指的是正常运行时间的百分比。

硬币的另一面是可以容忍的停机时间。99.9%(“三个9”)的正常运行时间意味着留给计划维护、升级和意外故障的时间每天只有1分多钟。

4. 安全性

安全性涵盖了从认证和授权到数据在运输和储存中的机密性的所有事情。

和性能一样,安全性很有可能在一定程度上对你很重要。对于部署到互联网的Web应用程序,安全性应该被视为最基础的东西。开放Web应用程序安全项目(OWASP,Open Web Application Security Project)1是学习安全性的一个很好的出发点。

5. 灾难恢复

如果失去一个运行了你的软件的硬盘、服务器或数据中心,会发生什么?灾难恢复处理的就是这些。如果你的软件系统至关重要,就会经常听到人们谈论业务连续性过程,也就是发生灾难事件时,应该做什么才

能保持持续运行的状态。

6. 可访问性

可访问性通常是指像W3C的可访问性标准这样的东西,指的是如何让视觉障碍之类的残疾人也能使用你的软件。

7. 监测

有些组织对于应该如何监测软件系统才能确保它们正常运行和满足服务请求,有特定的需求。

这可能包括将软件与平台特定的监测功能(比如Java平台的JMX)集成,或发生故障时向集中监测仪表发送警报(比如通过SNMP)。

8. 管理

监测通常提供一个软件系统的只读视图,有时会有运行时管理需求。

例如,有必要的话,暴露一些功能,使得操作人员能够修改系统运行时的拓扑结构或配置元素,刷新只读缓存等。

9. 审计

人们往往需要一个引起软件系统中数据或行为变化的事件的日志(即审计日志),特别是涉及钱的时候。通常这些日志需要捕获与变动由谁做出、什么时候做出以及为什么做出相关的信息。变动本身(即变动前后的值)往往也需要记录。

10. 灵活性

灵活性是一个有点滥用和含混的术语,指的是软件执行多个任务,或以不同方式执行单个任务的“灵活性”。一个很好的灵活性需求的例子是非技术人员修改软件内部使用的业务规则的能力。

11. 可扩展性

可扩展性也是滥用和模糊的,但它指的是扩展软件使其可以做一些现在还不能做的事的能力,也许是通过使用插件和API。一些市面上的产品(如微软Dynamics CRM)允许非技术用户扩展存储的数据和改变其他用户与数据交互的方式。

12. 可维护性

可维护性往往被认为是一个需求,但这到底是什么意思?

作为软件开发者,我们通常会努力打造“可维护”的软件,但值得我们思考的是,代码库以后由谁来维护。可维护性很难量化,所以我宁愿思考我们可以遵循的架构和开发原则,因为这些是编写可维护的代码的驱动力。

13. 法律法规

有些行业受到当地法律或监管机构的严格管理,导致了与数据保留或审计日志等相关的额外需求。举个例子,大多数金融机构(投资银行、零售银行、信托公司等)为了保持在市场中的运作能力,必须遵守一些规则(如反洗钱)。

14. 国际化

很多软件系统,特别是部署在互联网上的,不再以单一的语言交付。国际化是指以多种语言交付软件中用户可见元素的能力。这看似简单,当你试图将其加入已有软件时,才会意识到有些语言是从右向左书写的。

15. 本地化

和国际化相关的是本地化,是指以符合最终用户文化习俗的方式展现数字、货币、日期等内容。有时候,国际化和本地化也统称为“全球化”。

第 23 章 处理非功能需求的步骤

不管你怎么称呼它们,往往都需要花费一些精力,来获得可应用于所构建的软件系统的非功能需求清单。

23.1 捕捉

我实际的工作中,客户明确给出非功能需求信息的次数屈指可数。

我当然接到过大量需求规格书或功能需求清单,但很少看到其中包括任何关于性能、伸缩性、安全性等信息。面对这种情况,你就得主动出击,自己去捕捉它们。

23.2 提炼

一旦你开始问那些有关非功能需求的棘手问题,或你已经走运到能收到一些信息,就可能需要提炼它们。

偶尔偶时候,我们接到功能需求规格书中确实包含一些非功能需求的信息,但通常都含糊无用

举个例子,我曾从潜在客户那里收到过一份125页的文档,详述了对软件系统的需求。其中功能需求的细节占据了文档的绝大部分,只有最后半页是留给非功能需求的。里面说道:

性能:系统必须要快;安全性:系统必须安全; + 可用性:系统的运行时间应该达到100%。

虽然不是很有用,但至少能展开一些讨论了。你可以根据交流对象变换问题,而不是问需要多少可用性,然后得到一个不可避免的“24/7”的答案。

比如下面这些:

  • “你能忍受的系统停机时间是多少?”

  • “如果系统核心在朝九晚六的正常工作时间内出现故障,会发生什么?”

  • “如果系统核心在正常工作时间以外出现故障,会发生什么?”

你现在要做的是探索这些非功能性需求,搞清楚驱动力是什么。为什么系统要可见?

当我们谈论“高安全性”,要保护的是什么?

我们的目标是获得一组特定的,理论上可以明确量化的非功能需求。

比如下面这些:

  • 系统平均应该支持多少并发用户?高峰时段呢?

  • 多长的响应时间是可以接受的?系统各个部分都是如此,还是只是针对特定的功能?

  • 为了保护系统安全,我们究竟该怎么做?我们真的需要对数据加密吗,受限访问足够了吗?

如果你能联想到一定数量的非功能性需求(如用户数、数据量、最大响应时间等),就能写一些验收标准并客观地进行测试。

23.3 优先级的挑战

记住这一点,如果问人们是否需要一个东西,无疑我们都知道他们会说“是的”。

这就是为什么很难划分功能需求、用户故事等的优先级。

不管你使用哪一种度量优先级的方法(MoSCoW1,高/中/低,等等),只要尝试划分优先级,每件事最后都会变成“不可或缺”。

你可以创建一个“一定不能少”的目录,但我们知道每件事都会上目录。

这就要换一种方法,提出成本的影响有助于集中注意力。比如下面这些。

架构师:“你需要一个正常运行时间为100%的系统。构建这个系统必须通过大量冗余来消除每一个故障点,我们所有的花费都需要翻一番,外加很多自动故障转移工程的工作。这个成本大概是100万美元。或者我们可以为你构建一个简单一些的系统,必须告诫你,某些组件可能需要进行监测,发生故障时需要手动重启,这样的成本大概是10万美元。您需要哪一种呢?”

担保人:“哦,如果是那样,我要便宜的方案。”

凡事皆有可能,但每件事都有代价解释那些代价有助于找到给定语境中的最好方案。

第 24 章 约束

作为软件开发者,我们创建的每一件东西都存在于现实世界中,而现实世界的资源是有限的,现实世界就有约束。像质量属性一样,约束可以驱动、塑造和影响软件系统的架构。任职的组织或是工作的环境,都会将约束强加于你。约束的形态和大小不尽相同。

24.1 时间和预算的约束

时间和预算可能是大多数软件开发者都熟悉的约束,因为这两者常常都不够。

24.2 技术约束

构建软件的时候,我们经常碰到一些技术相关的约束,特别是在大型组织里。

  • 批准的技术清单:许多大型组织都有一个允许用于构建软件系统的技术清单,目的是限制组织必须支持,运行,维护和购买许可证的技术。如果你想使用任何不在清单上的技术,通常有一个漫长的例外流程,需要提出正式的申请。然而,我仍看到有团队为了能在Java项目中使用Groovy或者Scala而偷偷引入额外的JAR文件!

  • 现有系统的互操作性:在大多数组织中,你的软件需要整合已有的系统,而实现整合的手段往往非常有限。除此之外,就是别的系统需要和你构建的系统整合。在这些情况下,你可能会发现,组织性的约束规定了你可以用于整合的协议和技术。一些我合作过的投资银行就有他们自己内部用来在软件系统间交换交易信息的XML结构。我可不会用“简洁”和“易用”来描述它们!

  • 目标部署平台:构建一个全新的软件系统时,目标部署平台通常是影响技术决策的主要因素之一。这包括嵌入式设备、微软的Windows或Linux服务器的可用性,以及云。是的,即使这个我们称为云的神奇的东西,也有约束。举个例子,每个“平台即服务”(PaaS)提供的都不同,对某些东西,比如本地磁盘操作,你的软件能做什么,不能做什么,大多数都有限制。如果你不明白这些约束,部署时,陪伴你的很可能是焦虑的返工。

  • 技术成熟度:有些组织乐于采用有风险的尖端技术,拥抱这种进步带来的风险。其他组织本质上则保守得多。

  • 开放源代码:同样的,有些组织仍然不喜欢使用开源项目,除非它跟IBM或微软这样的名字扯上关系。我们曾经在一个高街银行1的项目中工作,该银行拒绝使用开源项目,却乐于使用来自一个非常著名的技术品牌的Web服务器。那是伪装过的开源Apache Web服务器。这样的组织在遇到问题的时候就喜欢冲人大喊大叫。开源许可证的混乱也阻碍了一些组织完全采用开源项目。如果你曾试图解释GPL和LGPL的区别,可能已经目睹过这种情况。

  • 供应商“关系”:就像生活中的很多事情,不是你知道什么,而是你认识谁。很多合作关系仍然是供应商请CTO(Chief TechnologyOfficer,首席技术官)吃喝玩乐,在高尔夫球场上“达成”的。如果你曾为大型组织工作,也好奇为什么你的团队被迫使用一些明显不合格的东西,原因可能就是这个!

  • 过去的失败:2000年前后,网盘,我们带着用Java RMI——一种允许通过Java虚拟机进行远程方法调用的技术——构建解决方案的提案走进一家银行。我遇到了很大的阻力,因为这家银行已经“尝试过它,不管用”。那个设计到此为止,任何讨论都没能改变他们的主意。由于过去的失败,Java RMI在这样的环境下被封杀。最终我们转而构建了一个框架,通过HTTP将序列化的Java对象传给一群JavaServlets(变相重新发明轮子)。

  • 内部知识产权:当你需要找到一个库或框架来解决所面临的问题,很可能已经有符合你需要的开源或商业产品。然而对有些人来说这还不够好,你必须使用组织自己内部的日志库、持久化框架或通信基础设施服务。这种情况并不罕见,不管它们是否真能正常工作。最近我听说一个组织构建了自己的CORBA2实现。

24.3 人员约束

更常见的是,开发软件可用的技术和方法受限于你周围的人。比如下面这些。

  • 你的开发团队有多大?

  • 他们有什么技能?

  • 如果你的开发团队需要扩展的话,能有多快?

  • 如果需要的话,你能够提供培训、咨询和专家吗?

  • 如果在交付后转交你的软件,接手的维护团队拥有和你的开发团队相同的技能吗?

  • 如果你让一个Java团队构建一个微软.NET解决方案,相当于给他们当头一棒。

因此,当你架构一个软件系统时,也要把人考虑进来。

24.4 组织约束

你要知道,有时候还有其他约束,包括下面这两个:

  • 软件系统是战术战略实施的一部分吗?这个问题的答案会影响约束的增减。

  • 组织政治有时能阻碍你实现真正想要的解决方案。

24.5 约束都是不好的吗

被强加的约束通常是“坏”的,但往往是出于好的理由。比如,大型组织不愿意支持和维护天底下所有技术,就试图限制最终用于生产的技术。

  • 一方面,这会降低创造力;

  • 但另一方面,它也剔除了你可能面对的大量潜在选项。

软件架构也事关引入约束,在一个代码库里面你到底想要多少个日志库或持久化库?

24.6 约束可以划分优先级

最后一点,值得记住的是,约束可以划分优先级。就像功能需求,有些约束比其他的更重要,利用好这一点。实际上,我们会划分约束的优先级。约束通常是你需要绕过的障碍,但有时候也能相互权衡。

24.7 倾听约束

每一个软件系统都要屈从于一个或多个约束,软件架构角色的一部分就是找出这些约束,搞清楚它们为什么会被强加进来,让它们帮助你塑造软件架构。做不好这件事,搞不好会出大事。

第 25 章 原则

约束是强加于你的,而原则是你为了将标准方法和一致性引入构建软件的方式而想采用的。

通用的原则很多,有些跟开发相关,其他则跟架构相关。

25.1 开发原则

说到原则,很多软件开发者立刻想到的都是关于软件应该如何开发。比如下面这些。

  • 编码标准和规范:“我们将采用内部的[Java|C#|其他]语言编码规范,这可以在我们公司wiki找到。”

  • 自动化单元测试:“我们的目标是核心库的自动化单元测试达到80%的代码覆盖率,无论代码开发是先测试还是后测试。”

  • 静态分析工具:“所有的生产和测试代码在提交到源代码管理之前,必须通过[Checkstyle|FxCop|其他]定义的规则。”等等。

25.2 架构原则

还有一些原则是关于软件结构应该如何安排的。

比如下面这些。

  • 分层策略:因为每一层都独立于周围,分层架构通常出现在有高度灵活性的软件系统中。比如,你可以把软件系统解构为UI(UserInterface,用户界面)层,业务层和数据访问层。使业务层完全独立于数据访问层意味着(通常)可以实现在不影响业务或UI层的情况下切换数据访问。能这样做是因为数据访问层向业务层呈现了抽象,而不是业务层自己直接处理数据存储机制。如果想以这种方式安排软件结构,你就应当确保开发团队里每个人都明白这个原则。“UI组件或域对象里没有数据访问逻辑”是该原则在实践中的一个具体例子。

  • 业务逻辑的位置:有时候,出于性能或可维护性的原因,你要确保业务逻辑总是驻留在一个地方。对于连接互联网的移动应用程序,你可能想要确保服务器尽可能多地处理发生的请求。或者如果你在整合一个已经包含了大量业务逻辑的遗留后端系统,可能想要确保团队里没有人打算复制它。

  • 高内聚、低耦合、SOLID1等:有很多关注点分离相关的原则,专注于构建不需要太多依赖就能完成工作的高内聚的小结构单元。

  • 无状态组件:如果你在构建一个需要很强可伸缩性的软件,那么尽可能把组件设计得无状态,就是一种确保可以通过复制组件来对系统进行横向扩展从而分担负载的方式。如果这是你的可伸缩性策略,每个人都需要明白他们必须使用相同的模式来构建组件。这有助于避免将来出现任何讨厌的意外和可伸缩性瓶颈。

  • 存储过程:关系型数据库的存储过程就像马麦酱2——你对它们不是爱就是恨。用不用存储过程都各有优缺点,但当团队只是选择一种数据访问的方法并坚持,我还是倾向于存储过程。然而,每条原则都有例外。

  • 域模型:丰富与贫瘠:有些团队喜欢在自己的代码中有很丰富的域模型,构建本质上非常面向对象的系统。另一些则倾向于更贫瘠的域模型,对象只是被粗粒度组件和服务使用的数据结构。方法的一致性有很长的路要走。

  • HTTP会话的使用:如果你在构建一个网站,可能想或者不想用HTTP会话来存储请求间的临时信息。这通常取决于很多事情,包括你的伸缩策略是什么,会话支持对象到底存储在哪里,服务器出现故障时会发生什么,你是否使用粘性会话,会话复制的成本,等等。再次,开发团队的每个人都应该明白想要的方法,并坚持下去。

  • 始终一致与最终一致:很多团队都发现,他们往往需要为满足复杂非功能需求做出权衡。比如:有些团队用数据一致性换取性能或可伸缩性。我们能看到所有的Facebook3状态更新,但是否都能立即看到真的重要吗?你的语境将决定立即或延迟的一致性是否妥当,但一致的方法很重要。

25.3谨防最佳实践

如果你经常构建大型企业软件系统,可能考虑过大多数我刚才列出的“最佳实践”原则。但要小心。即使是最善意的原则,有时候也会产生意想不到的负面影响。

如果只是构建一个快速的战术方案,为确保完整的关注点分离而采用复杂的分层策略,也能耗费你大量时间。

原则通常是因为好的理由才引入,但它们并不是任何时候都有好处。

构建软件的大小和复杂度,加上环境的约束,会帮助你决定采用哪些原则。语境一如既往是关键

一份明确的原则清单有助于确保团队中每个人都以相同的方式工作,但你要确保这些原则是帮助而非阻碍。倾听团队成员的反馈会帮助你认清你的原则是否奏效。

第 26 章 技术不是实现细节

26.1 你有复杂的非功能需求吗

确实,大多数软件系统都可以用几乎任何技术构建,Java、.NET、Ruby、Python、php,等等。看看大多数软件系统的数据存储需求,也会发现几乎所有的关系型数据库都能完成任务。大多数软件系统在非功

能特性方面的要求都不高,因此任何主流技术都差不多能满足。

但是,如果你有复杂的非功能需求,比如高性能或可伸缩性,那会怎样?事情很可能开始变得棘手,你必须搞清楚你的技术(和架构)选择是否会管用。如果你不考虑非功能需求,你的软件系统就可能无法满足

目标。

26.2 你有约束吗

对于构建软件可采用的技术和的可选的技能(人),很多组织都有约束。有些甚至断定软件应该购买或定制,而非自己构建。

约束能(且会)影响你能给出的软件架构。可以用各种手段挑战约束,但不能忽视,否则就会有交付一个无法与组织已有的IT环境集成的软件系统的风险

26.3 你有一致性吗

想象你在构建一个把数据存储到关系型数据库的软件系统。在实现功能时,开发者个人如何从数据库检索数据和向其存入数据重要吗?我见过一个Java系统,同一个代码库中采用了多个数据访问技术/框架;还见过一个SharePoint系统,各个组件的配置方式不尽相同。有时候,发生这种事情是因为代码库随着时间演变,方法也在变化,但通常只是开发团队每个人完全自由选择自己最熟悉的任何技术/框架/方法带来的副作用。

人们经常问我“选择哪个日志框架是否真的很重要”,如果你想让开发团队里每个人都使用同一个日志框架,那么是很重要。有些人乐意允许开发团队里任何人下载和使用任何他们想要的开源库。另一些则意识到如果不加以检查,就会导致问题。我不是说要扼杀创新,但你的代码库真的应该只有一个日志、依赖注入或对象关系映射框架。

缺乏一致性的方法会导致代码库难以理解、维护和增强。

增加单独可移部件的数量也会让部署、运营和支持变得复杂。

26.4 推迟技术决策与功能解耦

有必要简单谈谈推迟技术决策和等到“最后责任时刻”才做出决策

让我们想象一下,你在设计一个没有任何特别繁重的非功能需求或约束的软件系统。你选择什么技术重要吗?一个好的架构难道不应该容许你日后改变主意吗?

举个例子,很多人会说,你用哪个关系型数据库真的不重要,特别是如果你用一个对象关系映射层将代码与特定的数据库实现解耦,比如Hibernate、Entity Framework或者ActiveRecord。如果你没有任何重要的非功能需求或约束,并且确实认为所有的关系型数据库都是相等的,那么你用哪一个可能不重要。是的,你可以在代码中解耦数据库,推迟技术决策。但是别忘了,当数据库的选择不再是重要决策,ORM的选择就是了。你可以通过引入另一个抽象层,在代码中解耦ORM,但这里又做了一个软件系统结构的重要决策。

解耦是很好的方法,原因很多,而且它使技术决策得以推迟。当然,这并不意味着你应该推迟决策,特别是由于非功能需求和约束的存在相关的原因。

26.5 每个决策都是权衡

这又回到一个事实,任何技术都有其优缺点,作为可交换的商品,并不一定有不同的选项。对于通常被看作是商业化的技术,关系型数据库和Web应用程序框架是两个典型的例子。很多云服务提供商也是如此,即使他们有各自关于部署、监测、管理、成本、持续磁盘访问等方面的权衡。

一天结束时,不论是否与性能、可伸缩性、可维护性、找到有合适经验的人的能力等方面相关,你做出的每一个技术决策都有权衡。

理解技术选择也能协助高层次的预测和计划,如果你需要明白是否能用给定的有限预算实现目标,这就很有用。如果你不明白选择X技术而非Y的权衡,那就不应该做决策。设计软件系统的人要懂技术,这很重要。这就是为什么软件架构师应该是建造大师。

技术不只是一个“实现细节”,你做出的技术决策跟你分解、安排和设计软件系统的方式同等重要。

推迟技术决策,后果自负。

第 27 章 更多分层等于更高复杂度

额外的富客户端层带来收益的同时,也要考虑到额外引入的复杂度。所有的架构决策都少不了权衡。更多的可移动部件意味着更多的设计、开发、测试和部署工作。不管厂商的市场炒作会怎么说,从来没有什么是免费的,你需要评估给设计增加额外层的优缺点,特别是如果它们产生了额外的进程间通信。

第 28 章 协同设计是一把双刃剑

28.1 技术专家之间的人的协作障碍会影响最终的架构设计

让我们想象一下,你被任命负责建设一个三层的Web应用程序,你有一个由具备Web技术、服务端编程和数据库专长的人组成的小团队。从资源的角度来看,这堪称完美,因为你的团队拥有跨越整个栈的经验。你不应该有任何问题,对吧?

整个团队的有效性取决于很多因素,其中之一是克制自负的情绪,专注于交付给定语境下的最佳解决方案的意愿。有时候,个别人由于缺乏团队合作的经验,或在工作中产生了自负情绪,都会拖团队的后腿。

如果有需求是为用户查看和处理我们的三层Web应用程序上的数据提供一种方式,每一个专家可能都会给你不同的方法。

  • Web开发者:只要给我JSON格式的数据,我们就能用它在Web层做任何想做的事。甚至能加入一些jQuery来动态处理浏览器中的数据;

  • 服务端开发者:我们应该重用和扩展一些中间服务层已有的业务逻辑。这增加了重用,比把全部数据都发到Web层更安全,还能在周围编写自动化单元测试;

  • 数据库开发者:你们都是白痴。不管你们要什么数据,我都能很快地写一个存储过程出来。

在上述情形下的协作架构设计就比较棘手,不同技术领域的人,但站在自己的立场,不让步,虽然有每个技术专家,但最终的架构设计反而越难推进。

在大公司,这种现场经常见到,架构师定义的架构往往并不是技术最好的架构,而是各种团队利益关系综合、权衡后的结果。

28.2 经验影响软件设计

我们拥有的知识、经验和偏好往往会影响我们设计软件的方式,尤其是如果一个人单枪匹马完成。

缺少了交流,我们往往会基于已有的对软件应该如何设计的心智模型,去假设组件应该放在哪里、特性会如何工作。尽早扔掉这些假设有助于避免一些无可挽回的糟糕意外。我倾向于使用白板来设计软件的一个主要原因是它鼓励更加合作的方式,而不是大家都对着自己电脑上最喜欢的建模工具,各自为政。合作,也就是相互沟通和挑战。就像结对编程,合作是处理软件设计流程的一个有效途径,特别是如果用轻量级的方法来做。合作提高了质量,也让我们可以讨论和挑战一些常见的基于自己已有知识、经验和喜好做出的假设。它也为代码集体所有制铺平了道路,有助于打破软件开发团队中常见的孤岛。团队中的每个人都会有不同的想法,但要达成共识。

第 29 章 软件架构是对话的平台

软件的使用者只是利益相关者的一类,他们关注的是系统的功能性特征。

通常还有很多其他的类型,包括下面这些。

  • 当前的开发团队:当前的团队需要了解架构,知道驱动力是什么,这样他们给出的解决方案才会与架构一致,并且“管用”。

  • 未来的开发团队:任何未来的开发、维护团队都需要掌握相同的信息,这样他们才会明白解决方案如何运作,才能以一致的方式修改它。

  • 其他团队:你的软件往往需要和环境中的其他系统集成,从定制的软件系统到厂商的现成产品,因此每个人对它如何工作达成共识是至关重要的。

  • 数据库管理员:有些组织有单独的数据库团队,他们需要了解你的解决方案如何使用他们的数据库服务(比如,从设计和优化到容量规划和归档)。

  • 执行/支持人员:业务人员通常需要了解如何运行和支持你的系统(比如,从配置和部署到监测和故障诊断)。遵守、风险和审计:有些组织有必须遵守的严格规定,你的组织可能也需要证明你们确实遵守了这些规定。

  • 安全团队:对安全也是如此。有些组织有专门的安全团队,系统要经过他们的评审才允许进入生产环境。这些只是一部分可能和你的架构有利害关系的利益相关者,可能还有其他的,这取决于你的组织及其运作方式。如果你认为自己能闭门造车独立完成一个软件架构,你很可能错了。软件架构并非是孤立的,软件设计过程是一个交流的平台。五分钟的交流就有助于捕捉那些往往不起眼的架构驱动力,提高成功交付的机会。

软件架构不仅仅是愿景系统的愿景、期望、设计,各种利益方进行信息交流的载体。他们会站在各自的角度和视角,对软件架构进行审视,并给出自己的意见,这非常有助于确保未来的实现的软件系统,能够满足各方的需求和诉求。各个利益方,不太可能必须等待软件代码实现之后再进行交流,这时候软件架构就显得尤为重要。

以上是关于[架构之路-88]:《程序员必读之软件架构》-3-软件需求与架构设计的关系的主要内容,如果未能解决你的问题,请参考以下文章

[架构之路-86]:《程序员必读之软件架构》-1-什么是软件架构

[架构之路-87]:《程序员必读之软件架构》-2-软件架构师所需要技能

[架构之路-89]:《程序员必读之软件架构》-4-软件架构的可视化

[架构之路-89]:《程序员必读之软件架构》-4-软件架构的可视化

《程序员必读之软件架构》学习: 软件架构文档内容

《程序员必读之软件架构》学习: 软件架构文档内容