架构基础:SOLID、OOA/OOD 与隐式业务显式化
入门与动机 · 第 3/15 篇
上一篇:《流程与模型之痛:Scrum 断层、事务脚本与贫血 MVC》
下一篇:《DDD 宏观与微观概念:限界上下文直觉》
开头:DDD 之前的地基
领域驱动设计不是空中楼阁。要写好领域模型与分层代码,需要 SOLID 原则、面向对象分析与设计(OOA/OOD),以及把 隐式业务逻辑显式化 的习惯——否则容易回到上帝类 + 事务脚本的老路。
本篇梳理这些架构基础,并简要说明与中台化架构的关系,为进入 DDD 战略设计做准备。
一、基本原则:SOLID
SOLID 是 单一职责(SRP)、开闭(OCP)、里氏替换(LSP)、接口隔离(ISP)、依赖倒置(DIP) 的缩写。原则比设计模式更基础,深入理解能显著提升 OOD 能力与代码质量。

1. 单一职责(SRP)
定义:一个类应该只有一个引起它变化的原因——类应高度内聚,只实现一个功能。
实践中常有 上帝类:不该属于一个类的功能也大包大揽,内聚性差 → 难复用 → 只能复制粘贴(Repeat Yourself)→ 一团乱麻。
2. 开闭原则(OCP)
定义:对扩展开放,对修改关闭。面对新需求,应通过 增加代码(继承、装饰者等)实现变化,而非修改已有接口——一改接口,上层调用都要改。
开闭是 OO 设计核心;最好手段是 抽象。防止变异(Protected Variations):识别不稳定处,抽象出稳定接口。不必对程序每个部分都刻意抽象——拒绝不成熟的抽象与抽象本身同样重要。
3. 里氏替换(LSP)
定义:子类型必须能替换父类型,程序功能不受影响,父类才真正可复用。
继承有缺点:子类可修改父类成员,需求变更时其他子类可能跟着变,违反封装。LSP 规范包括:子类可实现父类抽象方法,但不覆盖父类非抽象方法;重载时输入参数可放大、返回值可缩小等。LSP 与 OCP 常相互依存。
4. 依赖倒置(DIP)
定义:不要直接依赖具体实现,双方依赖 抽象(接口) 解耦。
例如日志框架(log4j、logback 等)API 各异,直接依赖则切换痛苦;依赖 Logger 接口,应用与框架解耦,双方可独立演进。
5. 接口隔离(ISP)
定义:客户端不应依赖它不需要的接口——接口要 细、纯,服务依赖建立在 最小接口 上。
注意:ISP 强调 方法少、模块单一;SRP 强调 职责单一——一个职责的接口可有多个方法。原则多为 建议 而非强制;现实中很难「一模块一接口」,过度设计会增加复杂度——在合适场景选合适技术。
6. 迪米特法则(最少知识)
两个类不必直接通信就不应直接互相引用;需调用时可通过第三者转发。强调 低耦合、高内聚——类对耦合类知道得越少,修改波及面越小。成员变量、参数、返回值中的类是 直接朋友;局部变量中的类则不是。
SOLID 不是 OO 的全部,抽象、设计模式、架构模式、UML、读优秀源码同样重要——但 SOLID 更基础,值得优先掌握。
二、解耦上帝类:隐式业务显式化
上帝类的判断
上帝类(God Class) 维护过多职责(违反 SRP),连自己也难读懂。一般同时满足三条可视为上帝类:
| 指标 | 含义 |
|---|---|
| CPFD | 从多个不相关模块引用数据 |
| WOC | 所有方法圈复杂度之和 > 65 |
| TCC | 直接相关 private 方法占比 < 1/3(低内聚) |
过大类承担过多职责,充斥 if-else 与重复代码,是 坏味道 的开始。
简单场景下用 ServiceImpl 一杆捅到 DAO 的 Transaction Script 尚可凑合,但复杂业务会失控。
业务语义显性化
把淹没在 if-else 里的 隐式业务逻辑 抽取出来,用 通用语言 命名、写代码、扩展,变成 显式概念——很多重要业务概念在事务脚本写法里完全看不出来。
要求不只是口头讨论业务名词,更要在实现里 用达成共识的术语 体现在模块划分、Domain 建模、类/方法/变量命名上。
Domain 对象 = 业务语义的载体,代码即文档、代码即业务——让代码像读文章一样易懂,降低复杂度。
DDD 的最大好处之一,就是把晦涩的业务算法通过领域对象与统一语言 清晰显性化。例如核心 分配策略(DistributionPolicy) 若藏在一堆逻辑里,没人知道其领域含义;抽成独立概念并命名后,后续扩展新策略无需改原代码,领域专家也能读懂。

好代码不仅要程序员能读懂,也要让领域专家能读懂。
三、OOA、OOD、OOP
以典型项目阶段说明三者关系(可行性预研略):
| 阶段 | 英文 | 作用 | 产出 |
|---|---|---|---|
| 面向对象分析 | OOA | 需求 → 领域模型 | 用例、概念类及关系 |
| 面向对象设计 | OOD | 领域模型 → 逻辑架构 | 类图、时序图、状态机、包图 |
| 面向对象编程 | OOP | OOD → 代码 | 可运行实现 |
OOA:根据需求输出用例(用户与系统交互场景),再输出 领域模型(Domain Model) 与概念类及其关系——概念类反映现实事物。
OOD:决定如何分层、分包,保证高内聚低耦合,输出类图、交互图等。
OOP:按 OOD 结果编码。

DDD 中的战略建模(事件风暴、用例分析等)与 OOA/OOD 一脉相承,只是更强调 统一语言 与 限界上下文。
四、中台化架构(略)
2015 年起 中台 被广泛讨论:将通用、可复用的业务能力沉淀到中台模型,实现 企业级能力复用。中台落地仍面临 微服务设计与拆分 问题——DDD 可视为微服务与中台建模的「产品经理」:写业务功能时 面向领域,而非面向数据库表。
大系统可拆成多子系统(类似人体消化、神经等子系统)。企业软件平台常包含三类能力:
| 能力 | 要点 |
|---|---|
| 业务能力 | 功能、流程电子化,快速响应市场 |
| 数据能力 | 存储、挖掘、融合,支撑数字化运营 |
| 技术能力 | 运维自动化,微服务架构设计与演进 |
业务中台 承载核心关键业务,通过领域边界划分与建模,沉淀用户/订单/商品/支付等可复用能力,以微服务形式支撑前台。数据中台 与业务中台相辅相成,侧重统计、智能数据服务与「业务数据化、数据业务化」。技术中台 保障高可用与海量访问(网关、微服务框架、分布式数据库等)。
中台建设的核心挑战之一是 领域模型重构;DDD 提供划分边界与建模的方法,与微服务拆分天然衔接——后续战略设计篇会展开 限界上下文 与拆分原则。
小结
- SOLID + 迪米特 是写好领域对象与分层的基础。
- 上帝类 与隐式 if-else 业务是 DDD 要治理的对象;显式领域概念 让代码可读、可扩展。
- OOA → OOD → OOP 与 DDD 战略/战术阶段衔接;中台 场景下 DDD 负责领域建模而非表驱动。
下一篇进入 DDD 宏观与微观核心概念,从限界上下文建立直觉。