DDD
ドメイン駆動設計

ちょっとずつ読むドメイン駆動設計 第ニ部 モデル駆動設計の構成要素 第四章 ドメインを隔離する4

レイヤ化アーキテクチャの難点

レイヤ化アーキテクチャ.png

先日DDD本で紹介されているレイヤ化アーキテクチャは、上図の通り、モデルがインフラストラクチャに依存してしまっていると書きました。

たとえばどんな時にそうなるかというと、あるオブジェクトがアプリケーション全体で一意であることを確認するために、モデルがインフラストラクチャに問い合わせて、DB内のテーブルを検索する、などなど。。。

では、どうするか。いくつかの候補が「実践ドメイン駆動設計」で紹介されているので、暫くの間こっちを読んで行こうと思います。

他の選択肢 DIを使う

DI (2).png

上位モジュールは下位モジュールに依存してはならない。どちらのモジュールも、抽象に依存すべきである。抽象は、実装の詳細に依存すべきではない。実装の詳細が、抽象に依存すべきである。(実装ドメイン駆動設計 4.2レイヤより)

先ほどの例

あるオブジェクトがアプリケーション全体で一意であることを確認するために、モデルがインフラストラクチャに問い合わせて、DB内のテーブルを検索する

で言えば、モデルはインターフェイスであるRepositoryを呼び出し、その実装はインフラストラクチャでされているが、DIを使用してインフラストラクチャの実装自体はモデルから隠蔽させます。

以下ソースコード例です

(DI使用前)

SomeModel.java
// domain層
public SomeModel{
  // infrastractureに依存している
  Repository repository = new SomeInfrastracture();

  public isExist(){
    repository.find();
  }
}

interface Repository{
  find();
}

public SomeInfrastracture implements Repository{
  @override
  find(){・・・}
}

(DI使用後)

SomeModel.java
// domain層
public SomeModel{
   // 依存性注入によりinfrastractureの依存が隠蔽された
  @Autowired
  Repository repository

    public isExist(){
    repository.find();
  }
}

interface Repository{
  find();
}

// infrastracure層
@Repository
public SomeInfrastracture implements Repository{
  @override
  find(){・・・}
}

また、上記図ですが、書籍で示されている図よりもっとシンプルにしました。
自分のこれまでの経験では、インフラストラクチャがユーザーインターフェイスを使うことはなかったし、アプリケーションを利用することもなかったです。

また、書籍ではユーザーインターフェイスはドメインを利用しないような図になっていましたが、ユーザーインターフェイスからのデータをモデルに変換する責務をアプリケーションレイヤが負っているのですかね。。。

自分が利用してきたSpringFrameworkではユーザーインターフェイス(SpringFrameworkではController)で自動的にモデルに変換してくれるので、ユーザーインターフェイスがモデルを使用している図になっています。

いずれにしても大事なことはモデルがどこにも依存していないこと、です。