5

より多くの産業または自動化関連のアプリケーション (管理しなければならない外部コンポーネントに大きく依存しているアプリケーション) では、実際の問題からの抽象化だけでなく、表現も含むモデルがドメインに含まれている場合がよくあります。ドメインの外に物理的に存在するものへのポインター。

たとえば、ネットワーク デバイスを表す次のドメイン エンティティを考えてみましょう。

public class NetworkDevice {
   public IPAddress IpAddress { get; set; }
}

そのようなエンティティを保存または検証したり、エンティティの変更時にアクションを実行したりするだけでなく、アプリケーションは、ドメイン内の表現に基づいて外部コンポーネントを管理する必要がある場合があります。では、DDD はそのような場合にも適しているのでしょうか? それらのマネージャはドメイン サービスですか?

Eric Evans は有名なブルー ブックで、ドメイン サービスは、エンティティまたはリポジトリが単独では処理できない要求を満たすために、ユビキトス言語から取得したメソッドを実装するステートレス モデルである必要があると説明しています。しかし、サービスがステートフルである必要がある場合はどうでしょうか?

簡単な例: アプリケーションは、状態イベントについてドメイン内の他のアプリケーションに通知するために、ネットワーク内の構成された IP デバイスを監視する必要があります。IP デバイスがアプリケーション内に登録されると (たとえば、データベース内に保存されます)、「ping サービス」が通知され、デバイスの監視を開始します。

public class PingMonitor : IDisposable,
   IHandle<DeviceRegisteredEvent>,
   IHandle<DeviceRemovedEvent> 
{

    public List<NetworkDevice> _devices = new List<NetworkDevice>();

    public void Handle(DeviceRegisteredEvent @event) {
        _devices.Add(@event.Device);
    }

    public void Handle(DeviceRemovedEvent @event) {
        _devices.Remove(@event.Device);
    }

    public void PingWorker() {
        foreach(var device in _devices) {
            var status = Ping(device.IpAddress);
            if(status != statusBefore)
                DomainEvents.Raise<DeviceStateEvent>(new DeviceStateEvent(device, status));
        }
    }

}

次に、他のコンポーネントがこれらのステータス イベントを処理し、たとえば、デバイスがオフラインになると、他のプロトコルを介したデバイスとの通信を停止できます。

さて、それらのコンポーネントは何ですか?最初は、ドメインの特定の要件を満たすため、ドメイン サービスだと思っていました。ただし、これらはステートフルであり、ユビキトス言語を具体的に表していません( ping サービスのタスクは、ドメイン エンティティにpingを実行し、その状態を報告することですが、 ping サービスは、クライアントが ping を許可するメソッドを実装していません)。デバイス)。

それらはアプリケーション サービスですか。そのようなコンポーネントは DDD パターンのどこに収まりますか?

4

2 に答える 2

2

DDD では、長時間実行されるプロセスはSagaと呼ばれます。これは通常、ドメイン イベントを使用して実装されます。

トピックの紹介は次のとおりです

于 2014-03-07T13:31:03.310 に答える
1

私はかつて同様の機能を実装しましたが、それが役立つことを願っています:)

私たちの組織は、オンライン決済処理アプリケーションを所有しています。顧客が支払いを完了すると、オンライン決済プロバイダーは成功または失敗を示す通知を送信します。ネットワーク障害が発生すると、通知がアプリケーションに届かないことがあります。したがって、不満を持った顧客がここに来ます。そのため、自動チェックメカニズムが必要です。

アプリケーション ランナーは、チェックの実行を維持する責任があります。

public class CheckingBatch {
    private TransactionChecker transactionChecker;

    public void run() {
        List<Transaction> transactions = transactionsToBeChecked();
        for (Transaction transaction : transactions) {
                //publish events if the transaction needs check
                doCheck(transaction, now);                }
        } 
    }

    private List<Transaction> transactionsToBeChecked() {
         return transactionRepository.findBy(transactionChecker
            .aToBeCheckedSpec());
    }
}

別のアプリケーション サービスがイベントをリッスンし、実際のチェックを行います。

public class CheckTransactionServiceImpl implements CheckTransactionService {
    private TransactionChecker transactionChecker;

    @Transactional
    public void check(final TransactionNo transactionNo) {
        Transaction transaction = transactionRepository.find(transactionNo);
        CheckResult result = transactionChecker.check(transaction);
        //handle check result
    }
}

TransactionCheck は、オンライン決済ソリューションに依存しないドメイン サービスです。

public interface TransactionChecker {
/**
 * 
 * | data between online-payment provider and ours | txn STATUS | RESULT |<br>
 * | consistent | CLOSED | VALID |<br>
 * | inconsistent | CLOSED | INVALID |<br>
 * others omitted
 */
    CheckResult check(Transaction transaction);
/**
 * returns txn specification to filter to be checked ones.
 */
    ToBeCheckedSpecification aToBeCheckedSpec();
}

ご覧のとおり、アプリケーション サービスとドメイン サービスの両方がステートレスになりました。

私見、Pingはドメインサービス(TxnCheckerに関連)ですが、モニターは一種のアプリケーションサービス(CheckingBatchに関連)です。

于 2014-03-06T10:24:34.357 に答える