演进式架构-读书笔记

演进式架构.jpg

演进式架构

第1章 软件架构

  1. 向高度动态的(生态)系统中引入变化,可能会产生无法预料的结果。P3
  2. 软件开发体系由所有工具、框架、库以及最佳实践(软件开发领域的技术积累)构成。和生态一样,软件开发体系实现了平衡,开发人员能够理解这个体系并未其添砖加瓦。然后,这种平衡是动态的,随着新事物的不断出现,平衡不断被打破和重建。P3
  3. 有一种不幸的退化叫做架构比特衰减。架构师选择特定的架构模式来满足也无需求及让系统具备某些能力,但这些特征常常意外地随着时间推移而退化。P4
  4. 定义了那些重要的架构特征后,架构师如何保护这些特征不磨损呢?答案是添加演进呢你作为新的架构特征,使其在系统演进时保护其他特征。P5
  5. 持续架构值构建架构的过程没有最终状态,它会随着软件开发体系的不断变化而演进,并保护重要的架构特征。我们不会尝试定义整个软件架构,因为已经存在很多定义了。我们通过引入时间和变化作为头等架构元素来扩展当前的定义。P5
  6. 增量变更描述了软件架构的两个方面:如何增量地构建软件和如何部署软件。P5
  7. 适应度函数,该函数是一种目标函数,用于计算潜在的解决方案与既定目标的差距。在演化计算中,适应度函数决定一个算法是否在持续提升。换句话说,随着每个算法变体的产生,基于设计者对算法“适应度”的定义,适应度决定每个变体的“适应程度”。P6
  8. 对于演进式架构,随着架构的演进,我们有着类似的需求。我们需要评估机制,来评估变化对架构重要特征的影响,并防止这些特征随着时间的推移而退化。适应度函数的隐喻涵盖多种机制,包括度量、测试和其他验证工具。我们采用这些机制来确保架构不会以不良方式变更。当架构师确定了需要保护的架构特征时,他们会定义一个或多个适应度函数来提供保护。P6
  9. 康威提出:社会结构,特别是人与人之间的沟通途径,将不可避免地影响最终的产品设计。P8
  10. 持续式、敏捷式和应急式都表达了随时间不断变化的概念,这确实是演进式架构的关键特征,但是这些术语都没能准确地表达出架构将如何变化,或者说期望的架构最终是什么样子的。虽然这些术语都隐含着环境变化,但是都没能涵盖架构应有的样子。而在演进式架构的定义中,引导的含义反映了我们想实现的架构,即我们的最终目标。P10
  11. 演进式架构主要由三方面构成:增量变化、适应度函数和适当的耦合。P11

第2章 适应度函数

  1. 演进式架构是支持跨多个维度进行引导性增量变更的架构。P13
  2. 引导性这个词表示架构应该朝着某个目标变更或者体现目标。本书借用了进化计算中的一个概念——适应度函数,遗传算法设计用它定义成功。进化计算有多种机制,通过对每一代软件进行小的变更使方案逐渐成形。工程师会评估每一代解决方案的当前状态,来判断当前方案与最终目标的举例。P13
  3. 架构的适应度函数为某些架构特征提供了客观的完整性评估。P13
  4. 我们也可以将全系统适应度函数看作适应度函数的集合,其中每个适应度函数对应架构的一个或多个维度。当适应度函数所对应的维度间存在冲突是,使用全系统适应度函数有助于我们做出必要的权衡。P13
  5. 系统绝不是其组成部分的总和,而是各部分相互作用的产物。P14
  6. 原子适应度函数对单一的上下文执行,用来校验架构的某一维度,比如某个用来验证模块间耦合的单元测试。P16
  7. 整体适应度函数在共享的上下文中运行,综合校验架构的多个维度,比如安全性和伸缩性。P16
  8. 适应度函数间的另一个区别是执行频率。触发式适应度函数基于特定的事件执行,比如开发人员执行单元测试、部署流水线执行单元测试或质量保障人员执行探索性测试。16
  9. 持续式测试不是按计划执行,而是持续不断地验证架构的某些方面,比如事务处理速度。P17
  10. 静态适应度函数的结果是固定的,比如单元测试的二进制结果——成功或失败。P18
  11. 动态适应度函数依赖基于额外上下文变化的因素。某些值会视具体情况而定,比如在大规模运行的情况下,大多数架构师会采用较低的性能指标。P17
  12. 团队应该尽早确定适应度函数,将其作为初步理解全局架构关注点的一部分。团队还应该尽早确定系统适应度函数,来帮助他们确定想实现的变更。比较实现不同架构特征的价值和难度,有助于更早地设置高风险工作的优先级,从而做出能够应对变化的设计。P18
  13. 没能确定适应度函数的团队讲面临如下风险:P18
    • 做出错误的设计选型,最终导致软件构建失败。
    • 做出的设计选型在时间和成本上出现不必要的浪费。
    • 系统无法轻松应对日后的环境变化。

第3章 实施增量变更

  1. 演进式架构的定义暗含了增量变更,这意味着这种架构更容易实现小的增量变更。P21
  2. 持续交付描述了部署流水线机制。和持续集成服务器类似,部署流水线在“监听”到变化后执行一些列验证步骤,每一步都更加复杂。持续交付实践鼓励使用部署流水线将常规项目任务自动化,例如测试、服务器准备和部署等。P26
  3. 将项目的架构关注点(包括演进能力)转换为适应度函数能带来很多好处。P30
    • 适应度函数的结果客观且可量化。
    • 捕捉所有关注点作为适应度函数,创造了一致的执行机制。
    • 适应度函数列表便于开发人员设计部署流水线。

第4章 架构耦合

  1. 演进式架构注重适当的耦合,即如何确定哪些架构维度间应该相互耦合来以最小的开销和成本最大程度地获益。P39
  2. 架构量子则是具有高功能内聚并可以独立部署的组件,它包括了支持系统正常工作的所有结构性元素。在单体架构中,量子就是整个应用架构,每个部署都高度耦合,因此开发人员必须对其进行整体部署。相比之下,微服务架构在架构元素之间定义了物理限界上下文,封装了所有可能变化的部分。这种架构就是为了增量变更而设计的。在微服务架构中,限界上下文作为量子边界,包含了服务所依赖的组件。P40
  3. 分层架构的主要涉及准则是将不同的技术能力分隔到不同的层,每层职责各异。这种架构的主要优点是关注点独立且分离。每一层相对于其它层都是独立的,但能通过明确定义的接口互相访问。这使得对某一层的变更不会影响其他层,同时将相似的代码组织到一起,为该层的专业化和分离提供了空间。P45
  4. 微核架构定义了一个核心系统,核心系统对外提供API来通过插件丰富其功能。在这种架构中架构量子大小有两种:一种来自核心系统,另一种来自插件。P48
  5. 微服务架构通常遵循以下七个原则:P57
    • 围绕业务领域建模:微服务设计的重点是基于业务领域,而不是基于技术架构。因此架构量子反映了限界上下文。一些开发人员错误地认为限界上下代表某个单独的实体,例如客户。相反,它代表某个业务上下文或工作流,例如商品结账。微服务的目标是创建有用的限界上下文,而不是让开发人员构建更小的服务。
    • 隐藏实现细节:微服务的技术架构封装在基于业务领域的服务边界中。每个领域形成一个物理限界上下文。服务间通过传递消息或资源来集成,而不是通过暴露实现细节集成,例如数据库模式。
    • 自动化文化:微服务架构支持持续交付,它使用部署流水线严格地测试代码,并将一些任务自动化。
    • 高度去中心化:微服务形成了一种无共享架构,其目标是尽可能地减少耦合。
    • 独立部署:开发人员和运维人员希望可以独立部署每个服务,反映了服务间的物理限界上下文。
    • 隔离失败:每个服务都应该处理合理的错误场景并在可能的情况下将其恢复。很多DevOps的最佳实践通常在这种架构中出现,例如熔断器模式、舱壁模式等。
    • 高度可观察:在微服务架构中监控和日志成立首要问题。如果运维人员无法监控某个服务,那么它相当于不存在了。
  6. 微服务的主要目标是通过物理限界上下文来隔离领域及理解问题领域。P58
  7. 架构师通常将微服务成为“无共享”架构。这种架构的主要优势是在技术架构层面完全解耦。但是对耦合不满的人通常会提到“不当的耦合”。毕竟,一个没有耦合的软件系统也强不到哪里去。这里的“无共享”实际上是指“没有混乱的耦合点”。P59
  8. 虽然FaaS(功能即服务)能处理弹性的水平扩展,但是调用方必须处理所有的事务行为和其他复杂的协调工作。在传统应用中,通常由后端处理事务协调。然后如果BaaS(后端即服务)不支持该行为,那么协调工作就必然回转嫁给用户接口(服务请求者)。P63
  9. 架构演进的结构限制取决于开发人员处理耦合和功能内聚的水平。P64

第5章 演进式数据

  1. 当耦合的应用需要通过数据库模式变更来演进时会发生什么?如果应用A修改了护具库模式,可能破坏其他两个应用。幸运的是,正如《数据库重构》一书所讨论的,常用扩展/收缩重构模式来化解这种耦合。P70

第6章 构建可演进的架构

  1. 赋予现有架构演进能力取决于三个因素:组件耦合度、工程实践成熟度,以及开发人员构建适应度函数的难易程度。P81
  2. 架构师无法对“元工作比工作更有趣”综合征免疫,这种综合征变现为采用时髦但并不合适的架构,例如微服务。P84
  3. 团队可以通过多种划分方式将单体应用分解成服务:P85
    • 业务功能分组:企业可能有清晰的业务划分直接对应与IT能力。模仿当前业务沟通等级构建的软件无疑应验了康威定律。
    • 事务边界:许多业务需要依附于大量事务边界。当分解单体应用时,架构师经常发现事务耦合是最难解开的。
    • 部署目标:增量变更使得开发人员可以按照不同的计划有选择地发布代码。
  4. 计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决,除非该问题是由间接层太多导致的。P88
  5. 开发人员熟悉工具的好处,缺忽视所要做出的权衡。P93
  6. 服务模板是保证一致性的常见方案。其中包含一系列预配置的公共基础设施库,例如服务发现、监控、日志、度量、认证/授权等。
  7. 可牺牲架构的定义是:在概念验证成功后即被抛弃的架构。因此,在管理上,不应该询问是否该构件一个试验型的系统然后将其抛弃。因为你一定会那样做。因ß此,做好抛弃它的计划,因为你终将如此。P94
  8. 在Fred Brooks提到第二系统综合征时,他指出技术债会影响很多在初期很成功的项目。由于期望膨胀,小的、优雅的、成功的系统往往会演进成为塞满各种功能的庞然大物。业务人员不愿抛弃还在运行的代码,因此架构走向了一直做加法,但从不做减法的不归路。P95

第7章 演进式架构的陷阱和反模式

  1. 反模式:供应商为王反模式。一种完全围绕供应商产品构建的架构,将组织和工具病态地耦合。购买了供应商软件的公司计划通过插件扩充软件包,以丰富供应商软件的核心功能来匹配其业务。然而,很多时候无法将ERP定制到满足所有需求,开发人员发现他们受到了ERP的制约。P103
  2. 与其沦为供应商为王反模式的受害者,我们不如将供应商产品视为集成点。开发人员可以在集成点间构建防腐层,从而避免架构受到供应商工具变更的影响。p104
  3. 复用软件更像是器官移植而不是拼装乐高积木。P108
  4. 代码复用性越高,其可用性越低。换句话说,代码的易用性和复用性往往成反比。当开发人员构建可复用的代码时,他们必然会为了将来开发人员以各种方式使用该代码添加特性。所有针对未来的特性都使得开发人员更难将代码用于单一目的。P109
  5. 微服务避免代码复用,遵循重复优于耦合的理念。该理念认为复用意味着耦合,因此微服务架构是极度解耦的。然后微服务的目标并不是追求冲否,而是隔离领域内的实体。那些共享通用类的服务不再独立。在微服务架构中,Checkout和Shipping应该各自拥有其Customer的内部呈现。复用所带来的好处是虚幻的,除了其自身缺陷,它还会引入耦合。因此,虽然架构师了解重复的缺点,但他们利用重复抵消了耦合过多对架构的局部损害。P109
  6. 当耦合点妨碍了演进或其他重要的架构特征时,通过分叉或重复来打破耦合点。P110
  7. 不要为了架构而构建架构,构建架构是为了解决问题。P110
  8. 几十年来,编写软件的目标没有考虑敏捷性,而是围绕着降低成本、共享资源和其他一些外部约束。因此,很多组织缺乏能够支持演进式架构的基础。P111
  9. 更快的生产周期意味着架构可以更快地演进。因此一个项目的生产周期决定了架构的研究速度。换句话说,演进速度和生产周期成正比。P113

第8章 实践演进式架构

  1. 全功能团队的目标之一便是消除协调摩擦。创痛的团队彼此独立,开发人员通常需要等DBA做出变更或运维人员提供资源。同一个团队包含各种角色能消除不同团队协调所产生的偶然摩擦。P120
  2. 按照业务能力而非职能来组织团队。P121
  3. 亚马逊的“两个披萨团队”模仿了灵长类动物群体的行为。P122
  4. 团队成员间的连接数n(n-1)/2,构建小型团队是为了减少沟通连接。并且,为了消除不同团队间协作所产生的认为摩擦,这些小型团队需要是全功能团队。P124
  5. 文化:特定人群和社会的想法、习俗及社会行为。P124
  6. 架构师能通过提以下问题了解团队的工程文化:P124
    • 是否团队所有人都知道什么是适应度函数,并考虑了解新工具或产品选型对演进新适应度函数的影响?
    • 团队是否衡量了系统与所定义的适应度函数的匹配程度?
    • 工程师是否理解内聚和耦合?
    • 是否讨论了什么领域和技术概念该整合到一起?
    • 团队是基于变更能力还是基于他们想学习的技术来选择解决方案的?
    • 团队对业务变更如何做出反应?他们是否难于完成小的变更,或在小的业务变更上花费了太多时间?
  7. 试验文化:成功的演进离不开试验,但有些公司因为忙于交付而无暇进行试验。成功的试验是经常进行一些小型活动来尝试新的想法并将成功的试验集成到现有系统中。P125
    • 衡量成功的真正标准是在24小时内能完成的试验数量。
  8. 组织可以通过如下几种方式鼓励试验:P126
    • 从外部吸收想法:很多公司派员工参加展会,并鼓励他们寻求新的技术、工具和能更好地解决问题的方法。还有公司将外部建议或顾问作为新想法的来源。
    • 鼓励明确的改进:丰田公司因其持续改善文化而闻名。期望每个人能不断地寻求持续改善,特别是那些最了解问题并负责解决问题的人。
    • 进行探针试验并稳定下来:探针试验是极限编程实践,让团队构建一个临时方案以快速了解某个棘手的技术问题、探索某个不熟悉的领域,或是提升估算的信心。
    • 创造创新时间:谷歌因其“20%的时间”闻名于世,其员工可以将其20%的工作时间用于任意项目。其他公司组织黑个马拉松并允许团队探索新产品或改进现有产品。Atlassian定期召开24小时会议,并称其为Shiplt。
    • 采用基于集合的开发方式:基于集合的开发专注于探索多种方法。咋一看,由于额外的工作,多个可选项很费功夫,但在探索多个选项的同时,团队最终能更好地理解问题,并通过工具和方法找到真正的约束。
    • 连接工程师和最终用户:只有当团队清楚试验的影响,试验才会成功。A/B测试是企业应用这种试验思维的实践。企业的另一种实践是派团队和工程师观察用户是如何与软件交互来完成某项任务的。
  9. 公司不愿抛弃任何具有感知价值的东西,但通常,返工比重写的成本更高。将现有架构转变为可演进的架构的第一步是模块化。因此,开发人员的首要任务是研究当前项目是否具有模块性,并围绕这些发现重建架构。一旦架构变得不那么杂乱,架构师便能轻松地了解底层结构并为重建做出合理的决策。P135
  10. Martin Fowler将牺牲架构定义为“可抛弃的架构”。很多公司需要在开始时构建简单版本来进行市场调查或验证可行性。一旦验证成功,他们可以构建真正的架构来支持已经显现的架构特征。P135
  11. 与其尝试说服组织中的保守人群,不如展示这些想法对其实践的改进。P136
  12. 咨询柔道:柔道作为一种武术,有很多技巧是利用对手的重量进行对抗。咨询柔道则需要找到一个特性的痛点,并将解决该痛点作为案例。P136
  13. 未来已来,只是尚未流行。P136
  14. 任何校验架构的东西都是适应度函数,同等对待这些验证机制使得自动化和验证更加容易。我们希望架构师开始将架构特征视为可评估的事物,而非突发奇想,这样他们能构建出更具回弹性的架构。P138

你可能感兴趣的:(演进式架构-读书笔记)