Upgrade to Pro — share decks privately, control downloads, hide ads and more …

DIコンテナを学ぶ

hihats
December 26, 2016

 DIコンテナを学ぶ

PHPフレームワークのLaravelを通して、DIコンテナについて学習します

hihats

December 26, 2016
Tweet

More Decks by hihats

Other Decks in Technology

Transcript

  1. DIコンテナを学ぶ
    Laravelの肝

    View Slide

  2. このDIコンテナ(サービスコンテナ)を学びましょう
    ● LaravelではDIコンテナという仕組みを使用しており、そこで依存性の解決
    を行っています。
    ● リファレンス本の中でサービスコンテナと書いてあるものが、DIコンテナに
    当たります。
    ● コントローラーに依存関係を持たせなくてよくなるため、コントローラーの
    単体テストが容易になったりします。
    ● bootstrap/app.php の中で返される $app がサービスコンテナそのもの
    です。
    Laravelを使い始める前にまず

    View Slide

  3. しかし、まずその前に

    View Slide

  4. DIとは?
    依存性とは?
    コントローラー
    とは?
    MVCとは?
    前提知識も足りていないことが多い
    そもそも、フレームワークを使う上
    での基本からおさらい しときま
    しょう
    処理フローを学ぶためにフレーム
    ワークを使う場合と使わない場合の
    違いから入っていきます

    View Slide

  5. FW使わない場合
    ブラウザで
    http://localhost:8080/get_user.php?uid=3
    public/index.php
    public/get_user.php
    public/login.php
    ・・・・・
    fileひとつで処理が完結するpattern

    View Slide

  6. FW使う場合
    Entrypointが入り口の全てを引き受ける
    public/index.phpがEntrypointに当たる
    (Laravel含め多くのPHPフレームワークで)
    全てのアクセスがindex.phpを呼び出し、リクエスト内容(URL)から各コント
    ローラーに振り分けられる

    View Slide

  7. コンポーネント基礎構造
    ⑤ビジネスロジック
    ④コントローラー
    ③ Router
    ① Request
    ⑥ ビュー
    ⑦ Response
    Laravelも MVC パターンっぽくは見える
    が、Modelがない
    元々はModelsディレクトリが存在してい
    たが、5.1からなくなる
    既存の曖昧な「モデル」という表現を使う
    ことによるの弊害をなくしたかった
    もっと限定された語彙を使用し開発を行えば、明確
    に定義された責任を持つ、より小さくてきれいなクラ
    スへ、アプリケーションを簡単に分割できるでしょう
    by Taylor Otwell

    View Slide

  8. コンポーネント基礎構造
    ⑤ビジネスロジック
    ④コントローラー
    ③ Router
    ① Request
    ⑥ ビュー
    ⑦ Response
    Laravelも MVC パターンっぽくは見える
    が、Modelがない
    元々はModelsディレクトリが存在してい
    たが、5.1からなくなる
    既存の曖昧な「モデル」という表現を使う
    ことによるの弊害をなくしたかった
    ② Middleware
    もっと限定された語彙を使用し開発を行えば、明確
    に定義された責任を持つ、より小さくてきれいなク
    ラスへ、アプリケーションを簡単に分割できるでしょ
    う by Taylor Otwell

    View Slide

  9. つまり

    View Slide

  10. Model(らしきもの)をどう設計、実装するか
    は我々に委ねられている

    View Slide

  11. なので

    View Slide

  12. Modelはいったん置いときましょう
    設計思想や経験に基づき、各ユーザごとに様々なモデリングが行われている
    あまりにも理解のための幅が広く、難易度が高い
    その代わり、コントローラとビューについては、標準で設置されており、役割も定められているので、ここか
    ら理解していくのがよい
    (Laravelにおいては)

    View Slide

  13. Controller の責務
    ・ユーザからの入力を受け取る
    ・ビューを選択、生成する
    この二つだけ
    Sample(製品モデルを扱うコントローラ)
    app/Http/Controllers/ProductController.php をみてみる

    View Slide

  14. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct()
    {
    }
    //一覧
    public function index()
    {
    $id = request()->get(‘id’);
    $product = new Product();
    $products = $product->find($id);
    return view('product.index, array('products' => $products));
    }
    }
    app/Http/Controllers/ProductController.php

    View Slide

  15. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct()
    {
    }
    //一覧
    public function index()
    {
    $id = request()->get(‘id’);
    $product = new Product();
    $products = $product->find($id);
    return view('product.index, array('products' => $products));
    }
    }
    app/Http/Controllers/ProductController.php
    入力を受けとり
    ビューを生成

    View Slide

  16. ここから依存性の話

    View Slide

  17. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct()
    {
    }
    //一覧
    public function index()
    {
    $id = request()->get(‘id’);
    $product = new Product();
    $products = $product->find($id);
    return view('product.index, array('products' => $products));
    }
    }
    app/Http/Controllers/ProductController.php

    View Slide

  18. Object(コントローラー)がObject()に依存し
    ている

    View Slide

  19. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct()
    {
    }
    //一覧
    public function index()
    {
    $id = request()->get(‘id’);
    $product = new Product();
    $products = $product->find($id);
    return view('product.index, array('products' => $products));
    }
    }
    app/Http/Controllers/ProductController.php

    View Slide

  20. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct()
    {
    }
    //一覧
    public function index()
    {
    $id = request()->get(‘id’);
    $product = new Product(‘has_option’);
    $products = $product->find($id);
    return view('product.index, array('products' => $products));
    }
    }
    app/Http/Controllers/ProductController.php

    View Slide

  21. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct()
    {
    }
    //一覧
    public function index(Product $product)
    {
    $id = request()->get(‘id’);
    $products = $product->find($id);
    return view('product.index, compact('products'));
    }
    }
    $product = new Product();
    $product = new Product(‘has_option’);
    app/Http/Controllers/ProductController.php
    どちらも使える

    View Slide

  22. 依存されているObjectを外から引数で渡すことを
    「依存性の注入(Dependency Injection)」という

    View Slide

  23. これがDI(パターン)

    View Slide

  24. ちなみにLaravelでは、外でnewしなくても、タイプヒン
    ティングで勝手にインスタンス生成してくれる(条件
    つき)

    View Slide

  25. 結合を緩くする(疎結合)

    View Slide

  26. /**
    * Productインターフェースとそれを実装したクラスを1ファイルにまとめたもの
    */
    interface ProductInterface
    {
    public function __construct()
    {
    }
    }
    class PackageProduct implements ProductInterface
    {
    public function __construct()
    {
    }
    }
    class CloudProduct implements ProductInterface
    {
    public function __construct()
    {
    }
    }
    }
    ProductInterfaceを実装し
    た、具象クラスが二つ

    View Slide

  27. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct()
    {
    }
    //一覧
    public function index(ProductInterface $product)
    {
    $id = request()->get(‘id’);
    $products = $product->find($id);
    return view('product.index, compact('products'));
    }
    }
    抽象に注入せよ
    (OODのDI原則)

    View Slide

  28. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct(Product $product)
    {
    $this->product = $product;
    }
    //一覧
    public function index()
    {
    $id = request()->get(‘id’);
    $products = $this->product->find($id);
    return view('product.index, compact('products'));
    }
    }
    コンストラクタ
    インジェクション

    View Slide

  29. <?php
    namespace App\Http\Controllers;
    use Product;
    class ProductController extends Controller
    {
    /**
    * ProductController constructor.
    */
    public function __construct(Product $product)
    {
    $this->product = $product;
    $this->request = request();
    }
    //一覧
    public function index()
    {
    $id = $this->request->get(‘id’);
    $products = $this->product->find($id);
    return view('product.index, compact('products'));
    }
    }
    =Request::class

    View Slide

  30. 依存性がどんどん複雑になってくる

    View Slide

  31. 依存を再帰的に解決するなど、複雑な依存関係の
    解決を一手に引き受けてくれるのが

    View Slide

  32. DIコンテナ(サービスコンテナ)

    View Slide

  33. まとめ

    View Slide

  34. ● コントローラーに責務を追わせすぎないようにしましょう
    ● オブジェクト同士の依存性をできるだけ緩くしましょう(疎結合)
    ● 依存関係がソースコードの奥深くに入り込まないように、DIコンテナに解決
    を任せましょう

    View Slide