值对象和实体以及字典类型的DDD建模

dsi*_*zak 5 java domain-driven-design hibernate jpa

我想将我们的问题带给更多的听众,因为我们已经在公司中讨论了一段时间,但找不到答案。

让我们假设我们有一个交易对象,它是聚合根。在交易内部,我们有作为价值对象的金钱

class Transaction {
    private Money money;
    // other stuff
}
Run Code Online (Sandbox Code Playgroud)

class Money {
    private BigDecimal amount;
    private String currency;
}
Run Code Online (Sandbox Code Playgroud)

可以将这样的Transaction持久化(我们使用休眠方式)以将db转换为简单的表事务

+-----------------+
| transaction     |
+-----------------+
|id : bigint      |
|amount: decimal  |
|currency: varchar|
|other...         |
+-----------------+
Run Code Online (Sandbox Code Playgroud)

一切都会很好,但是...客户要求我们在数据库中有货币表(我们称其为字典表),并且每个有钱的表(包括交易)都需要指向货币表:

+-----------------+           +-----------------+
| transaction     |           |curency          |
+-----------------+           +-----------------+
|id : bigint      |     +---> | id: bigint      |
|amount: decimal  |     |     | code: varchar   |
|curr_id: bigint  | ----+     | name: varchar   |
|other...         |           +-----------------+
+-----------------+
Run Code Online (Sandbox Code Playgroud)

因此,从现在开始,Money对象应如下所示:

class Money {
    private BigDecimal amount;
    private Currency currency;
}
Run Code Online (Sandbox Code Playgroud)

从现在开始,我们不能将其称为value object :(还是我们可以?它也使我们持久化对象的方式变得复杂,因为我们不再需要使用hibernate embedable了,因为我们需要编写自己的自定义类型,请在此处输入链接描述。因为字典类型在使用中很流行,所以不是第一个面临此问题的人,问题是,如何在ddd建模范围内处理它们。

在处理地址时,我们将面临类似的问题。因此,我们知道我们有诸如Country和FederalState之类的字典(属于分层结构)。我们还知道,我们的应用程序中的许多对象(例如机构)都有自己的地址,但也与FederalState有联系。因此,在simpe情况下,我们将有:

class Institution {
    Address address;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

哪里

class Address {
    String street;
    String houseNo;
    // etc..
    String federalState;
    String country;
}
Run Code Online (Sandbox Code Playgroud)

但是我们需要它与联邦状态表有关系,因此Address看起来像:

class Address {
    String street;
    String houseNo;
    // etc..
    FederalState federalState;
}
Run Code Online (Sandbox Code Playgroud)

因此,我们再次面临同样的问题,即从现在开始,Address不再是值对象。我们知道如何从技术上做到这一点,但是从od ddd的角度来看,正确的方法是什么?

Adr*_*chi 1

“从 oddd 的角度来看,正确的方法是什么”

首先,使用字典实体并没有错。只是因为与字符串值不同,使用与字典实体的关系:

  1. 避免拼写错误(更稳健)
  2. 允许在不修改代码的情况下管理“值”集 - 您只需从存储中加载字典并填充下拉列表,而不是在代码中定义枚举(更灵活)。

抛开以上两者不谈,业务需求可能会强加这种设计。例如,对于这种Currency情况:当表达为实体时,允许定义关系Exchange Rate,其本身可能受“可审计记录/历史”方法的影响,用于存储汇率随时间的演变。
拥有一本State字典是(未来可能)处理不同销售税政策或立法限制(某些州不允许的产品/服务 - 请参阅“药用”杂草和其他)的扩展的良好基础。