Skip to content
/ eleven Public

低成本可落地的 领域驱动设计 技术方案脚手架。

License

Notifications You must be signed in to change notification settings

c5ms/eleven

Repository files navigation

Java CI with Maven

🛠️ Eleven

低成本可落地的领域驱动设计(DDD)技术方案脚手架

📖 项目介绍

Eleven 是一款严格遵循 DDD 理念的工程化脚手架,通过标准化的架构设计,助力团队快速构建易于维护的企业级应用。其核心设计原则如下:

🌟 分层架构规范

  1. 四层架构清晰分离

    • UI层 🖥️:专注于用户交互处理,负责输入校验与 DTO 转换,仅调用应用层接口,确保无任何业务逻辑侵入。
    • 应用层 🧩:作为流程协调中枢,定义粗粒度服务,处理事务管理与权限控制,仅依赖领域层的抽象接口。
    • 领域层 🏰:封装业务核心要素(实体、聚合、事件),保持技术实现中立,通过抽象接口与外界交互。
    • 基础设施层 ⚙️:实现上层定义的抽象接口(如仓储),提供数据库、消息队列等技术支撑,支持透明化技术替换。
  2. 依赖关系严格管控

    • 上层模块依赖下层抽象(例如应用层使用 UserRepository 接口而非具体实现),严禁反向依赖(技术层绝不能依赖业务层)。
  3. 层间协作规范明确

    • 接口设计遵循领域通用语言(如 OrderId),通过 DTO 解耦数据格式,严格禁止跨层直接调用(如 UI 层不得直连领域层)。
  4. 可演进性设计理念

    • 各层支持独立演进(更换框架或数据库不影响其他层),业务规则与技术细节彻底分离(核心逻辑沉淀在领域层,技术实现下沉至基础设施层)。

👥 适用群体

Eleven 脚手架精准适配多元研发场景,核心目标群体涵盖:

1. 复杂业务开发团队 🌐

  • 适用于金融、供应链、ERP 等业务逻辑高度复杂的场景,借助 DDD 厘清领域边界、沉淀业务规则,有效规避逻辑耦合风险。

2. 技术转型团队 ⚙️

  • 为传统架构向 DDD 转型的团队提供标准化模板,降低转型门槛,快速统一团队技术规范。

3. 多角色协作组织 👩💻👨💻

  • 架构师/技术经理:获取可复用的架构模板,聚焦领域建模核心工作;
  • 开发团队:按约定的结构快速编码,大幅减少协作成本。

4. 长期迭代项目团队 🛠️

  • 支持中大型项目的技术栈演进(如数据库替换),通过分层隔离设计确保核心领域稳定。

5. 企业级应用团队 🏭

  • 特别适合制造业、政务等复杂业务场景,依托 DDD 的领域建模能力提升业务表达力。

6. DDD 落地迷茫者 📚→💻

  • 为熟悉 DDD 理论却缺乏实践经验的开发者提供可复用架构模板与代码示例(涵盖聚合设计、分层实现等),解决“懂概念却难编码”的痛点。

分层设计

- xxxService:Bean 级别的 Application Service
  - xxxManager:Bean 级别的 Domain Service(为应用层提供通用逻辑支持,不隶属于领域层)
    - xxxSupport:Bean 级别的业务公共方法类
      - xxxEr/Or:Bean 级别的底层工具类(无层级依赖,聚焦业务级工具)
        - xxxUtil:与业务无关的静态工具类 🧰
        - xxxHelper:与业务相关的静态工具类 🔧
        - xxxContext:与框架相关的静态工具类 🖥️

聚合设计

下面将带你感受一下架构师在考虑实现的时候的整体流程,我们假设拿到了需求,也分析好了希求,现在开始内部决定如何实现,一起来看看将会发生哪些事情。

技术需求

架构师+技术经理+技术团队基于领域驱动设计对领域模型的要求,制定业务建模规则如下:

实体 📄

  • 具备唯一标识符(ID)。
  • 生命周期需显式管理,状态变化必须通过业务操作实现。
  • 封装完整业务逻辑,坚决避免贫血模型。
  • 聚合内 ID 只需局部唯一,由聚合根统一管理。
  • 禁止直接引用其他聚合的实体,通过聚合根 ID 建立关联。

聚合根 🔑

  • 作为聚合的唯一入口,外部仅能通过聚合根 ID 访问聚合内部对象。
  • 拥有全局唯一 ID,掌控聚合内实体的生命周期。
  • 提供边界保护:聚合内业务规则必须通过聚合根校验。
  • 遵循小巧设计原则:聚合规模应尽可能精简,排除无关实体。
  • 外部引用规则:仅允许通过聚合根 ID 引用其他聚合,严禁直接关联内部实体。

值对象 📊

  • 无唯一标识,通过属性值组合定义自身身份。
  • 不可变性:创建后属性不可修改,状态变化需生成新实例。
  • 无生命周期,纯粹作为数据载体存在。
  • 相等性判断基于属性值比较,而非引用地址比较。

领域服务 ⚙️

  • 承载业务领域的核心逻辑。
  • 支持对多个实体或聚合根的操作。
  • 完全剥离技术实现(如事务管理、GUI 交互)。
  • 如需依赖技术手段,需将其封装为接口以实现依赖倒置。

技术实现

领域模型技术范围(核心必含要素)

  • 领域实体 ✅
  • 领域聚合根 ✅
  • 领域实体仓库接口 ✅
  • 领域事件 ✅
  • 聚合根查询能力(读操作)✅
  • 聚合根操作能力(写操作)✅
  • 领域业务规则 ✅
  • (可选)复杂逻辑设计模型 ⚠️

领域模型技术手段

  • 采用 JPA 标记实体类(考虑到团队技术熟练度与未来规划,暂不进行实体与存储技术的解耦)。
  • 基于 CQRS 实现读写分离,严格恪守单一职责原则(方法仅专注读或写操作)。
  • 运用《领域驱动设计》中的对象规格(Domain Spec)技术实现对象查询。
  • 领域服务以 Manager 作为后缀命名,清晰区分于应用服务。
  • 领域服务承担领域模型业务代理职责,并管理领域事件(受限于当前技术条件)。

架构师评审要点

  • 要求团队将实现手段整理为核心技术文档,作为重要资产妥善保管。
  • 代码评审时须按规则逐条校验,严禁随意破坏设计原则。
  • 提出多项技术管理需求(具体内容详见文档补充说明)。

接口设计

状态码约定

状态码分类 含义 典型场景举例
2XX 成功响应 200 OK(请求处理成功)
4XX 客户端错误 404 资源不存在、403 权限不足等
5XX 服务器端错误 500 内部服务器错误

4xx 状态码详解

  • 404 NOT_FOUND 🚫:当必须的父级数据缺失或请求地址不存在时返回。
  • 403 FORBIDDEN 🔒:用户无操作权限时返回。
  • 422 UNPROCESSABLE_ENTITY 📉:数据校验失败或业务前提条件不满足时返回。
  • 500 INTERNAL_SERVER_ERROR 💥:服务器端出现错误(需开发人员排查解决)。

2xx 使用规范

  • 仅使用 200 OK 状态码:
    • 成功处理时返回对应资源或结果;
    • 特定场景下处理被拒绝时,仍返回 200 状态码,但需在结果中明确描述错误代码与原因。

REST API 设计

操作类型 路径格式 状态码 响应说明
创建 POST /XXX 200 成功返回创建的资源;拒绝时返回 4xx 及原因
读取 GET /XXX 200 成功返回请求资源;拒绝时返回 4xx 及原因
全量更新 PUT /XXX 200 幂等操作,成功无响应;拒绝时返回 4xx
局部更新 PATCH /XXX 200 可返回资源处理结果;拒绝时返回 4xx 及原因
删除 DELETE /XXX 200 成功无响应;拒绝时返回 4xx 及原因

微服务调用规范

内部 API(@AsInnerApi 标记) 🚪

  • 这类API会添加前缀/inner
  • 这类API不会注册到网关,通常也不会校验权限(自己在方法上控制权限即可)
  • 这类API不会复合rest风格,通常是面向命令方式的。

客户端 API(@AsRestApi 标记) 🌐

  • 这类API会添加前缀/rest
  • 这类API会被注册到网关,通常也会校验权限(自己在方法上控制权限即可)
  • 这类API会一定程度上遵循rest风格。

常见问题 Q&A

❓ 分析需求时,“实时/写操作/强一致”“异步/写操作/最终一致”“异步/只读”分别适用于什么场景?

🚀 实时/写操作/强一致:三者常同时出现,通常意味着在单体应用中直接调用领域服务,并在同一数据库事务内完成处理,确保数据强一致性。 🐌 异步/写操作/最终一致:适用于业务实时性要求不高但数据处理量较大的场景,可通过异步写入 MQ 并订阅处理,有效提升系统性能。 🔔 异步/只读:多数为通知类场景,无需同步处理,异步操作既能提升性能,又能实现服务解耦。

❓ 为什么领域层不分单独的包(如 /repository//entity)?

🌪️ 领域层逻辑本身已足够复杂,若机械地按设计模式拆分 24 个包,反而会增加认知负担。DDD 的核心是围绕业务建模,而非僵化的目录结构——合理的设计应让复杂度自然收敛,而非刻意拆分。

❓ 领域层的拦截器机制会污染核心逻辑吗?

🛡️ 核心逻辑是否被污染,本质取决于设计是否清晰,而非技术手段本身。若严格遵循职责分离原则,拦截器仅处理横切关注点(如日志、事务),便不会对核心业务逻辑造成影响;反之,混乱的设计才是“污染源”。

❓ 为什么领域服务不命名为 DomainService

🧩 DDD 是解决复杂软件问题的方法论,核心在于统一语言、建模与解耦,而非纠结于术语命名。过度追求“标准命名”却忽视业务本质,反而会陷入形式主义误区——命名应服务于团队共识,而非成为教条。

❓ 架构师强调写核心设计文档,究竟想表达什么?

📜 参考《敏捷开发》原则,文档应聚焦“必要的最小化”——核心设计文档需能推导出所有代码逻辑,成为团队协作的“指南针”。而海量流水账式文档若缺乏维护,只会成为负担,百害而无一利。

❓ DDD 只适用于互联网场景吗?

🏭 恰恰相反!DDD 诞生于企业级复杂业务场景,其领域建模能力在制造业、政务等需要深度业务抽象的领域更能发挥价值。互联网轻量级场景若盲目套用,反而可能导致过度设计。

🐳 Docker 配置

项目提供完善的 Docker 配置文件,助力快速实现容器化部署。核心配置位于: src/docker/eleven/docker-compose.yml(包含 Redis、Upms、Demo 等服务的详细配置)

使用建议 🚀

  1. eleven-framework 模块中扩展基础框架功能(如新增安全认证方式、日志处理策略等)。
  2. 按照 DDD 思想,在 eleven-service 模块中逐步落地具体业务功能。
  3. 在特定应用服务下创建 core/common 包:
    • core 存放业务无关的公共代码(如通用工具类);
    • common 存放业务相关的公共代码(如领域通用逻辑)。
  4. 定期将 core 包中的成熟代码沉淀到 eleven-framework,实现技术资产复用。
  5. 定期将 common 包中的业务代码沉淀到专属业务组件包,避免重复开发,提升协作效率。

Eleven 凭借清晰的分层架构、规范的协作模式与可复用的工程模板,助力团队高效落地 DDD,从容应对复杂业务挑战,让领域驱动设计从理论走向实践,真正成为企业级应用开发的“脚手架”。 🚀

About

低成本可落地的 领域驱动设计 技术方案脚手架。

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages