首页/开发/代码质量与评审速查/SOLID 落地:核心域与基础设施分离
设计原则与模式62 条

SOLID 落地:核心域与基础设施分离

业务核心只依赖接口(端口),数据库、消息、第三方 SDK 作为适配器实现端口:技术选型可替换、核心可脱离环境测试;依赖注入在组装层完成,业务代码无 new 基础设施。

核心域与基础设施分离

让业务核心只依赖接口(端口),数据库、消息与第三方 SDK 作为适配器实现端口:技术选型可替换,核心逻辑能脱离环境测试。依赖注入在启动或组装层完成,业务代码里不再出现直接构造基础设施的语句。

基本信息

结构核心域依赖端口(接口),适配器实现端口
组装位置启动层或组装模块做依赖注入
收益测试可用内存适配器,不依赖真实中间件
相关原则依赖倒置、单一职责
常见形态端口与适配器、六边形架构

典型使用场景

  • 需要脱离数据库跑单元测试的业务逻辑
  • 第三方 SDK 隔离在适配层,不污染领域代码
  • 未来可能更换存储或消息中间件的系统
  • 同一业务逻辑需要多种出入口(接口、定时任务、消息)
  • 沙箱与生产环境使用不同实现的场景

端口与测试替身

端口与测试替身
// 端口:核心定义接口
interface OrderRepository { Order byId(OrderId id); void save(Order order); }

// 适配器:生产用数据库,测试用内存实现
class MySqlOrderRepository implements OrderRepository { ... }
class InMemoryOrderRepository implements OrderRepository { ... }

OrderService service = new OrderService(new InMemoryOrderRepository());

分层职责

层职责约束
核心域业务规则与状态变化不引用框架与基础设施类型
端口定义核心需要的能力接口面向领域语言
适配器实现具体技术细节只做转换与调用,不写业务分支
检验边界是否有效,看核心能否在没有中间件的环境里跑起来:如果单元测试必须启动数据库或消息队列,说明依赖方向还没有倒过来。
端口方法直接暴露 ORM 实体或框架类型,核心会被持久化细节渗入;更换存储实现时业务代码照样要改,隔离也就失效了。
端口应当由核心定义:接口放在业务模块里,实现放在基础设施模块;反过来让核心去实现基础设施定义的接口,依赖方向就没有真正倒过来。

易错点

  • 端口方法直接暴露 ORM 实体:核心被持久化细节渗入,替换存储仍要改业务代码
  • 适配器里写业务分支:逻辑回流,边界形同虚设
  • 组装散落在业务代码中:到处出现直接构造基础设施的语句,无法替换
  • 为每个类都建接口:端口泛滥,调用链变长而收益有限

数据来源与参考

  • Alistair Cockburn 六边形架构(端口与适配器)与 DIP 实践
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌