Laravelのapp()->make()はアンチパターンなのか調べてみました。
結論
フレームワークに依存すると問題のあるドメイン層以外ではapp()->make()を利用してもいい。
調査内容
アプリケーションサービスのメソッド内でapp()->make()を利用していたら、
疎結合を意識してコンストラクタインジェクションを利用するようにコードレビューをもらったことがあったのですが、app()->make()は疎結合だし、コンストラクタからタイプヒンティングでプロパティに持たせるほうがインスタンスの作成時に必ず依存することで循環参照になりやすく結合度は高そうと思ったのでいろいろ調べて見ました。
パターンの種類でいうと
app()->make()はServiceLocaorで、
コンストラクタインジェクションはDIになります。
双方のバターンとも疎結合を基本としている。
という記事や、
そもそもDIは依存性の解決であって、依存が無くなるわけではない。
という記事があったりして正反対な意見があるようですが、ServiceLocaorをDIにすることで、サービスロケータ自体には依存しないようになるようです。
そのため、ServiceLocaorがアンチパターンのような記事をいくつか見かけたのですが、マーティンファウラー先生によるとそれは違うようです。
先生によるとDIよりService Locatorが利用できるのであれば、それを利用するのはもっともだとおっしゃっています。
1 | Service Locator と Dependency Injection とのどちらを採用するかの判断は、 ロケータへの依存性が問題になるかどうかにかかっている。 |
とありましたので、Laravelのフレームワークを利用する上で、フレームワークに依存すると問題のあるドメイン層以外では Service Locatorを採用したほうがよさそうです。
また、同様の意見が「上田勲. プリンシプル オブ プログラミング 3年目までに身につけたい 一生役立つ101の原理原則」にも書かれていました。
1 | 結合先モジュールの質にも着目しましょう。密な結合自体は問題ですが、本質的には、不安定な要素と密に結合するのが問題になります。安定的なライブラリに依存するのは特に問題ではありません。盲目的にデータ結合を目指すというより、相手によって付き合いの深さを判断しましょう。 |
「データ結合」とは、この本の中でもっとも疎結合であるという形です。
フレームワークとして提供されるサービスロケータの質は安定的しているといえるので、盲目的に疎結合を目指してDIを利用するということは良くないようです。
参考url
マーティンファウラー
https://kakutani.com/trans/fowler/injection.html#ServiceLocatorVsDependencyInjection
マーティンファウラーとは反対の意見
http://blog.a-way-out.net/blog/2015/08/31/your-dependency-injection-is-wrong-as-I-expected/