大数跨境

看待 DDD 的方式(从仍在学习的角度)

看待 DDD 的方式(从仍在学习的角度) 索引目录
2025-07-11
0
导读:关注【索引目录】服务号,更多精彩内容等你来探索!它更像是一位正在重新学习领域驱动设计 (DDD) 的人写的一篇(并非那么)深入的探讨。

关注【索引目录】服务号,更多精彩内容等你来探索!

它更像是一位正在重新学习领域驱动设计 (DDD) 的人写的一篇(并非那么)深入的探讨。如果你曾经盯着一张满是聚合、存储库和有界上下文的图表,心想:“等等……这到底是怎么回事?” 那么欢迎,你并不孤单。

这篇文章是我的方式:

  • 重建 DDD 的坚实心理模型。
  • 将抽象概念与(希望)直观的类比联系起来。
  • 分享令我感动的事情,尤其是通过更具对话性和个性化的视角。

无论您是像我一样刚刚开始学习,还是第一次探索 DDD,我都希望本指南能够拨开迷雾,激发好奇心,让旅程更加愉快。

DDD 的核心概念

我们开始了。首先,领域驱动设计 (DDD) 是一种战略性的软件设计方法,专注于通过丰富、有意义的代码来反映业务逻辑,从而对复杂的领域进行建模。无论你是在团队中,还是独自完成一个大型项目(愿上帝保佑你),你都应该对自己说:“在我们(或我)开始编码之前,请确保我们理解了我们在构建什么以及为什么构建它。”

从我(重新学习)的角度来看,DDD 是:

  • 一种将开发
    与领域专家或真正了解业务的人员重新联系起来的方法。
  • 一种重视代码边界和表现力
    的方法(你一会儿就会明白我指的是什么)
  • 一种要求团队在代码、业务对话和文档中使用通用语言或一致术语的结构。

DDD中的分层架构

DDD 不仅仅关乎建模,也关乎组织。大多数企业级应用程序受益于分层架构,这种架构能够分离职责并帮助管理复杂性。这些层是逻辑上的,而非物理上的。所以……这意味着它们可以帮助您理解和构建系统,但不一定能映射您的部署方式。

这些层的常见表示是:

1.领域模型层

系统的核心,业务逻辑所在。DDD 的关键构建块(实体、聚合、值对象等)就驻留在此层。
这一层包含定义系统行为的基本元素,并强制执行使领域有意义的规则。它与基础设施完全隔离,这是设计使然。在这里,您的软件可以像业务一样思考。

让我们来认识一下这里的基石:

实体 - 可识别的老兵

实体由一个唯一的身份(如或)定义,即使其属性发生变化,该身份也会随时间持续存在。orderIduserId

例子:

  • User
    :有userId,可能会更新他们的电子邮件
  • Order
    :由 标识orderId,即使其项目发生变化

你可以把它想象成......一个拥有护照的旅行者,无论穿什么衣服或去哪里,他们的身份都保持一致且可追踪。

价值对象 - 优雅的极简主义者

对象保存不可变且可互换的数据。两个具有相同属性的值对象相等。

例子:

  • Address
    :由streetcity和组成zipCode
  • Money
    :与amountcurrency

你可以把它想象成……一块油漆样本,仅由颜色和属性定义,而非身份。易于复制,可安全丢弃。

聚合 - 凝聚力集团

聚合是一组作为单个单元工作的实体和值对象。所有访问和更新通过聚合根进行。

例子:

  • Order
    总计可能包括OrderItemsShippingDetailsTotalAmount

您可以将其想象为……乐高积木,单个积木只有在按照一个明确的目的进行组装时才有意义。

聚合根 - 明智的守门人

聚合是聚合的主要入口点。它强制执行规则并确保一致性。你永远不会直接接触内部对象,而是必须通过屋顶。

例子:

  • Order
    是管理其项目、状态、支付流程并确保遵守业务规则的根源。

你可以把它想象成......学校校长,接触员工或记录,通过这一权力来确保秩序和完整性。

领域活动 - 大声播音员

领域事件表示领域内发生了一些有意义的事情。它允许系统在非紧密耦合的情况下做出反应。

例子:

  • OrderPlaced
    可以触发通知服务、付款处理或装运安排。

你可以把它想象成……镇上的公告员,大声宣布新闻,以便任何听到的人都可以决定下一步该做什么。

存储库 - 谨慎的僚机

Repository抽象了聚合的数据存储逻辑。它允许您检索、保存和删除域对象,而无需了解持久化的具体工作原理

例子:

  • OrderRepository
    处理类似save(order)或的方法findById(orderId)

你可以把它想象成……你的后台助理,你可以要求某些东西,它会默默地获取或存储它,而不会打扰演出。

2. 应用层

负责协调业务用例的组件,它不包含业务规则,但知道谁应该执行什么。它处理来自 UI 或外部系统的传入请求,然后将这些请求转换为领域模型的操作,通常使用已经为演示而构建的 DTO 或 ViewModel。

从不验证业务规则或直接与数据库交互,而是依赖于存储库。

一个很好的例子如下:

假设用户在您的网站上点击“下订单”:

  1. 表示层发送数据 ->PlaceOrderCommand
  2. 应用层接收命令
  3. 它要求OrderAggregate处理创建(借助域实体和规则)
  4. 成功后,它将返回一个用于显示的 ViewModel。

3.基础设施层

我们可以称其为“幕后修复程序”,它实用但不引人注目。它支持所有其他持久化、网络和外部服务,提供对数据库、外部 API、消息队列、文件系统的访问,实际上就是系统与外界交互所需的一切

绝不应该泄露到领域中。相反,它应该通过诸如存储库事件调度器服务接口之类的抽象来谨慎地为领域提供服务。

4. 表示层

用户所看到和与之交互的内容,通过 ViewModel 与应用层进行通信。该层负责提供用户界面 (UI)、处理输入并呈现输出。它通过 DTO 或 ViewModel 与应用层通信,确保只有有效且结构化的数据才能深入系统。

它负责通过视图、模板和控制器(例如在 MVC 框架中)显示用户界面。它还会在将输入传递给应用层之前对其进行格式化和验证。

何时(以及何时不)使用 DDD?

说实话:DDD 并非适用于所有项目。诚然,它在逻辑不断发展、多个团队需要保持一致的复杂领域中大放异彩,而且它也挺酷的(至少在我看来,在 IDE 中看到所有这些文件夹并知道在哪里查找错误,这感觉有点奇怪)。但如果你尝试将 DDD 用于周末待办事项列表应用……那还不如用火箭发射器猎兔子呢。

那么我们该如何决定呢?

您应该查看清单并查看项目是否符合以下任何一项:

  • 您正在处理复杂的业务规则,并且需要正确地表示现实世界的逻辑。
  • 您的领域将随着时间的推移而发展,例如新规则、新行为、新用例。
  • 您希望系统不同部分之间有明确的界限
  • 多个团队需要使用相同的语言,代码和业务术语必须保持一致。
  • 您构建的目的是为了长期的可维护性,而不是短期的速度。

另一方面,如果您的项目或应用程序是……

  • 主要是CRUD(创建、读取、更新、删除),领域复杂性较低
  • 快速 MVP 或概念验证
  • 一个单独的项目,需要快速迭代,而不是分层组织

... DDD 可能有点过度了。

话虽如此,即使在比较简单的项目中,您也可以完全应用 DDD 原则,而无需采用完整的架构。定义清晰的边界或避免基础架构泄漏到核心逻辑中,可以带来很大的不同。这不是一个“是”或“否”的问题,而是一个范围。您可以逐步采用 DDD 的部分功能,并让系统结构随着复杂性的需求而增长。

总结

好了,以上就是领域驱动设计的完整演练,它并非来自象牙塔般的理论,而是从一个将一切重新拼凑起来的人的视角。每一层都有其角色,每个概念都有其表达方式,现在希望 IDE 中的每个文件夹都有其存在的意义,而不仅仅是“感觉井井有条”。

这种方法并非追求完美,而是注重系统化思考,用业务语言进行交流,并有目的地进行构建。无论你决定完全拥抱 DDD,还是仅仅借鉴其最佳理念,目标都是一样的:编写合理的软件。

感谢您一路读到这里,如果您有任何想法、指正,或者您对 DDD 有什么自己的看法,请在评论区告诉我!我们都在这里学习。


关注【索引目录】服务号,更多精彩内容等你来探索!


【声明】内容源于网络
0
0
索引目录
索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
内容 444
粉丝 0
索引目录 索引目录是一家专注于医疗、技术开发、物联网应用等领域的创新型公司。我们致力于为客户提供高质量的服务和解决方案,推动技术与行业发展。
总阅读12
粉丝0
内容444