2

当涉及多个聚合时,我对域应该执行业务规则的方式表示怀疑。

假设我有帐户和外部帐户聚合:

public class Account {
    public String getId() {...}
    public void add (Double amount) {}
}

public class ExternalAccount {
    public String getId() {...}
    public void add (Double amount) {}
}

和这项服务:

public class TransferService implements TransferServiceInterface {
    public void transfer (String AccountId, String ExternalAccountId, Double amount) {
        Account fromAccount = accRepository.get(AccountId);
        ExternalAccount toAccount = extAccRepository.get(ExternalAccountId);

        transferIsValid(fromAccount, toAccount, amount);

        fromAccount.add(-amount);
        toAccount.add(amount);
    }
}

如果传输不符合域规则,则 transferIsValid 将抛出异常。

如何防止此模型的用户不使用服务并执行以下操作:

    Account fromAccount = accRepository.get(AccountId);
    ExternalAccount toAccount = extAccRepository.get(ExternalAccountId);

    fromAccount.add(-amount);
    toAccount.add(amount);

用户没有使用该服务,也没有使用 transferIsValid(...) 来检查完整性。我相信我的设计存在错误,因为用户不应该做一些无效的事情。我该如何预防?我的设计中的错误在哪里?

4

2 回答 2

4

首先:不要使用Add()退出。DDD 就是关注领域。而且我认为您So when I add a negative amount of money to account A, the equal amount will be added to account B在与产品负责人交谈时不会这么说。添加一个Widthdraw方法。


记住。编码时不涉及任何用户。程序员是。所有程序员都可以搞砸代码。

关于服务:您无法通过代码来防止这种情况发生。除非提款的唯一有效方式是将其转移到另一个帐户。在这种情况下,您可以更改Widthdraw()方法以将另一个帐户作为参数。

除此之外,只需将文档添加到您的Widthdraw方法中,并说如果涉及两个帐户,则应使用该服务。恕我直言,任何 DDD 开发人员都应该知道应该使用该服务,因为这是我们在 DDD 中做事的方式(你和我都这样做了,下一个具有 DDD 经验的开发人员也应该这样做)。

于 2012-09-11T05:53:34.877 回答
1

业务逻辑应该在 domain object中,因此,与其将业务逻辑放入 TransferService,我认为,避免业务逻辑泄漏到 Service 的更好方法是创建新的 Entity 调用AccountTransfercontains AccountFromand AccountTo,类似于(对不起,我在这里使用 C# ):

public class AccountTransfer
{
    Account From { get; set; }
    Account To { get; set; }

    // More properties         

    private bool IsValid(ammount)
    {}

    public void DoTransfer(int amount)
    {
        is (IsValid(ammount))
        {
            From.Withdraw(amount);
            To.Add(amount);
        }
    }
}

您可能需要对象中的更多信息,AccountTransfer例如:

  1. 何时转移
  2. 什么样的转账:通过visa转账,paypal....
  3. 要将此类填充到数据库中,您需要存储传输历史记录以便以后跟踪它们。

AccountTransfer通过这种方式,您还可以将 IsValid 方法作为私有方法放入其中。

于 2012-09-11T06:09:02.903 回答