Laravelでリポジトリを実装してみた+ちょっとした考察
昨日まで参加していたインターンシップ中の実装に関する考察です
プレゼンの切り貼りなので少しみづらいですがご了承ください
laravel触り始めて一週間なので、laravel特有の知識が足りていないので問題点等あればコメントお願いします。
リポジトリパターンの実装
- DDDの文脈で何回か実装した経験があった
- PHPにインターフェースがあることを知らなかった(Javascriptと勘違いしてた)
- 要は永続化処理を分離したい
そもそもMVC is 何?
クライアントからリクエストがきて、ルーティングでリクエスト処理して、コントローラーがModelに処理指示してViewに書き出してクライアントに返すという流れで処理をしている。参考文献の2にいい図がある。
- ControllerがModelに依存
- ViewがControllerに依存
- ControllerがModelに依存していることによりDBを触る処理がController内に記述される
3の依存を無くしたいよねという文脈からリポジトリパターンが来る。
ControllerがModelに依存
今回実装するリポジトリパターンはこれを以下のようにする
青色はインターフェースという意味
依存性逆転の法則
- 抽象に依存せよが標語
- ControllerがDBを触る処理に依存しているのが問題
- Repositoryと呼ばれるインターフェースを噛ませてあげることで抽象に依存させる
リポジトリについて
1 永続化処理を担当する
あくまで永続化処理を担当するインターフェース。その実体に関する知識はもっていない。実装するときにDBであろうが、Fileであろうが、メモリであろうが考慮しない。
2 テストがしやすくなる
役割を分けることにより、DBと通信をしなくては描けなかったテストが(インフラ、環境に依存している)、リポジトリの差し替えでメモリを使用してのテストに変更できるのでテストがしやすくなる。
3 DB入れ替えなどが容易に
リポジトリの実装を差し替えればいい
laravelへの実際の実装
ディレクトリ構造はこのような形
リポジトリは以下のようにインターフェースのみを記述
こちら側が実体。先ほどのインターフェースを実装している。Eloquent Modelを利用して保存処理を書いているのでファイル名にEQをつけている。(命名は後述する参考文献に則っている)
こちらはPostDataAccessとなっているがこれは先ほどのリポジトリのインターフェース。このインターフェースを実装しているものであればこのControllerで使用できるようになる。
依存性の注入はlaravelのproviderで行っている。こちらの、PostDataAccessEQRepositoryをPostDataAccessDBRepositoryなりPostDataAcesssInMemoryRepositoryなどに差し替えることより、インフラを切り替えることができる。便利。
以上でリポジトリの実装完了!
- MVCのC<->M間の依存は大規模になる程可読性やテスト容易性を下げる
- 今回はリポジトリのみの層分けでしたが、大規模開発であればcontroller->usecase->service->repository->infraと分けていくことによりさらに役割を分担できそう(フレームワークに囚われすぎない)
- 役割をきちんと分けることでFatControllerの対策にもなる!
MVCフレームワーク特有のControllerにばりばりDBの処理が依存している状況から脱出できそうですね!
フレーワークに囚われずアーキテクチャを考えて行けるようにしたいです。
ん?
View側でEloquent Modelのメソッドを呼び出すとModelに依存してしまう...
これが理想
viewで呼び出すと...
解決策
- せめてModel依存をControllerまでに抑えたいのでEloquentModelを使うときはControllerまでで抑える->先ほどのリポジトリでの実装の意味がなくなる
- 上と同様の理由でAPIモードなら大丈夫そう->リポジトリ..(略)
- Eloquent Modelはrepositoryの実装内に収める(保存・読み込み処理を担当させる)
三番目の実装方法が依存関係という点であれば上の層にもれないので綺麗に実装できそう。
問題点
- 開発速度とのトレードオフ
EloquentModel(Active Recordパターン)の良い部分を殺してしまっていそう。開発速度をもとめたいのならばガシガシViewだろうがなんだろうが書いていくべきなのかもしれない。
- 実装規模
大規模か小規模かによってアーキテクチャでどれくらい固めて縛るのかを考えて使っていきたい。
まとめ
- アーキテクチャをどれほど詰めるのかは用件によって最適解を考えていきたい
- Repositoryを採用してもView側でEloquentModelを利用していたら結局Modelに依存してしまう
一週間laravel触り学習しましたが、いろいろな機能があって慣れれば爆速で開発できそう。
個人的にfeature testの書きやすさが推し。
参考文献
laravel + dddとかでぐぐると解決策がいくつか提示されてそうなので調査を続けたい。
Discussion