プルリクのレビューしてると、
「それお前の趣味じゃんwwww」
「好みの話ですよね」
「決め。の話だね。」
雑に片付けられて、苛ついたことはないだろうか。
俺はめちゃくちゃある。
こうやって雑に流されかねない設計の問題点を解体して、どうあるべきなのかを考えたい。
こんな会話、見覚えはない?
- 「参照だけだし Repository でよくない?」
- 「QueryService 作るほどでもなくない?」
- 「それ、好みとかの話ですよね?」
そうなのかな、と諦められる人は諦めていい。
多くの現場ではコードも組織の構造も、だいたい歪んでいる。
リファクタは押し付けられたり、組織の構成をどうするとか言われたら面倒だしね。
ただ、判断としてどうするのが良かったのか。
もしそう思ったのなら、以降も付き合ってもらえると嬉しい。
権威が答えをくれるなんてことはない
権威ある設計方針、DDDやクリーンアーキテクチャ。
社内で頭の冴えるあの人が言っていたから、という前例踏襲。
そのまま当てはめれば正解になる答えなんてない。
そんな都合の良いノウハウなんかあるわけがない。
DDDが教えてくれること
DDDは、適切な役割と階層があることを教えてくれる。
- Entity
- Value Object
- Aggregate
- Domain Service
- Repository
世界には文節がある。
一つの塊として扱うべき意味の単位がある、ということだ。
クリーンアーキテクチャが教えてくれること
一方で、クリーンアーキテクチャは、
その役割をどう運用すれば壊れにくいかを教えてくれる。
- UI
- フレームワーク
- 外部依存
- 要件
変わりゆくものに、変わりにくいものを依存させない。
判断・ルール・意味は、できるだけ内側に閉じておけ、という話だ。
整理すると、こんな違いになる
- DDDは「世界の概念」を扱う
- クリーンアーキテクチャは「依存関係」を扱う
- DDDの主戦場はモデリング
- クリーンアーキテクチャの主戦場は境界
- DDDを間違えると意味が壊れる
- クリーンアーキテクチャを間違えると変更が辛くなる
つまり、今揉めている問題は
- Repositoryに実装するのが正しいのか
- QueryServiceに実装するのが正しいのか
- 参照なのか、更新なのか
- DDDなのか、クリーンアーキテクチャなのか
そういう話ではない。
- 実装場所がどこか
- コマンドかクエリーか
- 設計方針として、どのフレームワークを選ぶか
このように形式で考え始めると、
本来考えるべきだったことから、 どんどん遠ざかっていく。
操作する側が主語になる、という違和感
ここで立ち止まって考えたい。
Repository に処理を書くべきか。
QueryService に処理を書くべきか。
それとも「参照だから Repository でいい」のか。
この問いが荒れる理由は単純で、
主語であるべきことが主語になっていないからだ。
本来、設計で問うべき主語はこうだ。
- 状態として成り立っている事実 を扱っているのか
- 今この操作を成立させたい という要求を扱っているのか
実装の都合で立て始めた瞬間に
「ドメイン」から「実装者」へ
「意味」から「操作」へ
静かに議論はズレていく。
主語が「世界」なのか、「操作」なのか
設計で境界が曖昧な処理を考察する時一度、こう問い直してみるといい。
今決めるべきことは
- 事実 なのか
- 操作を成立 なのか
前者なら、それはドメインの話だ。
後者なら、それはアプリケーションの都合だ。
Repository が扱っても良いのはドメインの関心事だけだ。
操作の都合を背負った瞬間に、それはQueryServiceとなる。
具体例で考える
たとえば、ユーザーの退会可否を調べる処理。
## ユーザーは退会可能か一見、ただの参照に見える。
だから言われる。
参照だけだし Repository でよくない?
でも、少しだけ立ち止まる。
この問いの主語は何だ?
- 「ユーザーという存在が、今どういう状態か」
- 「今この操作をしようとしている人に、許可していいか」
後者だとしたら、
それはもう 操作の文脈 だ。
「退会できるか」は、世界の事実ではない
「退会ができるか」依存する何らかのことは簡単に想像がつく
- 未払いがある
- 関連データが残っている
- 管理者操作かどうか
- 画面経由か API 経由か
これらは、
- ユーザーという集約が「どうあるか」ではなく
- 今、何をしようとしているか
で決まる。
つまりこの問いは、
この世界はどうなっているか?
ではなく、
今この操作をしていいか?
という話だ。
ここで主語は、
完全に「操作する側」に移っている。
Repositoryの責務ではない
この判断を Repository に押し込むと、こうなる。
- Repository が操作文脈を知り始める
- 集約が UI やフローの都合を背負い始める
- 「参照なのに複雑」という謎コードが生まれる
これは本当に
これ、好みの設計ですよね?
違うよね。
好みの話に見えるのは、主語を取り違えているからだ。
QueryService は「逃げ道」ではない
QueryService とは、
- 世界の事実を返す場所ではない
- 集約を回復する場所でもない
操作のために、世界を読む視点 を引き受ける場所だ。
だから、
- 複数集約を横断してもいい
- 表示用に整形してもいい
- 「結果」を返していい
それは責務の放棄ではなく、
主語を正しく引き受けている だけだ。
もう一度、最初の問いに戻る
Repository か。
QueryService か。
参照か。
更新か。
この問いが荒れるのは、
どれも 答えに見えて、答えではない からだ。
設計で大事なのは、流派ではなく視点だ
DDD を使っているかどうかでもない。
クリーンアーキテクチャを採用しているかでもない。
主語を見ているかどうか。
責務の言葉で語れているかどうか。
これが見えていないまま進むと、最後は必ずこう終わる。
まあ、好みだよね。
そう言われてモヤっとしたなら、あなたの違和感は正しい。
その違和感は、設計のズレを捉えることができている。


コメントを残す