DDD开发模式说明

DDD开发模式说明 1. 文档目标本文档基于项目脚手架说明整理目的是统一团队对 DDD领域驱动设计开发模式的理解并指导在当前工程中的实际落地方式包括工程分层职责目录结构设计命名规范接口规范服务调用链路微服务间调用方式公共组件依赖原则2. 为什么要采用DDD传统三层架构通常按Controller - Service - DAO组织代码虽然上手快但随着业务复杂度上升容易出现以下问题业务规则集中堆积在 Service 层数据模型成为系统核心业务语义表达不足各层耦合较强模型或规则变化时影响范围大代码偏向“表结构驱动”不利于复杂业务演进DDD 的核心目标是让“领域模型”而不是“数据库结构”成为软件设计中心把复杂业务规则沉淀到领域层提升系统的可维护性、可扩展性和表达能力。3. DDD四层架构当前项目采用的是经典 DDD 四层架构并结合适配器/防腐层思想进行工程化落地。3.1 用户接口层User Interface / Adapter / API职责对外暴露接口接收请求、返回响应完成参数转换作为消息、事件等入口特点不承载核心业务规则只负责协议适配和调用应用层是外部系统访问当前服务的入口3.2 应用层Application职责定义系统要完成的业务用例编排领域对象完成业务流程协调领域层与外部接口之间的调用关系处理事务边界、输入输出 DTO、远程依赖抽象特点应用层要“薄”不应沉淀复杂业务规则更关注“做什么”而不是“业务规则本身是什么”3.3 领域层Domain职责承载核心业务概念、业务规则和状态表达领域模型定义实体、值对象、领域服务、仓储接口、领域事件特点是业务软件的核心领域层不依赖其他业务层业务变化优先体现在领域层3.4 基础设施层Infrastructure / Infra职责提供技术实现能力实现仓储、远程调用、消息发送、配置、持久化、过滤器、异常等实现领域层定义的接口特点面向技术细节通过依赖倒置为上层提供能力隔离框架、中间件、数据库、远程服务等具体实现4. 数据模型驱动与领域模型驱动对比4.1 数据模型驱动典型特点接口定义和实现集中在 API 层业务逻辑集中在 Service 层DAO 和数据库模型成为核心依赖表结构变化容易传导到服务层甚至接口层问题业务语义弱规则分散演进成本高4.2 领域模型驱动典型特点接口能力仍由 API 层提供业务逻辑拆分为“应用层编排 领域层规则”领域层是业务核心基础设施层通过依赖倒置实现技术隔离优势业务规则归位分层清晰复杂业务更容易扩展和维护5. 项目中的DDD工程结构项目脚手架的核心结构可以理解为两个部分sdk对外暴露接口契约biz服务内部业务实现5.1 SDK层用于给其他服务依赖主要包含北向接口定义adapter/api对外 API 定义adapter/request请求模型adapter/response响应模型作用统一服务间接口契约便于微服务之间通过 jar 方式复用接口定义5.2 Biz层承载真正的业务实现主要分为以下几层adapter职责API 实现参数转换消息/事件入口常见子目录implconvertorlistenerapplication职责定义应用服务编排领域服务定义输入输出 DTO定义对外部服务依赖的抽象接口常见子目录dto/inputdto/outputserviceservice/implremotedomain职责承载业务核心模型按领域划分子域定义实体、领域服务、仓储接口、事件接口常见子目录领域/entity领域/service领域/service/impl领域/repository领域/eventinfra职责实现技术能力与外部依赖实现仓储、远程服务、事件发送等接口提供异常、过滤器等基础能力常见子目录adapter/api.impladapter/eventadapter/repositoryadapter/repository/convertoradapter/repository/mapperadapter/repository/poadapter/repository/implexceptionfiltercommon职责放置本服务公共能力包括常量、枚举、工具类常见子目录constantsenumsutils6. 分层职责边界为了避免职责混乱开发时应遵守以下边界。6.1 Adapter层应该做什么可以做接收 HTTP / MQ / 事件请求调用 Convertor 做对象转换调用 Application Service返回统一响应不要做编写复杂业务规则直接操作数据库绕过应用层直接操作领域对象6.2 Application层应该做什么可以做编排业务流程调用多个领域服务控制事务边界调用 remote 接口抽象输出 DTO不要做沉淀复杂领域规则直接依赖数据库 Mapper编写面向技术实现的细节代码6.3 Domain层应该做什么可以做表达实体状态和行为编写领域规则定义仓储接口定义领域事件实现领域服务不要做依赖 Controller、Mapper、Feign、数据库表结构等技术细节出现明显的接口协议对象如 Request/Response/PO6.4 Infra层应该做什么可以做实现 Repository实现 RemoteService实现 EventPublisher落地持久化、远程调用、消息发送不要做反向主导业务规则直接把 PO 当成领域实体使用7. 推荐调用链路7.1 Command操作写操作推荐链路adapter - application - domain - infra说明接口层接收请求应用层编排业务领域层处理核心规则基础设施层落地持久化或外部交互7.2 Query操作查询操作可采用以下方式adapter - application - domain - infraadapter - application - infraadapter - infra其中普通查询建议优先使用第 2 种降低复杂度报表类、纯展示类查询可以使用第 3 种如果查询包含明确业务规则仍建议经过 domain原则读操作可以适度简化写操作尽量保持完整 DDD 链路8. 微服务之间的调用方式项目中推荐使用OpenFeign进行微服务调用。8.1 服务提供方将interface-api模块打成独立 jar对外暴露 API、Request、Response 等契约模型8.2 服务消费方引入服务提供方的接口 jar在infrastructure层实现远程调用通过application.remote中定义的抽象进行依赖倒置原则应用层依赖抽象基础设施层依赖具体远程实现避免应用层直接依赖 Feign 细节9. 命名规范9.1 类命名规范interface-api***Api、***Request、***Responseinterface/adapter***Controller、***Convertorapplication***AppService、***AppServiceImpl、***InputDto、***OutputDto、***RemoteService、***AppConvertordomain***DomainService、***DomainServiceImpl、***Entity、***Repositoryinfrastructure***RepositoryImpl、***RemoteServiceImpl、***Mapper、***Po、***InfraConvertor9.2 包命名规范统一格式com.gientech.ri.***.模块名说明***为工程名简写启动模块可不追加模块名10. REST接口设计规范10.1 URL规范统一格式/{系统名(可选)}/{应用名}/api/{业务模块(可选)}/{资源}(s)/{id}/{动作(可选)}?{param}{xxx}10.2 HTTP动词规范GET查询POST新增、复杂动作、批量处理PUT更新DELETE删除10.3 非CRUD动作规范对于批量操作、复杂业务动作不使用模糊参数而是在 URL 中显式表达动作例如POST /arch-govern/api/govern/tasks/batch-updatePOST /arch-govern/api/govern/task/010/execute这样做的好处语义清晰单一职责明确接口边界稳定11. 公共组件依赖原则项目中的公共组件遵循以下原则base和directory属于底层公共组件不依赖其他三个公共组件base和directory之间可以相互依赖计划、项目、需求等公共组件除依赖基础组件和目录组件外最好不要相互依赖如果必须依赖其他服务优先通过其application层提供的服务进行调用核心思想控制依赖方向避免横向耦合防止公共组件网状依赖12. 开发落地建议在当前脚手架下推荐按以下顺序开发功能明确业务领域和子域边界在domain中定义实体、仓储接口、领域服务在application中定义用例、DTO 和编排逻辑在adapter中提供接口实现与对象转换在infra中补齐仓储实现、远程调用、消息实现按命名规范和分层规范补充测试代码13. 总结本项目的 DDD 模式本质上是在经典四层架构基础上引入领域核心建模应用层编排基础设施隔离适配器/防腐层思想它强调的不是“目录拆分”而是“职责拆分”API层负责接入Application层负责编排Domain层负责业务规则Infra层负责技术实现对于复杂业务系统这种模式比传统三层架构更适合持续演进也更有利于团队协作和代码治理。