我正在阅读关于 SO 的类似问题:How update an entity inside Aggregate,但我仍然不确定用户界面应如何与聚合内的实体交互。
假设我有一个User
, 和一堆Address
es。User 是聚合根,而 Address 只存在于聚合中。
在 Web 界面上,用户可以编辑他的地址。基本上,会发生什么:
- 用户在其 Web 界面上看到地址列表
- 他点击一个地址,然后被重定向到这个页面:
edit-address?user=1&address=2
- 在这个页面上,他得到一个表格,他可以在其中修改这个地址。
我决定绕过聚合根,这很简单:
- 我们将直接
Address
加载Id
- 我们会更新它,然后保存它
因为我们想用 DDD 的方式来做,所以我们有不同的解决方案:
我们要么要求用户通过 Id 获取此地址:
address = user.getAddress(id);
address.setPostCode("12345");
address.setCity("New York");
em.persist(user);
这种方法的问题是,IMO,聚合根仍然无法更好地控制地址的处理方式。它只是返回对它的引用,因此这与绕过聚合没有太大区别。
或者我们告诉聚合更新现有地址:
user.updateAddress(id, "12345", "New York");
em.persist(user);
现在聚合可以控制对该地址的处理,并且可以采取任何与更新地址相关的必要操作。
或者我们将地址视为一个值对象,我们不更新我们的
Address
,而是删除它并重新创建它:user.removeAddress(id);
address = new Address();
address.setPostCode("12345");
address.setCity("New York");
user.addAddress(address);
em.persist(user);
最后一个解决方案看起来很优雅,但意味着地址不能是实体。那么,如果它需要被视为一个实体,例如因为聚合中的另一个业务对象具有对它的引用,该怎么办?
我很确定我在这里遗漏了一些东西来正确理解聚合概念以及它是如何在现实生活中的例子中使用的,所以请不要犹豫,提出你的意见!