LoginSignup
11
11

More than 5 years have passed since last update.

フレームワークのコントローラー(アプリケーション・ページ)でのDIコンテナの利用について

Posted at

勉強し始めで自分のコードをリファクタリングしたり他人のコードから学習したいと思っている今日この頃
ひとまず、手近な自分のコードとにらめっこする

DIコンテナについて

大まかな現状と前提

fuelPHPをつかってる。
コントローラーではbefore()やafter()など元々の便利なメソッドが用意されている。
現状、before()は使うがafter()はほぼ使ってない。

before()では共通のセッションのinit処理とかするけど、
突貫時に共通化できるからといって、いろいろと不作法なことをしてしまうこともある。あとあとイヤになる。

素朴な疑問など

本筋から外れがち。m(_ _)m

MVCにおいてDIをどこで行うか。コントローラがDIコンテナになり得るか。

コントローラからDIを実行するのにDIコンテナを呼び出すってコトだよね。
コントローラをDIコンテナにするとかは違うよね。どうかね。
もし後者だとしたら吾、どこから注入するのか。View?
それはコントローラとは呼ばないかね。
でも、ViewからのインターフェイスでDIする、そういうのもありかもな。
多分そういう概念あるよね。なんていうのかしら。

..コンストラクタより前の時点でDIするのはどうか。
必要なければコンストラクタ以降でよくて、必要になったらそれ以前の処理に繰り上げれば良いのかな。

注入をパターン化できないのか

DIの注入をコンテナをつかうとして、その注入をさらに固めたり拡張したり、、

..依存関係の定義をまとめる処理を固めてbootstrapあたりで呼び出す的な感じかしら。

クラスを分けてたくさん書くの面倒なときってないかしら

まあダメなんだろうけど、横断的関心のままに全部依存させてしまいたい。
依存させない方が良いものを一度に書いてしまいたい。
。。という欲求をある程度みたしつつほどよく分ける感じ無理かしら。
後から分けやすくしつつ、最初は一緒に書いてしまうためのルールみたいな。
状態が破壊的かどうかとか、モジュールが読み込みされているか、
とかその辺が整理されていればなんとかなるかしら。
ちがうか、そもそもの設計時にはもっと考えることあるものな。
いや、それは後回しとかできないかな。

ってか開発ツールが便利になれば良いのにね。
未実装のクラスや未実装のファイルや未実装のメソッドをクラス名指定で記述したら、
キーボードショートカットのタグジャンプ的な処理で指定先に作成や挿入して呼び出し記述に変換してくれるとか。
無名関数を選択してそれを変換して飛ばしたり。
技術的にはできそうね。
まあ、できなくてもクラス名で飛んでから書いて戻ればいいのかもしれないけど。
戻るのはaptnaでできたっけかしら。

いや、やはりそれも面倒だな。変更があったときに呼び出し元を全部連動して変更したいし、
ctags的なものでそういうのできないのかしら。

..このへんどうしていいのかイメージが持ててないな。

fuelPHPでscaffoldで生成されるコントローラはモデルをそのまま呼び出している

この生成のコードをDIコンテナに渡す的な感じにしておくとか。
拡張できるレイヤーをひとつ挟むと良いのではないか。どうだろう。

予測的なモジュール化への対応

ひとまずモジュールにしたりクラスを作らないけど今後同じ処理が実装されるかもというときにどうするか
こういうことは関係しそうな気がするけどわからん
CommonFunc.php,CommonClass.phpとかやっちゃうとつい肥大化してしまい、良くないよなと思う今日この頃

..たぶん、そういうときにもDIコンテナでやっといたらいいんじゃないかと。

DIコンテナの実装について

http://shiro-goma.hatenablog.com/entry/2014/06/30/092136

requireしているconfig_container.phpを見てみましょう。

pimpleの使い方が具体イメージで分かる
factory()を使う場合とシングルトンになる場合がある

http://tanakahisateru.hatenablog.jp/entry/20121212/1355239198

pinocoという独自フレームワークのDIをpimpleと比較して解説。
DIコンテナを使うときの注意点がわかる
単にDIコンテナと呼ばれるものを使うってことがDIなんじゃない。
DIコンテナで単一の依存注入以外のことをしてしまうと差し替えがうまく出来ない。

こういう部分部分のまとまりの良さを、OOP用語で凝集度といいます。一般的に、凝集度が高いほうが、テストも保守もレビューもしやすいです。
こうしちゃうと、たしかに、外から依存性を注入しないといけないので、すぐには動かせないかもしれません。でも、個々の部品から全体へのアクセス権を奪うことで、各実装が好き勝手できないようになります。どのモジュールが何に依存するのかという関係が、いつの間にか誰にも知られずに変わってる、なんて、ちょっとしたホラーですよね。現場ではよくありますが。
それにほら、システムのコンテナを渡してしまうのは、みんな大嫌いな、あのグローバル変数と同じことですよね。いつでもなんでもグローバル変数という、あのプログラムセンスを許せないなら、それと同じ意味のことをやっちゃダメ。
なぜグローバル変数がダメなのかは、いつどこで書き換えられるかわからない、ということ以外に、仕様を変えたいのに誰が使っているかわからない、というのも問題でしょ。スコープが閉じてなくて広すぎ、っていう問題。

なんでDIコンテナを使うのかOOPの考え方を改めて考えられる。

下記の発展系かな。

http://qiita.com/Hiraku/items/48fbdfca4b63c74494e9

http://dev.classmethod.jp/server-side/java/spring-firstcontact/

spring-webmvc: 画面遷移コントローラ
spring-jdbc: データアクセス
spring-security: 認証や権限回り
spring-batch: バッチ処理
適当に4つほど挙げましたが、この他にも、OAuthの実装やソーシャルなサービスとの連携だったり、正直数えきれないほどのコンポーネントがあります。
狭義のSpringであるDIコンテナは、これらのコンポーネントを組み合わせて「統合するためのフレームワーク」という位置づけです。統合と言われても抽象的でさっぱりイメージが沸かないかもしれません。「O/Rマッパ」や「コントローラ」等は目的が具体的で認識しやすい機能ですが、「何をもってして "統合できた" と考えるのか」がとても曖昧です。説明するのも正直難しいです。

コンポーネントの統合についてイメージがわく

http://www.1x1.jp/blog/2014/02/how-to-use-ioc-container-in-laravel.html

bind(), bindShared(), bindIf(), instance(), singleton(), alias(), extend(),,連想配列ライク,,
などlaravelのDIコンテナのバインド方法の多様さが分かる

DI + AOPの実装

http://c4se.hatenablog.com/entry/2014/12/11/013136

PHPで簡単に華麗にDIとAOPをキメる

かなり勉強になりそうなエントリーだけどまだわからん。

http://ethna.jp/old/ethna-community-topic-di_con.html

2005年でも日本でDI+AOPとかされていたっぽい。

http://yusei-game.jp/yusei/yuseiki/PHP100%E8%A1%8C%E3%81%A7DI%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%EF%BC%92

 例によって、自分ではたぶん使わないAOP+DIコンテナライブラリを改良した。インターセプタがデストラクタと変数参照・代入を拾えるように。って必要なのかそれ(笑)

自分のコードを一部切り取ってリファクタリング

test.php

//と思ったけど、pimpleを使ってみるか。。
//でもまあ、コードを書かないと身につかないから書こう。。たぶん。

メモ

単語のイメージがわいてないので、疎結合・密結合の事例をそれぞれまとめたい。
今のわたしは、設計思考というか設計感覚とかが足りない、持っていないんだろうな。

http://d.hatena.ne.jp/noopable/20090412/1239484575

ZFではフロントコントローラーをサービスロケーターとして使っているケースがあります。たとえば名前解決やらルート解決をしていくのに、ルーターやディスパッチャーへのリソースが必要な時、
...
サービスロケータでも当面の間は良好にシステムを組めるわけですが、たとえばサービスロケーターとしてのZend_Controller_Frontは、そこにぶら下がっているクラス群に遠慮して最適化が図れないようになってしまいます。逆にサービスロケーターに依存しているクラスは、同じサービスロケーターを持っているシステムにしか簡単に移植できないという問題をはらみます。

フロントコントローラーでルーティングなど基礎的なものはサービスロケータで実装するとかはありなのか。
まあ、フレームワークにフロントコントローラーをカスタマイズする方式がスタンダードに提供されていないのなら
それ以外で基本的なサービスロケータを自分で決めても良いのかも知れないけど。

やや抽象的なコードで、DIコンテナ、マンセーって感じで書いてしまいましたが、当然DIコンテナについてもアンチパターンが存在します。2005年のこの記事技術トピックス|DIコンテナの本当の使いどころ(2/2) | ウルシステムズ株式会社 | UL Systems, Inc.がよくまとまっていました。
Zend FrameworkでDIコンテナを使うとすると、おそらくinjectorをどう実装するかっていうところで問題になると思います。たとえばActionControllerをDIコンテナでDIしようとすると、Dispatcher実装を変更しなければならないとか、その辺の解決をそこかしこで始めると、エイヤーで結局DIコンテナをシングルトンで解放とか。=>それってわかりにくいサービスロケーターだよね。っていう落ちになりがちです。

DIコンテナとは何かとかどういう実装がDIコンテナかということよりも、どのように使うとどんなメリットがあるのかという具体性を考慮して使いどころを見極めることが重要と考えます。

何処を密にするとかクラス図とかで設計しないと後で困るぞってコトかしら。

11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11