Open8

MVCとADR(Action-Domain-Responder)をざっくりと

awonosukeawonosuke

mvcの考え方で責務は分けることは出来るが、何も考えずに実装すると境界が曖昧になる。

adr:責務をより限定的にすることで、分かりやすくした

awonosukeawonosuke
  • adr:ビジネスロジック、リクエスト処理、レスポンス成形を分離する考え

    • 互いを疎結合にしたい、その状態を望む
  • mvc:コントローラにリクエスト処理、ビジネスロジック、レスポンス成形が混ざる場合が多い

    • 結果としてコントローラ、クラスの肥大化
    • コントロール内のメソッドが密結合になりがち
awonosukeawonosuke

https://nextat.co.jp/staff/archives/174

  • Model, Domain
    • ほぼ同じ、宗教論争になる
  • Controller, Action
    • 1アクション1クラス
    • アクションに対する横断処理、合成処理のやりやすさ
    • 神コントローラの誕生を阻止
  • View, Responder
    • ビューはテンプレートを使うとは限らない(JSON返す時など)

Presentation Domain Separationの原則

  • MVCが本当に実現したかったこと
  • ドメイン層はプレゼンテーション層に比べ使い回しやすく変更されにくい
  • 疎結合にしておくと幸せになれる

ビューの役割

  • ドメイン(モデル)層の処理結果をユーザーにどう見せるかを決めるロジック
  • クライアントが違えばどう見せるべきかも変わる
    • ブラウザ、コマンドライン

Webアプリケーションの”ビュー”

  • ユーザーモデル($userなどドメインの出力)→変換→HTTPレスポンス(HTML, JSON, etc.)
  • テンプレート→レスポンスボディのみ
  • ビューはステータスコード、HTTPレスポンスヘッダも扱うべき対象となる

ControllerにWebアプリケーションでの”ビュー”の処理(責務)が混在してる
ステータスコード、HTTPレスポンスヘッダなど

public function show($user_id, UserShowUseCase $useCase)
{
    $user = $useCase->run($user_id);

    // ここから
    if (is_null($user)) {
        return response('Not Found', 404);
    }
    return view('users.show', ['user' => $user]);
    // ここまで
}

Responder

  • クラスを定義することでHTML, JSONなどでResponderを入れ替えることで出しわけ可能
  • Domainは使い回すことができる→疎結合、責務の分離ができる

まとめ

  • ADRはMVCが本当にやりたかったこと
  • Webアプリケーションでの”ビュー”はHTTPレスポンスを生成する処理のこと
  • テンプレートだけが”ビュー”ではない

ADRパターンのデメリット

  • Actionのファイルに1つ1つコンストラクタ注入を書くのがだるい
  • 複数のActionでメソッドを共有するときControllerでprivateメソッドのような楽ができない
  • Responderクラスをいちいち作るのが面倒
  • 処理がController以外に分散して一覧性が悪い

ADRとMVCの中間は?

  • Controllerの分割
  • ControllerクラスのままでResponderの導入
awonosukeawonosuke

https://zenn.dev/naoki_oshiumi/articles/0467a0ecf4d56a

Repositoryパターンを採用する際のEntity, Service, Repositoryの棲み分け

  • Service:アプリケーションビジネスルール担当
  • Repository:DB、API通信の担当(Serviceから呼び出される)
  • Entity:エンタープライズビジネスルール担当

おまけ(Webサービスを前提とする)

  • Responder:HTTPレスポンスの成形(ヘッダ、ボディなど)
  • Action:ServiceとResponserの橋渡し(リクエスト→処理:Service→レスポンス:Responder)