从质量属性到模式:软件架构的关键指引
在软件项目的开发过程中,明确架构需求是至关重要的。而质量属性和质量属性场景为描述架构需求提供了有效的方法。下面我们将深入探讨质量属性以及如何将其与合适的模式进行匹配。
1. 质量属性简介
软件项目的需求主要分为两类:功能性需求和非功能性需求。
-
功能性需求
:描述了软件解决方案必须完成的任务,通常以用例或故事的形式表达。例如,用户与系统交互时执行的操作,像填写订单、更新客户详情、批准贷款等。
-
非功能性需求
:指系统预期具备或展现的属性,常见的有性能、安全性、可用性等方面的要求,也被称为“质量属性”。
以下是质量属性及相关概念的正式定义:
-
质量属性
:软件的一种特性,是适用于质量因素、质量子因素或度量值的通用术语。
-
质量因素
:从管理角度衡量软件对其质量有贡献的属性,通常用“质量属性”来替代这一表述。
-
质量子因素
:将质量因素或质量子因素分解为技术组件,这里称为“具体属性”。
-
度量值
:度量的输出结果或属于度量范围的元素。
-
软件质量度量
:输入为软件数据,输出为单个数值的函数,该数值可表示软件具备影响其质量的给定属性的程度。
大多数驱动软件架构设计的需求来自系统的质量属性,因为质量属性的影响通常是系统级的。例如,我们期望系统整体性能良好,而不仅仅是用户界面部分。不过,也有少量需求可能来自功能性需求。那么,如何确定这些需求呢?答案在于软件架构的定义,质量属性的来源是利益相关者。
利益相关者是对项目有切身利益的人,典型的系统有众多利益相关者,包括客户、最终用户、运维人员、开发团队、测试人员、维护人员和管理层等。在某些系统中,利益相关者甚至可以是股东或普通公众,比如为 911 中心构建新的调度系统。
架构师的一个重要角色是分析质量属性,并设计出既能满足所有功能性需求,又能支持质量属性的架构。然而,质量属性之间有时会相互冲突,例如性能与安全性、灵活性与简单性之间的矛盾。架构师的职责就是在不同的质量属性(以及利益相关者)之间找到平衡,以确保系统的整体质量最大化。
为了解决特定质量属性的需求,可以设计出相应的上下文解决方案(模式)。但仅仅说系统需要“良好的性能”或“可测试性”,并不能明确具体的实现方法。为了辨别哪些模式适用于特定的质量属性,需要更深入地理解质量属性的正式定义,而使用场景是获得这种具体理解的有效途径。
2. 质量属性场景
质量属性场景是简短的、类似故事的陈述,通过功能情况展示质量属性在系统中的体现。它最初是作为评估软件架构的一种方式出现的。软件工程研究所开发了多种评估方法,如架构权衡分析方法(ATAM),该方法基于场景来对比和比较候选架构对不同质量属性的满足情况。
场景可以作为输入,确保质量属性得到实际满足。此外,还可以识别出哪些策略或模式能够使场景得以实现,从而确保质量属性得到满足。ATAM 等评估方法建议构建一个效用树来表示系统的整体效用,场景作为效用树的叶子节点,通过考虑架构如何使场景成为可能来评估架构。
场景通常以包含刺激、上下文和响应的三部分陈述来表达。刺激是系统、用户、其他系统或其他人采取的行动;响应确定系统在刺激发生时的预期行为;上下文指定期望获得响应的环境或条件。例如:
-
刺激
:当执行数据库操作时。
-
上下文
:在正常条件下。
-
响应
:操作应在 100 毫秒内完成。
虽然以这种三部分陈述的方式描述质量属性场景通常更好,因为它使场景更具可验证性和完整性,但这只是一个指导原则,并非强制要求。如果场景以其他形式表达更自然,不必拘泥于这种模板。
了解了质量属性对软件架构的重要性以及如何编写质量属性场景后,就可以重新审视项目中的架构需求,并使用下面的表格来查找与需要解决的挑战相关的模式。
3. 从质量属性到模式
在考虑项目的架构需求时,可以参考以下表格来查找适用的模式。需要注意的是,该列表并非详尽无遗,每个模式还有其他用途,但它仍然是一个很好的起点。
| 质量属性 | 具体属性 | 示例场景 | 相关模式 |
|---|---|---|---|
| 可用性 | 正常运行时间 | 即使与广域网断开连接,服务仍能产生内部结果。 | 主动服务 |
| 可用性 | 减少系统停机时间 | 服务器崩溃时,系统仍可运行。 | 服务实例 |
| 可用性 | 硬件故障恢复能力 | 服务器崩溃时,系统仍可运行。 | 可网格化服务 |
| 可用性 | 硬件故障恢复能力 | 仅一台服务器崩溃时,系统至少以原容量的 50% 继续运行。 | 服务实例 |
| 可用性 | 硬件故障恢复能力 | 服务器崩溃后,系统在两分钟内恢复运行。 | 虚拟端点 |
| 可用性 | 改进故障检测 | 出现故障或性能下降时,系统在规定时间内通过短信提醒管理员。 | 服务看门狗 |
| 可用性 | 变更(部署)工作量 | 正常情况下,为扩展目的添加服务器(包括安装、配置等)不应超过四小时。 | 服务总线 |
| 预算 | 控制硬件成本(TCO) | 网格允许将负载分布在较便宜的硬件上。 | 可网格化服务 |
| 业务驱动因素 | 上市时间 | 新变更的上市时间应少于六个月。 | 客户端/服务器/服务 |
| 可变更性 | 添加功能 | 在三周内将新功能集成到系统中。 | 通信反转 |
| 可变更性 | 替换组件(供应商) | 开发期间,替换信用卡处理网关应在一周内完成。 | 服务总线 |
| 可变更性 | 替换组件(供应商) | 开发期间,替换信用卡处理网关应在一周内完成。 | 编排 |
| 灵活性 | 扩展点 | 预计系统明年需要符合 SOX 合规性,并对所有服务进行审计。 | 边缘组件 |
| 灵活性 | 减少假设 | 正常交互时,服务以“即发即忘”的方式调用。 | 解耦调用 |
| 灵活性 | 时间耦合 | 正常情况下,订单发货后两小时内通知下单方。 | 请求/反应 |
| 灵活性 | 解耦 | 服务之间应尽可能少地了解彼此。 | 通信反转 |
| 灵活性 | 接口 | 开发期间,系统应支持添加 REST API。 | 服务总线 |
| 灵活性 | 业务流程 | 开发和运营期间,为所有订单流程添加超时设置应在一周内完成。 | 编排 |
| 灵活性 | 可组合性 | 开发期间,开发人员能够在多个业务流程中查找和重用服务。 | 编排 |
| 灵活性 | 添加新业务流程 | 正常情况下,向系统添加新的预付费计划并投入生产应在两天内完成。 | 工作流化 |
| 灵活性 | 可变更性 | 正常情况下,更改计费流程以支持新的信用卡清算提供商应在一周内完成。 | 复合前端 |
| 完整性 | 正确性 | 在所有条件下,系统处理的订单都应被计费。 | 传奇模式 |
| 完整性 | 可预测性 | 正常情况下,客户被收取已取消订单费用的概率应低于 5%。 | 传奇模式 |
| 完整性 | 正确性 | 在所有条件下,五个工作日内未收到付款将取消订单和发货。 | 预订模式 |
| 完整性 | 可预测性 | 正常情况下,客户被收取已取消订单费用的概率应低于 5%。 | 预订模式 |
| 互操作性 | 集成 | 运营期间,集成新的子系统应在两个月内完成。 | 服务总线 |
| 可维护性 | 向后兼容性 | 随着合同的演变,服务应能够支持使用旧版本合同的消费者。 | 边缘组件 |
| 可维护性 | 添加服务 | 为新服务配置安全设置,单个开发人员的工作量应少于半天。 | 身份提供者 |
| 可维护性 | 更轻松的升级 | 单个服务实例可以在不影响服务可用性的情况下进行升级。 | 虚拟端点 |
| 可管理性 | 报告 | 管理人员应始终能够全面了解业务请求处理的状态和问题。 | 服务监控器 |
| 可管理性 | 了解系统健康状况 | 出现错误时,管理员应能够了解不同业务流程中的问题和性能瓶颈。 | 编排 |
| 性能 | 延迟 | 评估报价的盈利能力时,不受外部服务调用的延迟影响。 | 主动服务 |
| 性能 | 消除数据丢失 | 系统确认的消息不会丢失。 | 解耦调用 |
| 性能 | 降低延迟 | 即使在峰值负载下,处理传入请求也不会降低延迟。 | 解耦调用 |
| 性能 | 更高的消息吞吐量 | 在压力条件下,系统每秒处理超过 10000 个请求。 | 并行管道 |
| 性能 | 延迟 | 正常情况下,99% 的服务请求应在一秒内完成,100% 的请求应在两秒内完成。 | 可网格化服务 |
| 性能 | 延迟 | 任何请求的身份验证成本不超过 100 毫秒。 | 身份提供者 |
| 性能 | 响应性 | 正常情况下,执行长时间操作(如搜索、重新计算路线等)时,用户界面不会挂起。 | 请求/反应 |
| 性能 | 截止时间 | 在负载和正常条件下,系统应能定期更新股票价格。 | 主动服务 |
| 可移植性 | 安装 | 安装过程中,从一个环境切换到另一个环境应几乎不需要时间。 | 服务主机 |
| 可靠性 | 处理故障 | 从通信断开恢复时,所有中断的进程应保持一致。 | 传奇模式 |
| 可靠性 | 减少数据丢失 | 系统确认的消息不会丢失。 | 事务性服务 |
| 可靠性 | 增加自主性 | 正常运行期间,系统应持续清理所有临时资源。 | 服务看门狗 |
| 可靠性 | 平均修复时间(MTTR) | 正常运行时,发现故障服务的时间应少于两分钟。 | 服务监控器 |
| 可重用性 | 核心模块集定义 | 大多数新计划应重用 90% 以上的通用销售流程活动。 | 工作流化 |
| 可重用性 | 减少开发时间 | 开发期间,为新服务设置环境应在几分钟内完成。 | 服务主机 |
| 可重用性 | 接口 | 所有服务除了满足特定请求外,还应支持通用服务 API。 | 通信反转 |
| 可扩展性 | 处理增加的负载 | 通过添加服务器而不更改软件来处理增加的负载。 | 并行管道 |
| 可扩展性 | 横向扩展 | 能够通过增加硬件来处理增加的服务负载。 | 可网格化服务 |
| 可扩展性 | 横向扩展能力 | 能够通过增加硬件来处理增加的服务负载。 | 服务实例 |
| 安全性 | 欺骗 | 处理消息前,系统应使用发送者的公钥验证签名,防止冒充。 | 安全基础设施,安全消息 |
| 安全性 | 欺骗 | 所有情况下,发送和接收消息时,系统应添加时间戳、序列号或过期时间以应对重播攻击。 | 安全基础设施,安全消息 |
| 安全性 | 抵赖 | 所有通信中,发送消息时系统应添加时间戳并要求签名,防止发送者否认发送消息。 | 安全基础设施,安全消息 |
| 安全性 | 信息泄露 | 发送敏感信息时,系统应加密重要信息(或整个消息),防止他人读取敏感数据。 | 安全基础设施,安全消息 |
| 安全性 | 篡改 | 所有通信中,系统应验证签名,确保请求或响应内容未被更改。签名损坏时,系统应记录并丢弃消息。 | 服务防火墙 |
| 安全性 | 篡改 | 所有通信中,系统应验证消息格式是否正确,丢弃并记录错误消息。 | 服务防火墙 |
| 安全性 | 信息泄露 | 所有通信中,系统应扫描出站消息中的敏感内容,防止发送。 | 服务防火墙 |
| 安全性 | 信息泄露 | 发送消息时,如果回复消息的目标在已知组之外,记录并提醒管理员。 | 服务防火墙 |
| 安全性 | 信息泄露,权限提升 | 所有情况下,处理消息前,系统应检查传入消息是否存在 XPath、SQL 注入攻击和病毒,发现问题时通知管理员。 | 服务防火墙 |
| 安全性 | 拒绝服务 | 正常运行时,攻击者试图向系统发送大量请求时,系统应识别攻击,阻止已知攻击者,忽略其请求并通知管理员。 | 服务防火墙 |
| 安全性 | 权限提升 | 所有情况下,处理传入消息前,系统应验证合同和元素大小,发现问题时提醒管理员。 | 服务防火墙 |
| 安全性 | 身份验证 | 正常运行时,系统应在五分钟内更新撤销的权限。 | 身份提供者 |
| 安全性 | 权限提升 | 所有情况下,授权用户时,系统应确保服务消费者不声称拥有其没有的权限。 | 身份提供者 |
| 安全性 | 治理 | 开发和运营期间,企业架构团队应确保所有服务使用安全通道。 | 服务监控器 |
| 安全性 | 单点登录(SSO) | 正常运行时,用户已通过系统身份验证后,系统不应要求其再次输入凭据。 | 身份提供者 |
| 安全性 | 联合身份验证 | 正常运行时,系统应能够支持对外部服务(第三方管理的服务)进行身份验证。 | 身份提供者 |
| 安全性 | 审计 | 系统应始终跟踪身份验证或授权规则的任何更改。 | 身份提供者 |
| 安全性 | 欺骗 | 处理消息时,系统应验证消息是否带有安全令牌,并根据权限授权访问。 | 身份提供者 |
| 安全性 | 审计 | 系统应始终记录请求者及其请求的审计跟踪。 | 服务监控器 |
| 安全性 | 信息泄露 | 正常运行时,系统应查看消息日志,通过比较消息流量路由与已知和配置的路由来识别中间人攻击。 | 服务监控器 |
| 可测试性 | 测试覆盖率 | 开发期间,所有关键需求的测试覆盖率应达到 100%。 | 事务性服务 |
| 可测试性 | 性能 | 压力测试期间,应能够对系统中每个服务的性能进行计时。 | 服务监控器 |
| 可测试性 | 增加隔离性 | 服务可以与交互的服务隔离进行测试。 | 解耦调用 |
| 可测试性 | 增加组件隔离性 | 测试小的单个组件有助于确保它们在管道中连接时的成功。 | 并行管道 |
| 可测试性 | 覆盖率 | 开发期间,服务的每个功能的测试覆盖率应达到 100%。 | 请求/回复 |
| 上市时间 | 开发便捷性 | 开发期间,在服务中暴露已开发的新功能,实现和测试应在半天内完成。 | 请求/回复 |
| 可用性 | 可操作性 | 正常使用系统时,系统应在不同任务之间重用输入的数据(如个人详细信息),以便最终用户能够流畅地完成业务任务。 | 复合前端 |
| 可用性 | 效率 | 用户学习新功能时,体验应简化,以确保最小的学习曲线。 | 客户端/服务器/服务 |
通过这个表格,可以初步找到与质量属性相关的模式,为解决项目中的架构挑战提供方向。
4. 质量属性与模式匹配的实际意义
在软件架构设计中,将质量属性与合适的模式进行匹配具有重要的实际意义。
4.1 满足利益相关者需求
不同的利益相关者对软件系统有不同的期望和需求。例如,客户可能更关注系统的可用性和性能,以确保业务的正常运行;开发团队可能更关心可维护性和可测试性,以便提高开发效率和代码质量;而运维人员则注重系统的可靠性和可管理性,降低维护成本和风险。通过识别和分析质量属性,并选择相应的模式,可以更好地满足不同利益相关者的需求,提高系统的整体满意度。
4.2 平衡质量属性冲突
如前文所述,质量属性之间可能存在冲突。例如,为了提高系统的安全性,可能需要增加额外的验证和加密机制,这会增加系统的开销,从而影响性能;为了提高系统的灵活性,可能会引入更多的组件和接口,增加系统的复杂性,降低其简单性。架构师需要在这些冲突的质量属性之间找到平衡,选择合适的模式来优化系统的整体质量。例如,在性能和安全性之间,可以采用解耦调用模式,将一些耗时的安全验证操作异步处理,减少对系统性能的影响。
4.3 提高系统的可扩展性和适应性
随着业务的发展和变化,软件系统需要不断地进行扩展和升级。通过选择具有良好扩展性的模式,可以使系统更容易适应新的需求和变化。例如,可网格化服务模式可以通过增加硬件资源来处理增加的负载,实现系统的横向扩展;而工作流化模式可以方便地添加新的业务流程,提高系统的灵活性和适应性。
5. 模式选择的考虑因素
在选择与质量属性匹配的模式时,需要考虑以下几个因素:
5.1 系统的具体需求
不同的系统有不同的需求,需要根据系统的特点和目标来选择合适的模式。例如,对于一个实时性要求较高的系统,如金融交易系统,可能更注重性能和响应性,因此可以选择主动服务模式或并行管道模式;而对于一个安全性要求较高的系统,如电子商务系统,可能需要采用安全基础设施和服务防火墙等模式来保障系统的安全。
5.2 成本和资源限制
在选择模式时,需要考虑成本和资源的限制。一些模式可能需要更多的硬件资源或开发成本,需要在满足系统需求的前提下,选择性价比最高的模式。例如,为了提高系统的可用性,可能需要采用冗余服务器和备份机制,但这会增加硬件成本和维护工作量。因此,需要在可用性和成本之间进行权衡,选择合适的模式。
5.3 技术团队的能力
模式的实现需要一定的技术能力和经验。在选择模式时,需要考虑技术团队的能力和水平,确保团队能够理解和实现所选的模式。例如,一些复杂的模式,如编排模式和服务网格模式,需要团队具备较高的技术水平和实践经验。如果团队的技术能力有限,可能需要选择一些相对简单的模式,或者对团队进行相关的培训和学习。
6. 总结与展望
质量属性和模式的匹配是软件架构设计中的重要环节。通过识别和分析质量属性,使用质量属性场景来明确具体需求,并选择合适的模式,可以设计出满足利益相关者需求、平衡质量属性冲突、具有良好可扩展性和适应性的软件架构。
在实际应用中,需要根据系统的具体情况和需求,综合考虑各种因素,选择最合适的模式。同时,随着软件技术的不断发展和创新,新的质量属性和模式也会不断涌现,需要持续关注和学习,以提高软件架构设计的水平和质量。
为了更直观地展示质量属性与模式匹配的过程,下面给出一个 mermaid 格式的流程图:
graph LR
A[确定系统利益相关者] --> B[分析质量属性]
B --> C[编写质量属性场景]
C --> D[识别质量属性需求]
D --> E[选择相关模式]
E --> F[评估模式可行性]
F --> G{是否满足需求?}
G -- 是 --> H[实施模式]
G -- 否 --> B
H --> I[监控和优化系统]
这个流程图展示了从确定系统利益相关者开始,经过分析质量属性、编写场景、选择模式、评估可行性,到最终实施模式并监控优化系统的整个过程。如果选择的模式不能满足需求,则需要重新回到分析质量属性的步骤,进行调整和优化。
通过以上的分析和介绍,希望能够帮助读者更好地理解质量属性与模式的匹配关系,在软件架构设计中做出更明智的决策。
超级会员免费看
785

被折叠的 条评论
为什么被折叠?



