zl程序教程

您现在的位置是:首页 >  后端

当前栏目

2022.23 架构整洁之道

架构 之道 整洁
2023-09-11 14:18:07 时间
这周读了《架构整洁之道》,有不少收获和启发,是本不错的架构方面的书籍,可以开阔视野巩固知识,值得技术人阅读
Bob大叔围绕“架构整洁”这一重要导向,系统地剖析其缘起、内涵及应用场景,涵盖软件研发完整过程及所有核心架构模式。全书分为6部分,第1部分纲领性地提出软件架构设计的终极目标,描述软件架构设计的重点与模式;第2~4部分从基础软件构建编程范式的定义和特征出发,讲到设计原则、组件构建原则,进一步描述函数、组件、服务设计与实现的定律,以及它们是如何有效构建软件系统的整体架构的;第5部分从整洁架构的定义开始,详细阐述软件架构设计过程中涉及的方方面面,包括划分内部组件边界、应用常见设计模式、避开错误、降低成本、处理特殊情况等,并以实战案例将内容有机整合起来;第6部分讲述具体实现细节,提到数据库、web、应用程序框架等都是实现细节。
软件架构的终极目标是,用最小的人力成本来满足构建和维护该系统的需求。现实工作中,追求快速的功能实现是非常常见的事情,但要注意不能只考虑实现成本,还有考虑后期的维护扩展成本。架构设计的核心,是追求软件的可维护性、可扩展性,以便使软件在未来能较为方便地升级改造,以适应未来业务的发展变化,使得软件整个生命周期的总成本最小。
需求分析(书中称为行为价值)和架构设计(书中称为架构价值)的差异在于,需求分析关注系统的功能性需求,即系统对外提供的功能;架构设计关注系统的非功能性需求,即可维护性、可扩展性、灵活性等内在的、长期性的特性。
架构设计和核心代码开发是密不可分的。架构师必须要做一线程序员,亲自编写核心代码。架构师如果不亲身承受因设计不佳而带来的痛苦,就很容易因为不了解一线情况而瞎指挥,从而难以得到一个良好的软件架构。
编程范式核心都是对程序员的权力加以限制。计算机程序实际上是人类思维的载体,如果不对其加以限制和规范,任凭思维的野马自由驰骋,那么随着软件规模的上升,其结果必然是局面失控。迄今为止出现了三种编程范式:结构化编程、面向对象编程、函数式编程。结构化编程的本质,是禁止了goto语句,从而对程序控制权的直接转移进行了限制。面向对象编程的本质,是禁止了函数指针,从而对程序控制权的间接转移进行了限制。函数式编程的本质,是基本禁止了变量赋值语句,只允许在非常严格的限制条件下,才允许更改某个变量的值。函数式编程语言中的变量(Variable)是不可变(Vary)的。不可变性是软件架构设计需要考虑的重点,因为一切并发应用遇到的问题,一切由于使用多线程、多处理器而引起的问题,如果没有可变变量的话都不可能发生。不可变性只有在一定情况下是可行的。
编程范式与软件架构关系相当密切。比如面向对象编程中的多态是我们跨越架构边界的手段,函数式编程是我们规范和限制数据存放位置与访问权限的手段,结构化编程则是各模块的算法实现基础。编程范式解决的问题和软件架构的三大关注重点不谋而合:功能性、组件独立性以及数据管理。
将应用程序的内部服务切分,划分为可变的和不可变的两种组件。不可变组件用纯函数的方式来执行任务,期间不更改任何状态。这些不可变的组件将通过与一个或多个非函数式组件通信的方式来修改变量状态。一个架构设计良好的应用程序应该将状态修改的部分和不需要修改状态的部分隔离成单独的组件,然后用合适的机制来保护可变量。
为了提升组件内部的聚合度,应遵从以下三个原则:(1)REP复用/发布等同原则,即软件复用的最小粒度等同于其发布的最小粒度;(2)CCP共同闭包原则,即将那些为相同目的而修改的类放到同一个组件中,将那些为不同目的而修改的类放到不同组件中;(3)CRP共同复用原则,即把需要共同复用的类放到同一个组件中,不是紧密关联的类不要放在一起。
为了降低组件之间的耦合度,应遵从以下三个原则:(1)无依赖环原则,即不要出现环形依赖;(2)稳定依赖原则,即依赖关系要指向更稳定的方向,一个稳定的、难于修改的组件不应该依赖于一个经常变更的组件;(3)稳定抽象原则,即组件的抽象化程度应该与其稳定性保持一致,稳定组件尽量用接口和抽象类来实现。
一个良好的软件架构从逻辑上大致可以分为用例(流程性业务逻辑)、业务实体(原子业务逻辑)、接口适配器(从抽象到具体的桥梁)、框架与驱动程序(具体技术实现)四个层次,底层依赖于上层,而不能反向依赖。一个良好的软件架构应当能独立于其所使用的程序框架、数据库、UI等技术实现细节,并且具有可测试性。

源码中的依赖关系必须只指向同心圆的内层,即由低层机制指向高层策略,控制流整体是从内向外(DIP)。架构设计的任务就是找到高层策略与低层细节之间的架构边界,同时保证这些边界遵守DIP依赖关系规则。
软件架构师必须仔细权衡成本,决定哪里需要设计架构边界,以及这些地方需要的是完整的边界,还是不完全的边界,还是可以忽略的边界,必须持续观察系统的演进,找到设置边界的优势超过其成本的拐点,那就是实现该边界的最佳时机。
一个良好的软件架构从逻辑上大致可以分为用例(流程性业务逻辑)、业务实体(原子业务逻辑)、接口适配器(从抽象到具体的桥梁)、框架与驱动程序(具体技术实现)四个层次,底层依赖于上层,而不能反向依赖。一个良好的软件架构应当能独立于其所使用的程序框架、数据库、UI等技术实现细节,并且具有可测试性。
架构设计时,需要将软件的高层业务逻辑与底层的技术实现(如UI、数据库、I/O操作等)隔离开来。前者较为稳定,后者容易变化。在设计阶段,应尽量多地考虑高层的业务逻辑,将涉及技术实现的决策尽量向后推移。 
系统应按照用例来划分成不同模块,因为不同的用例在未来往往有不同的变更时间和变更原因。系统的主要用例应该在其系统结构上清晰可见,用例是描述业务逻辑的,不应涉及用户接口这样的细节。