文中的想法最适用于实现(复杂)业务规则、状态转换并将其数据保存到某个数据库的后端应用程序。
复杂的逻辑应该在您可以完全控制内部域模型的数据结构上实现,您可以根据问题对其进行定制以简化代码。
这是本文中使用的术语定义的(自以为是的)列表:
- 领域= 要保留应用程序逻辑中最复杂部分的代码区域。任何架构的目标都是清理实现系统基本复杂性的环境。
- 数据传输对象 (DTO) = 跨系统边界移动的对象,例如,编组为 JSON、XML 或二进制格式。
- API = 系统的入口点(REST 端点或消息队列)以及所涉及的 DTO。许多系统都暴露了一个 REST API,然后依次调用其他系统的 API。
- 领域对象 (例如,值对象、实体、聚合)= 应用程序的内部数据结构,通常保存在某些数据库中,但在系统外部不可见
避免 DTO 的原因
- DTO 臃肿
- DTO 扁平
很多时候 DTO 是扁平的,很容易退化为具有几十个属性的结构。另一方面,我们更喜欢在我们的领域中使用更小的结构,只有当我们更积极地将我们发现为嵌套对象的概念建模时,我们才能获得这种结构。
- DTO 属于不同的有界上下文
- DTO 贫血
- 手动写入
- 从“客户端库”导入
- 从 OpenAPI/swagger/WSDL 规范生成
- DTO 是可变的
- DTO 不受约束
然而,在我们公开的 API 中,许多 Java 团队选择向我们的“请求”DTO添加验证注释(例如@NotNull,、、@Size... @Pattern) 。之后,我们只要求框架检查所有内容。这很酷。
然而,第 3 方 API 的 DTO从不带有约束。
因此,任何类型的 DTO(或)在 领域中使用时都可能呈现损坏的数据。
但是这里的“有效”意味着两件事:
- 简单的全局约束,例如“必填字段”。
- 强制执行我的域的一致性规则,例如“激活的合同设置了激活日期”。
- DTO 不受您的控制
banq:用领域事件替代或包装你的DTO:事件驱动系统中不同类型的事件:

图中Policy代表业务规则,Command和Event属于DTO的升级版本,命令事件之间有因果关系(蓝色)和相关性关系(绿色),这两种逻辑关系见:简单说说康德的四组范畴