メシのタネ

メシのタネになる、AIや技術総合情報のサイト


操作する側が主語になるとき、それはRepositoryの振る舞いとして適切なのか?


  1. Architecture
  2. 操作する側が主語になるとき、それはRepositoryの振る舞いとして適切なのか?

プルリクのレビューしてると、
「それお前の趣味じゃん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 を使っているかどうかでもない。
クリーンアーキテクチャを採用しているかでもない。

主語を見ているかどうか。
責務の言葉で語れているかどうか。

これが見えていないまま進むと、最後は必ずこう終わる。

まあ、好みだよね。

そう言われてモヤっとしたなら、あなたの違和感は正しい。

その違和感は、設計のズレを捉えることができている。


コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください。