《架构之道》第1~2章

第1章 元设计方法

元设计方法 = 系统设计 + 项目设计

在系统设计中,元设计方法提出了一种将大系统分解为小模块/组件的方式。该方法能为模块/组件的定义(结构、角色和语义)以及交互设计(这些组件应该如何交互)提供指导。输出是系统的架构。

在项目设计中,该方法帮助我们为管理人员提供构建系统的几个选项。每个选项都是进度、成本和风险的各种组合,还可以作为系统集成的指导,并匹配相应方案以供执行和跟踪。

设计验证是至关重要的,当架构设计不充分或组织无法承受构建系统的压力的时候,就不该让团队启动系统的开发。

  • 首先,设计必须满足客户的要求。
  • 其次,设计必须在组织或团队的约束范围内。

设计的早期验证是必要的。理想情况下,在项目开始的一周内,必须知道这个架构是否合理。

使用元设计方法,只需几天就可以生成整个系统设计,通常只需三到五天,而项目设计所需的时间与此类似。
帕金森定律表明,只要还有时间,工作就会不断扩展,直到用完所有时间。
限制设计时间会迫使架构师做出足够好的设计。

分析瘫痪(analysis-paralysis

分析瘫痪的主要原因是没有识别系统和项目的设计决策树。
事实证明,大多数软件系统有很多共同点,至少决策树的轮廓不仅是相同的,而且在这些系统中也是统一的。
当然决策树的叶子节点会不同。
使用约束条件是决策树剪枝中最有价值的技术之一。
约束越多,设计任务就越容易。

元设计方法的一个重要优点是传达设计思想。

“没有银弹。”

第2章 分解

软件架构是软件系统的高层设计和结构。
识别系统组成部分的行为称为系统分解。

功能分解

功能分解根据系统的功能将系统分解为其构建块。

功能分解带来的问题:

  • 妨碍重用
  • 数量或规模过度
  • 客户端臃肿的组合
  • 多入口
  • 服务臃肿和耦合

何时使用功能分解

这些页面中的派生并不意味着功能分解是一个坏主意。功能分解是一种不错的需求分解技术。它帮助架构师(或产品经理)发现隐藏或隐含的功能区域。从顶部开始,即使是模糊的功能需求,我们也可以将功能分解提升到一个非常精细的级别,揭示需求及其关系,以树状方式排列需求,并识别冗余或互斥的功能。然而,将功能分解扩展到设计中是致命的。需求和设计之间不应该有直接的映射。

领域分解

领域分解:根据业务域(如销售、工程、会计和运输)将系统分解为构建块。

领域分解不起作用的原因是它仍然是变相的功能分解。

每个领域通常都会演变成一个丑陋的功能混杂集,领域内部复杂性会增加。内部复杂性增加能使我们避免了跨域连接的痛苦,因为跨域通信通常会减少为简单的状态更改,而不是触发涉及所有域的所需行为执行的操作。跨域组合更复杂的行为确是非常困难的。在这样的领域分解中,有些功能是根本不可能实现的。

功能分解和领域分解的动机是业务或客户希望尽快获得其特性。问题是,永远不能单独部署一个特性。

功能分解和领域分解的一个关键缺陷与测试有关。有了这样的设计,耦合度和复杂性非常高,开发人员只能进行单元测试。
可悲的现实是,单元测试几乎毫无用处。虽然单元测试是测试的重要组成部分,但它不能真正测试系统。

基于易变性的分解

元设计方法的设计指导是:基于易变性进行分解

基于易变性进行分解识别潜在变化的区域,并将这些区域封装到服务或系统构建块中。然后,将所需的行为实现为易变封装区域之间的交互。

基于易变性进行分解的动机是简单性本身:任何变化都封装在一起,其中包含对系统的影响。

使用功能分解,构建块表示功能性的区域。当一个变更发生时,会影响到架构中的多个组件。因此,功能分解倾向于最大化变化的影响。适应变化是必须避免功能分解的真正原因。

功能分解大大增加了系统的复杂性。一般来说,代码越复杂,其质量就越低。

基于易变性的分解有助于回归测试。组件数量的减少、组件规模的缩小以及组件之间交互的模拟都大大降低了系统的复杂性。

寻找变化的需要是分解的关键标准,而不是功能。

基于易变性的分解的主要挑战与时间、沟通和感知有关。

在软件系统架构中,架构师只能在周期性的重大变革中将一个完整的系统分解为模块。这样的变革性设计平均几年一次。

Dunning-Kruger效应:一个领域中的不熟练的人员倾向于轻视它,相比实际,认识上觉得它不那么复杂、风险要小或要求不那么高。

识别易变性

如何发现变化的事物和易变的事物之间的区别?
在寻找易变性是,我们应该留意那些会对整个系统产生连锁反应的变化或风险。变更不一定让架构失效。

易变轴:

  • 第一个轴是同一个客户随着时间的推移发生的变化。
  • 客户对系统的要求和期望的改变可能在不同的客户之间同时发生。

通常使用易变轴寻找易变性区域的行为是一个迭代过程,与设计本身的因子交织在一起。
轴应该总是独立的。如果变化的区域不能隔离到某一个轴上,这通常意味着它是伪装的功能分解。

客户提供伪装成需求的解决方案极为普遍。

易变列表

在分解系统和创建架构之前,我们应该简单地编制一个易变区域的候选列表,作为需求收集和分析的自然组成部分。
应该持开放的态度来对待这份清单。
该列表是跟踪观察结果和整理思想的有力工具。

  1. 关键观察
    尽早在分解中找出易变区域并映射它们是非常重要的。
  2. 系统分解
    一旦确定了易变区域,就需要将它们封装到架构的组件中。
    从易变区域列表到架构组件的转换几乎不是一对一的。

对于设计,总是从简单和容易的决定开始。这些决策约束了系统,使后续决策更加容易。

易变性和业务

虽然必须封装易变区域,但并不是所有可能更改的内容都应该封装。换言之,可能改变的事情并不一定是易变的。

在系统分解期间,我们必须确定要封装的易变区域和不要封装的区域。
判断有可能改变的事情确实是业务的一部分而无需封装,有两个简单的指标:

  1. 可能的变化是罕见的;
  2. 封装变更的任何尝试都不划算。

识别易变性的另一个有用技术是尝试为竞争对手(或公司的其它部分)设计一个系统。

易变性和寿命

易变性和寿命密切相关。公司或应用程序以同样的方式执行某操作的时间越长,公司继续以同样方式做该事的可能性就越高。