13

我正在阅读关于 SO 的类似问题:How update an entity inside Aggregate,但我仍然不确定用户界面应如何与聚合内的实体交互。

假设我有一个User, 和一堆Addresses。User 是聚合根,而 Address 只存在于聚合中。

在 Web 界面上,用户可以编辑他的地址。基本上,会发生什么:

  • 用户在其 Web 界面上看到地址列表
  • 他点击一个地址,然后被重定向到这个页面:edit-address?user=1&address=2
  • 在这个页面上,他得到一个表格,他可以在其中修改这个地址。

我决定绕过聚合根,这很简单:

  • 我们将直接Address加载Id
  • 我们会更新它,然后保存它

因为我们想用 DDD 的方式来做,所以我们有不同的解决方案:

  1. 我们要么要求用户通过 Id 获取此地址

    address = user.getAddress(id);
    address.setPostCode("12345");
    address.setCity("New York");
    em.persist(user);

    这种方法的问题是,IMO,聚合根仍然无法更好地控制地址的处理方式。它只是返回对它的引用,因此这与绕过聚合没有太大区别。

  2. 或者我们告诉聚合更新现有地址

    user.updateAddress(id, "12345", "New York");
    em.persist(user);

    现在聚合可以控制对该地址的处理,并且可以采取任何与更新地址相关的必要操作。

  3. 或者我们将地址视为一个值对象,我们不更新我们的Address,而是删除它并重新创建它

    user.removeAddress(id);
    address = new Address();
    address.setPostCode("12345");
    address.setCity("New York");
    user.addAddress(address);
    em.persist(user);

    最后一个解决方案看起来很优雅,但意味着地址不能是实体。那么,如果它需要被视为一个实体,例如因为聚合中的另一个业务对象具有对它的引用,该怎么办?

我很确定我在这里遗漏了一些东西来正确理解聚合概念以及它是如何在现实生活中的例子中使用的,所以请不要犹豫,提出你的意见!

4

1 回答 1

7

不,您没有遗漏任何东西 - 在大多数情况下,最好的选择是2 号(尽管我会调用该方法changeAddress而不是updateAdress- update 似乎不是 DDD),这与地址是实体还是值对象无关。使用无处不在的语言,您宁愿说用户更改了他的地址,所以这正是您应该建模的changeAddress方式 - 这是决定是更新属性(如果地址是实体)还是分配全新对象(当它是 VO)的方法.

以下示例代码假设最常见的场景 - 地址为 VO:

    public void ChangeAddress(AddressParams addressParams)
    {
        // here we might include some validation

        address = new Address(addressParams);

        // here we might include additional actions related with changing address
        // for example marking user as required to confirm address before
        // next billing
    }

此示例中重要的是,一旦创建了 Address,它就被认为是有效的 - 在您的聚合中不能有无效的 Address 对象。但是请记住,您是否应该遵循此示例取决于您的实际域 - 没有一条可以遵循的路径。这是最常见的一种。

是的,您应该始终通过遍历聚合根来对您的实体执行操作——原因在许多关于 SO 的答案中都给出了(例如在这个 Basic Aggregate Question中)。

某物是实体还是 VO 取决于需求和您的领域。大多数时候地址只是一个值对象,因为具有相同值的两个地址之间没有区别,并且地址在其生命周期内往往不会改变。但同样,大多数情况下,这取决于您正在建模的领域。

另一个例子 - 对于大多数域 aMoney将是一个值对象 - 10$ 是 10$,它除了数量之外没有任何标识。但是,如果您要对一个在票据级别上处理货币的域进行建模,则每个票据都有自己的身份(用某种唯一编号表示),因此它将是一个实体。

于 2011-08-25T23:06:30.343 回答