🧠
DDD実装パターンのまとめ
DDD実装パターンのまとめ
DDD実装パターンを調べ倒して自分なりに検討したものをまとめてみました。
もちろん決してこれが正解ではないしあくまで実装パターンのみに過ぎないので、備忘録かつ誰かの参考になったらいいと思います。
Domain層
- ソフトウェアが解決したい業務における問題領域。他のどの層にも依存しない。
-
Entity
- アプリケーションが解決したい事項の登場人物(ヒト・モノ・コト)をコードで表現したオブジェクト。
- EntityCollection
- Entityの配列を持つコレクションオブジェクト。
-
EntityFactory
- Entityの生成を担うクラス。
- EntityCollectionFactory
- EntityCollectionの生成を担うクラス。
-
ValueObject
- Entity一部のプロパティを切り出して知識を持たせたオブジェクト。
- ValueObjectCollection
- ValueObjectの配列を持つコレクションオブジェクト。
-
RepositoryInterface
- Domain層とInfrastructure層の依存関係を逆転させるためのInterface。実装はInfrastructure層に記述する。
-
DomainService
- エンティティや値オブジェクトの責務ではない業務のロジック、特定のドメインオブジェクトに属さないビジネスロジックを記述する。
- 値オブジェクトやエンティティと異なり「ドメイン特有のインスタンス変数」を持たない。あくまでドメインサービスは振る舞いに特化したクラスになる
- ビジネスルールとして名前がつけられるかどうか
Infrastructure層
- DBを含む外部サービスとの入出力をする層
-
Repository
- Entityの永続化(DBへの保存・更新・削除)、または参照(取得)を責務とするクラス。
- 基本的に入力(メソッドの引数)はEntityまたはValueObject、出力がある場合(メソッドの返り値)はEntity(Collection)を返す。
-
QueryService
- 特定のユースケースや、フロントから要求されるデータ型(ページネーション等)の参照(取得)を責務とするクラス。
- DBから要求されたデータを取得・生成し、専用のDtoにして返却する。
- InterfaceはApplication層に設置し、Application層は「このような条件を指定すると、このような型で返ってくる」というという抽象的な知識だけ持ち、実装の知識はインフラ層に隠蔽する。
- CQRS(コマンドクエリ責務分離)は導入するメリットは大きいが、コードの複雑性も上げてしまうとのこと。
Application層
- ドメイン層のオブジェクトを使って、アプリケーションとして成り立たせるための機能を実現させる層
-
Dto
- DataTransferObjectの略称。ドメイン層のオブジェクトを、データとして扱いやすい形に加工するオブジェクト。主にApplication層からPresentation層に値を返却するために使用する。
- DtoCollection
- Dtoの配列を持つコレクションオブジェクト。
-
DtoFactory
- Dtoの生成を担うクラス。
- DtoCollectionFactory
- DtoCollectionの生成を担うクラス。
-
Command
- Usecaseのクラス内メソッドの引数として渡されるオブジェクト。主にPresentation層で生成され、Presentation層で受け取ったリクエストのデータを各Usecaseに対応する形で加工し、Usecaseに渡される。
-
CommandFactory
- Commandの生成を担うクラス。
-
Usecase
- アプリケーションとして成り立たせるための機能を実現させるオブジェクト。主にPresentation層から渡されたCommandオブジェクトからドメインオブジェクト(EntityもしくはValueObject)を生成し、Repository・QueryService等を呼び出して永続化(保存・更新)もしくは参照(取得)を行う。
- Entity等ドメインオブジェクトをPresentaion層に返却する場合は、対応するDtoに変換して返却する。(ドメインオブジェクトにプレゼンテーション層に関連する処理が混入するのを防ぐ、エンティティが持つメソッドをプレゼンテーション層で使えてしまうことを防ぐ、DTOをかませることでドメイン層の修正の影響をプレゼンテーション層が直接受けなくなる)
-
QueryServiceInterface
- Infrastructure層にあるQueryServiceのInterface。
Presentation層
- リクエスト取得・レスポンス返却等、クライアント側との疎通を行う層
-
ViewModel
- 主にControllerからクライアント側に出力する際に、クライアント側が要求する形に加工するためのオブジェクト。
- 基本的にApplication層から受け取ったDtoを加工する。
- ViewModelCollection
- ViewModelの配列を持つコレクションオブジェクト。
-
ViewModelFactory
- ViewModelの生成を担うクラス。
- ViewModelCollectionFactory
- ViewModelCollectionの生成を担うクラス。
-
Controller
- クライアント側からのリクエスト取得・レスポンス返却を担うクラス。
- 基本的にリクエストのデータからCommandオブジェクトを生成→UsecaseにCommandオブジェクトを渡す→Usecaseに返り値がある場合はDtoを受け取る→DtoからViewModelを生成→ViewModelのデータをレスポンスとして返却という処理を行う。
フロントエンドではどうしたらいい?
どうしてもサーバーサイドの話になりがちだが、フロントエンドでは導入できないんだろうかと思いつつ、いまだにしっくり来るパターンは考えられていません。
下記記事は参考になりました。
- WEBフロントエンドにおけるソフトウェア設計の考察 / Consideration of software design in WEB front end
- フロントエンドの複雑さに立ち向かう / Tackling Complexity of Front-end Software with DDD and Clean Architecture
- フロントエンド✖️DDDで自社サービスの新規機能開発をした話
参考ソースコード
参考記事・画像
-
DDDで外部サービスを使う場合に、どのレイヤにいれるか迷ったのでおしえていただけますでしょうか。 1. | Peing -質問箱-
-
- 本記事にとっては身も蓋もないタイトルの記事ですが、かなり参考になった記事です。
Discussion