本記事は、DDD-Community-Jp Advent Calendar 2020 の8日目で、
5日目に @jnuank さんが投稿した 『リポジトリのインターフェースはどこに置く?』 に対して、自分なりに回答したものとなります。
■ はじめに
まず「リポジトリのインターフェースをどの層に置くべきか?」という問いに対しては、
その前提として、
- そもそも「ドメイン」とは何であり、
- どんなアーキテクチャを前提としていて(どんな層があって)、
- だからどの層にどんな役割があるか
といった前提を明らかにした上で、「結果として何をどこに配置するのか」を話す必要があるように思います。
これらの概念がずれていると、お互いの話がすれ違う原因となるためです。
次章より、現時点の私が考えている前提と、なぜ UseCase/Application 層に置くか? という理由について、言語化を試みてみようと思います。
■ 前提(アーキテクチャ)
まずは先に前提とするアーキテクチャから。
自分の考え方は、ベースに クリーンアーキテクチャ や ヘキサゴナルなどのオニオン系アーキテクチャ、ひいては Port & Adapter パターン があり、『いかにドメインを守るか?』 という事を強く意識しています。
詳しい理由については後述しますが、この「ドメインを守る」という考え から、
自分は 「リポジトリのインターフェースは UseCase/Application 層に置くべきだ」 と考えています。
ただしこれは絶対にという話ではなく、「私はそう考えている」というだけなので注意してください。
一般的には Domain 層に置くパターンが比較的多いように思います(根拠なし)。
また Domain 層に置くパターンを否定するものではありません。
何らかのアーキテクチャに則って 皆の意識が統一されていれば何処に置いても構いません。
■ 前提(ドメインと言う言葉と、ドメイン層について)
現時点での自分なりのドメイン、ドメインオブジェクト、ドメイン層に関する考えを以下のように纏めました。
- ドメイン とは、「何らかの活動における知識や体系、それらの領域」 のこと。
- ドメイン層 とは、**外界から完全に遮断されており、ドメインを形作る小さなルールや「最小単位の仕事(集約)」**を扱う場所。
-
ドメインオブジェクト とは、ドメインを形作る「小さな閉じたルール」 のこと。
- 大小様々な閉じたルールを組み合わせた、最小単位の閉じた仕事が「集約」 。
- 「○○Id」や「××Name」といったクラス(値オブジェクト)が、「最も小さな閉じたルール」。
「閉じた」 という言葉を使っているのは、外界の様々なものから隔離されたピュアなルールである事を表すためです。
また 「小さな」 という言葉を使っているのは、ドメイン層に存在するものは、
「究極に昇華された個々のピュアなビジネスルール/仕事になっていてほしい」 という思いがあるからです。
■ だからどうなる?
「永続化はドメインに閉じたルールではない」 ので、ドメイン層ではなく「ユースケース層に置く」。
この考え方のポイントは、ドメイン層を「外部から閉じて守られ安全になった世界」として扱う 事です。
そのため、外部の世界へのやり取りに関わるリポジトリのインターフェースは、ドメイン層に配置したくない のです。
もしもそれがビジネスのルールだと思うのであれば、それは集約の範囲が間違っているのでは?という感覚(暴論) です。
あくまでも、ユースケース層ですべてをお膳立てしたうえで、閉じた知識群を使って安全にビジネスを駆動したいという考えに則っています。
したがって ユースケース層の役割 は、
- 小さな仕事を連結して、大きな仕事をさせること
- 小さな仕事の準備
- 小さな仕事の結果を何らかの形で取り扱う
となります。
また実際の処理の流れは以下のようなイメージになります。
- ユースケース層で集約を取ってきたりと準備する
- ドメイン層にある集約を介して、ピュアなビジネスルールを組み合わせて小さな仕事をする ==> 集約に変更が発生する
- ユースケース層で集約に起きた変更を永続化する
■ 今後の展望
ドメイン層は閉じたピュアで守られた世界だから、外とつながるリポジトリのインターフェースはユースケース層に置くんだ!
という形になるのですが、最近ではユースケース層とドメイン層とは異なる層がどこかにあって、
そこへインターフェースを置くべきかもしれない、という思いが沸いています。
それは「ユースケース層」という名前から、そこに置くのが本当に最適解なのだろうか? という点にうっすらとした違和感を覚えているためです。
ドメイン層を閉じたものとできますし、依存関係を外から内のみにも出来てはいるのですが、どうにも理由が後ろ向きでありもう一押しほしい感じがしています。
新しく層を作るべきなのか、それとも Port のような名前でユースケース層に入れるべきなのか・・・
などなど、これらの部分についてはもう少し検討が必要そうです。
改めて何か思いついたら、再度記事にしてみようと思います。