見出し画像

Reading: ドメイン駆動設計 モデリング実装ガイド

久しぶりに開発中心の案件を間近に控えているので、設計を適切に行えるようにDDDの知識を蓄えておこうと思う。
実際のところ、やろうと思いながら先延ばしにしていたのだけど、後押ししたのが、近頃同僚たちとした、RESTful APIにおける「リソース」とはなにか、という問題。

基本的にRESTful APIではエンドポイントはリソースにし、GETやPOST、PUT、DELETEなどによって操作することを実現できるように作る。
と言った時にそのリソースとは一体何であって何でないのか。

* リソース自体に明確な指針はなく、アプリの仕様や利便性から自由にできる、決まっているのはそれが名詞であるということだけ
* どのような粒度でエンドポイントのリソースを定義するかは設計の腕の見せ所
* 将来の成長をどこまで織り込むかによってエンドポイントの名称の付け方などにも変化は生じる

といった話が上がった。
それこそ、次のようなエンドポイントはありなのかなしなのか、も意見が分かれた。

/employees/$id/department
/employees/$id/rank

基本的には、なしではない、が、できることならパラメーターによって応答フィールドの指定のような対応で済ませたい、がその場での結論だった。
この辺り、RFCなどにも何かしら良いまとめがあるわけではなさそうだったので、RESTful APIの世界よりももう少し広く、モデリングの対象となっている現実とのつながりの部分にフォーカスしないといけないのだと思った。

というわけで前置きが長くなったけれど、DDDを勉強していくことにする。

序盤で外してはいけない定義について書いている。

それでは、人々はなぜ、ソフトウェアを開発するのでしょうか? それは、ソフトウェアによって、ある領域に存在する特定の問題を解決するためと言えるでしょう。この「ソフトウェアで問題解決しようとする対象領域」を「ドメイン」と呼びます。

出典:ドメイン駆動設計 モデリング実装ガイド pp.10-11

つまり、DDDにおいてはドメインは問題解決しようとする対象領域、と。
問題解決のアプローチとしては、ドメインを定義して、モデルを作り、そのモデルの内容をソフトウェアに反映し、不足があればドメインを改善し、以下続く、という流れの様子。

実装との絡みで理解しやすかったのは、オニオンアーキテクチャーを前提とした、ユースケースをまず書いて、実装をユースケース層とドメイン層に分けるという記載。
Javaでプログラムを書くときやりがちなのはPOJOと称して、ドメイン知識(=ルール・制約)は持たせず属性のみを定義するというもの。
それをここでは、定番のなんでも受け取るSetterは排して、ドメイン知識に従った実装を加える。
例えば、あるタスクの延期可能回数は3回まで、といったルールがあったとしたら、延期処理の知識はドメイン上のTaskに持たせて3回を超えていたらできないようにするとか。

そこで、DDD ではモデルが適用される範囲を明示的に定義し、それぞれの中でモデル、 言語の統一を目指すのです。この明示的に定義された範囲を「境界づけられたコンテキスト」と呼びます。

出典:ドメイン駆動設計 モデリング実装ガイド p.44

書籍の中でも触れられているけど、システムがでかくなると、利用するコンテキストの混ざった内容になってしまって、特に後から開発者が入ったときなどに、依頼された範囲じゃないからわからないので触れない、というレガシーコードが発生してしまう、というのも経験上よくあった。
なので、コンテキストを分けるという考え方はとても好き。(実装をどうするかは別の話としてあるけれど)

読んでいくうちに、usecase / domain / presentation / infrastructure の責務に分けて実装していくのを早く手の内にしたいと思い、とりあえず手を動かし始めた。
で、アイデアを形にしていくの楽しいなと思い始めた矢先にQuarkus(Javaの最新軽量高速フレームワーク)で依存性注入をリポジトリパターンと併せて実現する方法が分からなくて詰まった。
かれこれ2時間は調査したけど解決に至らず、結局Stack Overflowに質問投稿している。回答つくといいけれど。

と思ったら、数分で回答ついた。ただの凡ミスだった......。気を取り直して頑張ろう。

posted on: https://blog.tkhm.dev/2020/08/reading.html