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メソッドにドキュメントを追加して、2 つのアカウントが関係する場合にサービスを使用する必要があることを伝えます。私は、DDD開発者は、DDDで物事を行う方法であるため、サービスを使用する必要があることを知っておく必要があります(あなたと私はそうしました、そしてDDDの経験を持つ次の開発者もそうする必要があります)。

于 2012-09-11T05:53:34.877 に答える
1

ビジネスロジックはドメインオブジェクトに含める必要があるため、ビジネスロジックを配置する代わりに、 サービスへのビジネスロジックのリークを回避するためのより良い方法は、containsとでTransferService呼び出される新しいエンティティを作成することです(申し訳ありませんが、ここではC#を使用します) )::AccountTransferAccountFromAccountTo

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. どのような転送:ビザ、ペイパル経由の転送...。
  3. このクラスをデータベースに取り込むには、転送履歴を保存して後で追跡します。

このようにして、IsValidメソッドもAccountTransferプライベートメソッドとして内部に配置します。

于 2012-09-11T06:09:02.903 に答える