メシのタネ

メシのタネになる、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 を使っています。コメントデータの処理方法の詳細はこちらをご覧ください