去年くらいから、職場でDDDを取り入れ始めた
今までDDDを聞き齧ってはいたが、ドメイン駆動設計に基づいてソフトウェア開発をしたことはなかった
最初にドメインモデルを仮組みして、ドメインクラスを使って業務を行うユースケースクラスを作り、フロントアプリから呼び出すためのAPIエンドポイントを作る
この時、私の頭の中にはこういう構造があった
この時なぜか「presentation層は絶対にドメインクラスを参照しちゃいけない」と思い込んでいた
なので、Controllerのリクエスト/レスポンス、UseCaseのリクエストにはDTOを使う設計にした
その結果、ドメイン層にたどり着く前に二回もデータの移し替えが発生することとなった
Controller用リクエストdto
↓
UseCase用リクエストdto
↓
ドメインクラス
これはおかしいと思って別チームに相談したところ「他のレイヤーを意図的にドメイン層に依存させるというのも手なんですよ」というアドバイスをもらい、下記のような構造に変わった
Controllerのリクエスト・レスポンスのみdtoを用意し、それ以外はドメインクラスを介して処理を行う形にした。
このような構造になった結果、どの層でもドメインクラスを使うようになった。
データ変換の回数は半減して、無駄なコードが減った
今まで基本データ型で扱っていた値がエンティティ・値オブジェクトとなったことで、どのレイヤの処理でもドメインのルールに則ったオブジェクトが扱われていることが保障されるようになった
思ったこと・分かったこと
私が最初考えていた構造は、レイヤ間の独立性を重視したアーキテクチャだった
その方法だと、各レイヤの独立性を高めることができるというメリットがあり、複数のチームが手分けして開発を進めるような環境では利点となる
しかし、レイヤ間の独立性を重視すると、レイヤを跨ぐごとにデータ変換を行う必要性が出てくる。データ変換処理に後からロジックを追加することは容易なので、業務ロジックが散逸する環境になりがち
どの層でもドメインクラスを使うようにすると、ロジックは自然とドメイン層に集約されるようになる。各レイヤーをドメイン層に依存させることで、業務ルールに反する動きをさせないような構造を作ることができる
私が扱っているシステムのクライアントはフロントエンドアプリであって、APIのインターフェースはある程度フロント側に寄り添った仕様にする必要があったため、今回はControllerのリクエスト・レスポンスのみdtoを用意することにした。だが、クライアントの性質よってはドメインクラスをそのまま使ってしまうという選択肢もある