一家公司决定使用软件解决特定问题,因此它们收集了该系统的需求列表。 有很多种用于需求收集的技术,这些技术通常由团队在软件开发过程中定义。 但是,架构师在设计软件解决方案时还必须考虑许多其他因素,如图4-1所示。
图4-1。软件解决方案由领域需求和架构特性组成
架构师在定义领域或业务需求方面进行协作,但是一个关键的职责是定义、发现和分析软件必须做的与领域功能没有直接关系的所有事情:架构特性。
软件编码和设计时候架构有什么不同呢?很多时候,架构师在定义架构特性方面的作用,系统的重要方面实际与问题域无关。许多组织使用各种术语(包括非功能性需求)来描述软件的这些功能,但是我们不喜欢这些术语,因为它是在自我贬低。架构师创建了该术语以区分架构特性和功能需求,但是从语言的角度来看,命名非功能性的需求会带来负面影响:如何说服团队充分关注“非功能性”的需求?另一个流行的术语是质量特性,我们不喜欢它,原因在于它在做事后的质量评估,而不是系统设计。我们更喜欢架构特性,因为它描述了对架构以及整个系统的成功至关重要的关注点,同时又不影响其重要性。
架构特性满足三个条件:
指定非域设计的注意事项
影响设计的某些结构方面
对于应用程序成功至关重要
我们定义的这些相互联系的组成如图4-2所示。
图4-2。架构特性的不同特征
图4-2中所示的定义除了列出的三个修饰词外,还列出了三个组件:
指定非域设计的注意事项
在设计应用程序时,需求指定应用程序应该执行的操作;架构特性指定了成功的运维和设计标准,涉及如何实施要求以及为何做出某些选择。例如,一个常见的重要架构特性为应用程序指定了一定的性能标准,而这通常不会出现在需求文档中。也没有要求文档指出“避免技术债务”,但这些都是架构师和开发人员的常见设计考虑因素。我们将在“从领域关注的问题中提取架构特性”中深入讨论显式和隐式特性之间的区别。
影响设计的某些结构方面
架构师试图在项目上描述架构特性的主要原因与设计注意事项有关:此架构特性是否需要特殊的结构考虑才能成功?例如,安全实际上是每个项目的关注点,并且所有系统都必须在设计和编码过程中采取预防措施来达到基准。但是,当架构师需要设计一些特殊的东西时,它会上升到架构特性的水平。在下面示例系统中,考虑两种围绕付款的情况:
第三方支付处理
如果在集成点处理付款细节,则该架构不需要特殊的架构考虑。该设计应包含标准的安全措施,例如加密和散列,但不需要特殊的架构。
应用内付款处理
如果正在设计的应用程序必须处理付款程序,则架构师可以为此设计特定的模块,组件或服务,以从架构上隔离关键的安全问题。现在,架构特性对于架构和设计都会有影响。
当然,在很多情况下,即使这两个标准也不足以做出某种决定:在此决策过程中,可能会出现过去的安全事件,与第三方集成的性质以及许多其他标准。它仍然表明了架构师在确定为某些功能进行设计时必须考虑的一些注意事项。
对应用程序成功至关重要
应用程序可以支持大量的架构特性……但不仅于此。对每个架构特性的支持增加了设计的复杂性。因此,对于架构师而言,一项关键工作在于选择最少的架构特性,而不是选择尽可能多的架构特性。
我们进一步将架构特性细分为隐式和显式架构特性。隐式需求很少出现在需求中,但是它们对于项目成功是必不可少的。例如,可用性,可靠性和安全性实际上是所有应用程序的基础,但很少在设计文档中指定它们。架构师必须在分析阶段使用他们对问题域的了解来发现这些架构特性。例如,高频交易的公司可能不必在每个系统中都指定低延迟,但是该问题域的架构师应该知道这个如此重要。显式架构特性往往出现在需求文档或其他特定说明中。
在图4-2中,故意选择三角形:每个定义元素都支持其他元素,而其他元素又反过来支持系统的总体设计。三角形创建的支点说明了这样一个事实,即这些架构特性经常相互影响,从而导致架构师在权衡一词中普遍使用。
已列出架构特性(部分)
架构特性广泛存在于软件系统的范围内,从低级代码特性(如模块化)到复杂的操作关注点(如可伸缩性和弹性)。尽管过去试图将其编撰成法典,但实际并不存在真正的通用标准。相反,每个组织都创建了自己对这些术语的解释。此外,由于软件生态变化如此之快,因此不断出现新的概念,术语,度量和验证,从而为架构特性定义提供了新的机会。
尽管数量众多,规模庞大,但架构师通常将架构特性分为大类。下面几节将介绍一些,并提供一些示例。
运维架构特性
运维架构特性涵盖了性能,可伸缩性,弹性,可用性和可靠性等功能。 表4-1列出了一些运维架构特性。
运维架构特性与运维和DevOps关注点严重重叠,在许多软件项目中形成了这些关注点的交叉点。
架构特性的结构
架构师必须关注代码结构。在许多情况下,架构师对代码质量问题负全责或共同承担责任,例如良好的模块化,组件之间的松耦合,代码可读性以及许多其他内部质量评估。表4-2列出了一些结构架构特性。
交叉切割架构特性
虽然许多架构特性可以轻松的识别,许多不属于或违反分类标准但仍构成重要的设计约束和考虑因素。表4-3说明了其中一些。
任何架构特性列表都必然是不完整的列表。任何软件都可以基于独特因素来发现重要的架构特性(例如,请参阅“ Italy-ility””)。
ITALY-ILITY
Neal的一位同事讲述了一个有关架构特性的独特性质的故事。她为一个需要集中式架构的客户工作。然而,对于每个提出的设计,客户的第一个问题是“但是,如果我们意大利分开,会发生什么?” 多年前,由于通讯中断,公司总部与意大利分支机构失去了联系,这在组织上造成了很大的创伤。因此,对所有未来架构的坚决要求是,该团队最终将其称为Italy-ility,他们都知道这意味着可用性,可恢复性和弹性的独特组合。
此外,前面的许多术语都是不精确和模棱两可的,有时是因为微妙的细微差别或缺乏客观的定义。例如,互操作性和兼容性可能看起来是等效的,这在某些系统中是正确的。但是,它们之间存在差异,因为互操作性意味着易于与其他系统集成,而后者又意味着已发布的、已注册的API。另一方面,兼容性更关注行业和领域标准。另一个例子是易用性。 一个定义是用户学习使用软件的难易程度,另一个定义是系统可以自动了解其环境以使用机器学习算法进行自我配置或自我优化的级别。
许多定义重叠。例如,考虑可用性和可靠性,它们几乎在所有情况下都重叠。但是请考虑基于TCP的互联网协议UDP。UDP通过IP可用,但不可靠:数据包可能会在传输中乱序,接收方可能不得不再次要求丢失数据包。
没有完整的标准列表。国际标准组织(ISO)发布了按功能组织的列表,与我们列出的许多功能重叠,但主要是建立了不完整的类别列表。以下是一些 ISO定义:
效率
相对于已知条件下使用的资源量的性能度量。这包括时间行为(响应的度量,处理时间和/或吞吐率的度量),资源利用率(使用的资源的数量和类型)和容量(超出最大已建立限制的程度)。
兼容性
产品,系统或组件可以在共享相同硬件或软件环境的同时与其他产品,系统或组件交换信息和/或执行其所需功能的程度。它包括共存(可以在与其他产品共享公共环境和资源的同时有效地执行其所需的功能)和互操作性(两个或多个系统可以交换和利用信息的程度)。
易用性
用户可以针对其预期目的有效,高效且令人满意地使用该系统。它包括适当性可识别性(用户可以识别软件是否适合他们的需求),可学习性(用户可以轻松学习如何使用软件),用户错误保护(防止用户犯错误)和可访问性(使软件可用)给具有最广泛特性和能力的人)。
可靠性
系统在指定条件下指定时间段内运行的程度。 此特性包括以下子类别:成熟度(软件是否满足正常运行下的可靠性需求),可用性(软件可运行且可访问),容错(软件是否在硬件或软件故障的情况下仍按预期运行)和可恢复性(通过恢复任何受影响的数据并重新建立系统的所需状态,软件可以从故障中恢复。
安全
该软件可以保护信息和数据的程度,从而使人员或其他产品或系统拥有与其权限类型和授权级别相适应的数据访问程度。这一系列特性包括机密性(只有授权访问的人才能访问数据),完整性(软件可以防止对软件或数据的未经授权的访问或修改),不可否认性(可以证明已采取行动或事件),问责制(是否可以跟踪用户的用户操作)和真实性(证明用户身份)。
可维护性
表示开发人员可以修改软件以对其进行改进,纠正或使其适应环境和/或要求的变化的有效性和效率。 此特性包括模块化(软件由离散组件组成的程度),可重用性(开发人员可以在多个系统中使用资产或用于构建其他资产的程度),可分析性(开发人员如何轻松地收集有关组件的具体指标)软件),可修改性(开发人员可以在不引入缺陷或不降低现有产品质量的情况下修改软件的程度)和可测试性(开发人员及其他人员测试软件的容易程度)。
可移植性
开发人员可以从一种硬件,软件或系统转移系统,产品或组件的程度 其他操作或使用环境。此特性包括适应性的子特性(开发人员可以有效地并有效地使软件适应不同或不断发展的硬件,软件或其他操作或使用环境),可安装性(可以在指定的环境中安装和/或卸载软件)和可替换性(开发人员以其他软件轻松替换功能)。
ISO列表中的最后一项针对软件的功能方面,我们认为它不属于该列表:
功能适用性
此特性表示在特定条件下使用时,产品或系统提供满足规定和隐含需求的功能的程度。此特性由以下子特性组成:
功能完整——功能集涵盖所有指定任务和用户目标的程度。
功能正确性——产品或系统以所需的精度提供正确结果的程度。
功能适当性——功能在多大程度上促进了特定任务和目标的完成。这些不是架构特性,而是构建软件的动机要求。这说明了如何思考架构特性和问题域之间的关系。我们将在第7章中介绍这种演变。
软件架构中的许多歧义
设计师之间始终感到沮丧的是,缺乏对这么多关键事物(包括软件架构本身的活动)的清晰定义! 这导致公司为相同的事物定义自己的术语,这导致了整个行业的混乱,因为架构师要么使用了不透明的术语,要么更糟的是使用相同的术语来表达完全不同的含义。尽我们所能,我们不能在软件开发领域强加标准术语。但是,我们确实遵循并推荐领域驱动设计的建议,以在同事之间建立并使用一种普遍使用的语言,以帮助确保减少基于术语的误解。
权衡与最不差的架构
由于多种原因,应用程序只能支持我们列出的一些架构特性。首先,每个受支持的特性都需要设计,还需要结构上的支持。其次,更大的问题在于以下事实:每个架构特性通常会对其他特性产生影响。例如:如果架构师想要提高安全性,几乎可以肯定会对性能产生负面影响。应用程序必须进行更多的动态加密,隐藏秘密的间接操作以及可能降低性能的其他活动。
下面的比喻将有助于说明这种相互联系。显然,飞行员经常学习如何驾驶直升机,因为这需要对每只手和每只脚进行控制,切换一只手会影响另一只手。因此,驾驶直升机是一项平衡的工作,它很好地描述了选择架构特性时的权衡过程。架构师设计支持的每种架构特性都可能使总体设计复杂化。
因此,架构师很少能够设计系统并使每个架构特性最大化。通常,决策归结为几个相互竞争的问题之间的权衡。
小提示
永远不要为最好的架构而努力,而是要为最不差的架构而努力。
太多的架构特性导致通用解决方案试图解决每个业务问题,并且这些架构很少起作用,因为设计变得笨拙。
这表明架构师应该努力设计架构,使其尽可能地迭代。如果您可以更轻松地对架构进行更改,则可以减少在第一次尝试中发现确切正确内容的压力。敏捷的软件开发最重要的经验之一就是迭代的价值。这在软件开发的各个级别(包括架构)都适用。
原文 :https://www.jianshu.com/p/524d8670b13e
全书翻译目录:https://www.jianshu.com/p/05711d172dfa
声明:本资料仅供学习交流严禁使用于任何商业用途!请购买正版图书:https://www.oreilly.com/library/view/fundamentals-of-software/9781492043447/cover.html
资料整理和翻译:杨传池Chris IT老兵,人生三大爱好(爱好喝茶,喝酒和喜欢做梦)
10+年的软件研发和项目管理经验;
7+年大型房产信息化、数字化咨询经验;
50+人以上研发团队管理,擅长团队管理和人才梯队建设;
熟悉研发管理、工程构建、体系建设、DevOps和领域建模,掌握IT研发价值链和工具链。