《软件架构:架构模式、特征及实践指南》问题与题解
第一章 概述
1.定义软件架构的四个维度是什么?
软件架构由结构、架构特征、架构决策和设计原则组成。
2.架构决策和设计原则之间的区别是什么?
设计原则和架构决策的不同之处在于,设计原则是指导原则,而不是必须遵守的规则。
3.列出软件架构师的8个核心期望。
指定架构决策、持续分析架构、掌握最新趋势、确保决策被遵守、丰富的经历和经验、具备业务领域知识、具备人际交往能力、了解并驾驭政治。
4.软件架构的第一定律是什么?
软件架构中的一切都是在做权衡。
第一部分 基础
第二章 架构思维
1.描述架构与开发的传统方法,并解释为什么这种方法不再有效。
架构师负责分析业务需求以提取和定义架构特征,选择适合该问题域的架构模式和架构风格,以及负责创建组件(即系统的组成部分)。然后架构师将上述这些产出交给开发团队,由开发团队负责为每个组件创建类图、构建用户界面以及开发和测试。
这种方法将架构师和开发人员隔开,从而导致了与架构相关的所有问题。架构师所做的决策常常无法传达给开发团队,而开发团队对于架构的改动也极少反馈回架构师。按这种方式,架构师与开发团队是割裂的,因此在架构落地中很少能达成最初计划的目标。
2.列出知识金字塔的三个层次,并提供每个层次的例子。
知识金字塔包括“已知”、“已知的未知”、“未知的未知”三个层次。“已知”指代技术人员日常工作用到的技术、框架、编程语言和工具。例如,Java就是Java程序员的“已知”。“已知的未知”指代技术人员稍微了解或听说过,但没有掌握的技术。例如Clojure语言。大多数技术人员都听说过Clojure,也知道这是一种基于Lisp的编程语言,但却不会使用。“未知的已知”是知识金字塔中面积最大的部分,指代能够完美解决技术人员面临的问题的技术、工具、框架和编程语言,但是技术人员甚至都不知道它们的存在。
3.为什么架构师关注技术的广度比关注技术的深度更重要?
因为架构师的职责就是根据功能做出与技术限制相匹配的决策,所以广泛了解各种解决方案是非常有价值的。
4.有哪些方法可以保持技术深度并作为架构师继续实践?
第一种方法是频繁继续概念验证(Proof-Of-Concept,POC)。这种做法不仅要求架构师编写源代码,还要求架构师能够通过考虑实现细节来帮助验证架构决策。
第二种方法是处理一些技术债或架构相关的story问题,使开发团队腾出精力来处理关键的功能性用户问题。同样属于第二种保持编码能力的是在迭代中修复bug。
第三种方法是创建简单的命令行工具和分析器来进行自动化来帮助开发团队完成日常任务。
第四种方法是进行频繁的代码审查。尽管架构师这样做实际上并未编写代码,但他们参与到了源代码中,通过代码审查能确保代码符合架构规则,并在团队中进行指导和辅导。
第三章 模块化
1.共生性是什么意思?
如果一个组件的变更需要修改另一个组件才能保持系统的整体正确性,则两个组件是共生的。共生性包括静态共生性和动态共生性。
2.静态共生性和动态共生性的区别是什么?
静态共生性是指源代码级的耦合,架构师将以下静态共生性的类型视作事务之间相互耦合的程度,无论它们是传入耦合还是传出耦合。
名称共生性(CoN):多个组件必须在实体名称上达成一致。
类型共生性(CoT):多个组件必须在实体类型上达成一致。
意义共生性(CoM)或公约共生性(CoC):多个组件必须在特定值的含义上达成一致。
位置共生性(Cop):多个实体必须就值的顺序达成一致。
算法共生性(CoA):多个组件必须在特定算法中达成一致。
动态共生性,分析运行时调用。下面是对动态共生性不同类型的描述。
执行共生性(CoE):多个组件的执行顺序很重要。
时机共生性(CoT):执行多个组件的时机很重要
值共生性(CoV):当多个值相互关联时,更改必定会一起进行。
身份共生性(CoI):当多个值相互关联时,更改必定会一起进行。
3.类型共生性是什么意思,它是动态共生性还是静态共生性。
类型共生性是指,通常在许多静态类型语言中存在的将变量和参数限制为特定类型的做法。但是这并不是静态型类型的特权,一些动态类型语言也提供了可选类型,比如Clojure和Clojure Spec。
它是属于静态共生性。
4.最弱的共生性形式是什么?
身份共生性
5.最强的共生性形式是什么?
名称共生性
6.在基于代码的共生性中,静态共生性和动态共生性哪个更好?
静态共生性,因为开发人员可以通过很简单的源代码分析来判断静态共生性,同时,现代化的工具使静态共生性的重构变得轻松。比如意义共生性,开发人员可以用含有名称的常量来替换魔术值从而将代码重构成名称共生性,从而改进代码。
第四章 现有的架构特征
1.要将属性视为架构特征,必须满足哪三个条件
明确非领域设计的某个注意事项
影响设计的某些结构项
是否对应用的成功至关重要
2.隐式特征和显示特征的区别是什么,分别举一个例子。
隐式需求很少出现在需求中,但是它们对于这个项目的成功是必不可少的。例如,可用性、可靠性和安全性实际上是所有应用的基础,但很少在设计文档中指定,架构师必须在分析阶段使用他们对问题域的了解来发现这些架构特征。
显示架构特征出现在需求文档或其他特定说明中。
3.提供一个运营性特征的例子。
可用性:系统需要多长时间可用
连续性:灾难恢复能力
性能、可恢复性、可靠性/安全性、健壮性、可伸缩性。
4.提供一个结构特征的例子。
可配置性、可拓展性、可安装性、可利用性/可重复利用性 、本地化、可维护性、可移植性、可支持下、可升级性:能够轻松快速地将服务器和客户端上的应用或解决方案从先前版本升级到新版本。
5.提供一个横切特性的例子。
横切特性也叫跨领域特性。尽管许多架构特征属于易于识别的类别,但也有许多特征属于不合理的分类,但却构成了重要的设计约束和考虑因素。
安全性:是否需要在数据库中对数据进行加密?加密内部系统之间的网络通信?远程用户访问需要使用哪种身份特征。
6.对于可用性或性能而言,哪个架构特征更重要?
对于可用性或性能而言,运营性架构特征更重要。
第五章 识别架构特征
1.说明为什么限制架构应该支持的特征的数量是一个好的实践。
支持太多架构特征会导致架构越来越复杂,因此不要痴迷于架构特征的数量,而要保持设计尽量简单。
2.true或false:大多数架构特征来自业务需求和用户story。
false,一些架构特征来自需求文档中的显示声明。其他方面则来自架构师固有的领域知识,这是领域知识始终对架构师有益的众多原因之一。
3.如果业务利益相关者声明了上市时间(例如,尽快向用户推出新功能和错误修复)是最重要的业务问题,架构需要支持哪些架构特征?
敏捷性,可测试性,可部署性。
4.可伸缩性和弹性之间的区别是什么?
可伸缩性是在不严重降低性能的情况下处理大量并发用户的能力。弹性是处理突发请求的能力。
5.你发现你的公司即将进行几项重大收购,以显著增加其客户基础。应该担心哪些架构特征。
互操作性、可伸缩性、适应性、可拓展性。
第六章 度量和治理架构特征
1.为什么循环复杂度是架构分析的一个重要指标?
过于复杂的代码代表代码的坏味道,如果团队不关注逐渐增加的复杂性,那么这种复杂性将主导代码库。
2.什么是架构适应性函数?如何使用它们来分析架构?
任何对某些架构特征或架构特征组合进行客观的完整性评估的机制。
适应度函数不是供架构师下载的一些新框架,而是提供了分析许多现有工具的新视角。架构特征的验证技术随其特征变化而变化。适应度函数取决于使用它们的方式,与许多现有的验证机制重叠:度量、监视器、单元测试库、混沌工程等。
3.提供一个架构适应度函数的示例,以度量架构的可伸缩性。
4.对于允许架构师和开发人员创建适合的功能的架构特征,最重要的标准是什么?
对这些特征进行度量并进行治理。
第七章 架构特征的范围
1.什么是架构量子,为什么它对架构很重要?
架构量子:对于高功能内聚和同步共生性的可独立部署的工件。
架构量子为架构特征提供了新的范围。在现代系统中,架构师在量子级别而不是系统级别上定义架构特征。通过在较窄的范围内关注重要的运营问题,架构师可以及早发现架构难题,从而导致混合架构。
2.假设系统由一个用户界面和四个独立部署的服务组成,每个服务都包括自己的独立数据库。这个系统会有一个量子还是四个量子?为什么?
四个量子,一个架构量子包括所有必须的组件,与架构的其他部分独立。如果某应用使用数据库,则它就是量子的一部分,因为没有数据库,系统将无法运行。
3.假设系统包括管理部分,管理静态引用数据(例如产品目录和仓库信息),以及管理订单放置的面向客户的部分。这个系统应该有多少量子?为什么?如果你设想有多个量子,管理量子和面向客户的量子可以共享一个数据库吗?如果是这样,数据库需要驻留在哪个量子中?
一个量子,因为它们能存放在一个数据库中。如果有多个量子,管理量子和面向客户的量子不能共享一个数据库。数据库需要驻留在各自的量子中。
第八章 组件化思维
1.我们将组件这个术语定义为应用程序的一个构建块——应用程序所做的事情。组件通常由一组类或源文件组成。组件通常如何在应用程序或服务中显示?
组件在架构中也作为子系统或层出现,是许多事件控制器的可部署工作单元。另一种类型的组件(即服务)倾向于在它自己的地址空间中运行,并通过底层的网络协议(如TCP/IP)或更高层的格式(如REST或消息队列)进行通信,从而在微服务等架构中形成独立、可部署的单元。
2.技术分区和域分区的区别是什么?提供每个例子。
它们对各自支持的顶级划分风格不同。
比如架构师根据技术将架构划分为展示层、业务规则层、服务层、持久层等。
在域驱动设计中,架构师识别相互独立和分离的领域或工作流。微服务架构风格就是基于这种哲学。
3.域分区的优点是什么?
更接近业务功能而不是实现细节的建模。更容易利用逆向康威演习来围绕领域构建跨功能团队、更接近单体和微服务架构风格。消息流匹配问题域、易于将数据和组件迁移到分布式架构中。
4.在什么情况下技术分区优于域分区?
当需要让开发人员能够快速找到代码库的准确类别时。
5.什么是实体陷阱,为什么它不是组件标识的好方法?
当架构师错误地将数据库关系标识为应用程序中的工作流时,就会出现实体陷阱反模式,这种对应在现实生活中很少出现。相反,这种反模式没有考虑到应用程序的实际工作流。使用在实体陷阱影响下创建的组件也往往过于粗粒度,在源代码的打包和总体结构方面没有为开发团队提供任何指导。
6.在确定核心组件时,什么时候可以选择工作流方法而不是参与者/操作方法?
在使用事件和消息的分布式结构(如微服务)中很有效,因为它帮助架构师定义最终系统中使用的消息。