web-dev-qa-db-ja.com

DDD-ドメインオブジェクトのビジネスルールを外部サービスに委任する

状況:

最初のプロジェクトで [〜#〜] ddd [〜#〜] を実装しています。戦略パターンを正しく実装する方法を明確にしたいと思います(私の場合、APIトークンがアクティブかどうかを確認します)。これはApiTokenインスタンスのビジネスルールですが、この戦略にはさまざまな実装が考えられるため、このロジックを外部実装に委任したいと思います。

実装:

ApiTokenクラス:

public abstract class ApiToken {
    public abstract boolean isActive(TokenActiveStrategy strategy);
}

これはトークン戦略コントラクトです:

public interface TokenStrategy {
    boolean isActive(final ApiToken token);
}

そして使い方:

TokenStrategy tokenStrategy = new DatabaseTokenStrategy();

if (!token.isActive(tokenStrategy)) {
   throw new AuthenticationException(ExceptionCodeType.TOKEN_NOT_ACTIVE);
}

そして具体的なApiTokenクラス:

@Override
    public boolean isActive(final TokenStrategy strategy) {
        return strategy.isActive(this);
    }

質問:

DDDの原則に関して、ドメインオブジェクトのドメインビジネスルールoutのチェックを委任しても問題ありませんか?

3
Artegon

ドメインオブジェクトは、それ自体のコンテキスト外の情報を提供する責任はありません。 APIトークンがアクティブであるかどうかは、トークン自体が回答できるものではなく、APIプロバイダーへの質問です。APIプロバイダーが真実の源です。

現実世界のよい例えは、車が登録されているかどうかを教えてもらえますか?いいえ、グローブボックスにナンバープレートや登録用紙が入っていてもできません。地元のAuto/Roads当局だけがその質問に正直に答えることができます。

私にとって、実装しようとしている機能(ApiTokenがアクティブかどうかの確認)は、ドメインサービスに常駐させる必要があります。次に、ドメインサービスの具体的な実装を作成すると、itがAPIプロバイダーを呼び出すことができます(単体テストの場合は、それをスタブで模擬できます)。

if (!apiTokenService.isTokenActive(token)) {
    throw new AuthenticationException(ExceptionCodeType.TOKEN_NOT_ACTIVE);
}

(コードがないため申し訳ありませんが、Java(?)は私の強みではありません)

4
e_i_pi

残念ながら、これらのことを行う方法の客観的な単一の真実はありません。それは常にDDDの解釈と、作業しているコンテキストに依存します。

解釈

1つの解釈では、Entitiesはデータホルダーまたはレコードにすぎず、Servicesまたはその他のサポートクラス。この解釈では、あなたのApiTokenにはisActive()メソッドすらなく、代わりにすべてのデータを( getters を介して)発行し、他のクラスに処理を任せます彼らが好きなように。

ただし、オブジェクト指向のコンテキストで作業する場合は、解釈が大幅に異なる可能性があります。この場合、提案されたソリューションには2つの問題があります。

  1. Strategyオブジェクトは、ApiToken内のすべてに完全にアクセスできる必要があります。言い換えれば、それらは非常に密に結合されます。これはOO世界では眉をひそめています。

  2. Strategyクラスはドメインの一部ではありません。開発者とビジネスの間で共有される語彙の一部ではありません。 ユビキタス言語 の一部ではありません。

OO + DDDを考慮した1つの可能なソリューション

私はあなたの要件のすべてを知らないという通常の免責事項で、これを行うことはどうですか:

_public interface ApiToken {
    boolean isActive();
}

public final class DatabaseApiToken {
    ...
    @Override
    public boolean isActive() {
        ...sql or whatever...
    }
}
_

これははるかに単純で、上記の両方の問題を解決し、DDDとOOの両方に対応しています。

その他のポイント

また、whyを見て、メソッドisActive()が必要です!時には(常にではありませんが)実際に単一のユースケースがあり、それ自体をintoApiTokenに移動できるため、 isActive()は不要であり、ApiTokenにはより完全なロジックがあるため、これは良いことです。

これが オブジェクト指向ドメイン駆動設計 についての私のプレゼンテーションで、いくつかの追加ポイントがあります。

1