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

CakePHPで学ぶDIコンテナ / Learn a DI Container through CakePHP

itosho
December 12, 2020

CakePHPで学ぶDIコンテナ / Learn a DI Container through CakePHP

PHPカンファレンス2020の登壇資料です。

itosho

December 12, 2020
Tweet

More Decks by itosho

Other Decks in Programming

Transcript

  1. CakePHPで学ぶDIコンテナ
    PHPカンファレンス2020 @itosho

    View full-size slide

  2. こんにちは!

    View full-size slide

  3. Discordみてるので、盛り上げてください!

    View full-size slide

  4. どんな25分になるか?
    This session’s goal

    View full-size slide

  5. 今日話すこと
    ・DIとDIコンテナについての概要
    ・CakePHPに新しく導入されるDIコンテナの使い方
    ・DIコンテナがCakePHPに導入される意味

    View full-size slide

  6. 今日話さないこと
    ・DI関連の突っ込んだ話
     ・例えば、Autowiringやサービスロケーターパターンとの比較は話しません
    ・CakePHPのDIコンテナの実装の詳細
     ・今回は裏側ではなく、使い方にフォーカスします
    ※ちょっと聴きたい発表と違うな…と思った方はTrack2の「今こそ理解する、PHPの日時計算」がおすすめです!
    (弊社の同僚が登壇しているので宣伝)

    View full-size slide

  7. 皆さんをこんな気持ちにしたい!
    ・(DIに馴染みがない人)DIやDIコンテナを使ってみよう!
    ・(CakePHP使っている人)CakePHPでもDIコンテナを使ってみよう!
    ・普段使っているフレームワークの今後について考えてみよう!

    View full-size slide

  8. 自己紹介
    ・伊藤 翔 @itoho
     ・コネヒト株式会社 執行役員兼CTO
    ・Backend Engineer / CakePHP Contributor
     ・エンジニアキャリア(12年): 金融系SIer->Web系受託->CGMサービス->コネヒト(コミュニティサービス)
     ・FW遍歴: 独自のFW->Ruby on Rails->CakePHP->echo
    ・バイアスがあると思うので、切り口の一つとして聞いてください
     ・議論のきっかけになればいいなと思っています!

    View full-size slide

  9. DIとDIコンテナを知る
    What’s a DI and a DI Container?

    View full-size slide

  10. そもそも、DIとは?
    ・DI = 「Dependency Injection」の略
    ・日本語で言うと「依存性の注入」
    “依存性の注入とは、コンポーネント間の依存関係をプログラムのソースコードから排除するために、外部の設定ファ
    イルなどでオブジェクトを注入できるようにするソフトウェアパターンである。”(Wikipediaから引用)

    View full-size slide

  11. そもそも、DIとは?
    ・DI = 「Dependency Injection」の略
    ・日本語で言うと「依存性の注入」
    “依存性の注入とは、コンポーネント間の依存関係をプログラムのソースコードから排除するために、外部の設定ファ
    イルなどでオブジェクトを注入できるようにするソフトウェアパターンである。”(Wikipediaから引用)
    なるほど、分からん

    View full-size slide

  12. DIの歴史を知る
    ・DIという言葉自体はマーティン・ファウラー氏が作成(2004年頃)
    ・似た概念として「Inversion of Control」(制御の反転)が存在
     ・Ioc自体は1994年頃、ロバート・C. マーチン氏(ボブおじさん)が提唱
    “制御の反転とは、なんらかの種類のプログラムにおいて、プロシージャを「呼び出す側」と「呼び出される側」が、
    従来のプログラムとは逆になるようにする、ということである。”(Wikipediaから引用)

    View full-size slide

  13. DIの歴史を知る
    ・DIという言葉自体はマーティン・ファウラー氏が作成(2004年頃)
    ・似た概念として「Inversion of Control」(制御の反転)が存在
     ・Ioc自体は1994年頃、ロバート・C. マーチン氏(ボブおじさん)が提唱
    “制御の反転とは、なんらかの種類のプログラムにおいて、プロシージャを「呼び出す側」と「呼び出される側」が、
    従来のプログラムとは逆になるようにする、ということである。”(Wikipediaから引用)
    コードで話そう

    View full-size slide

  14. 用語の整理
    ・サービス: 特定の機能を提供するオブジェクト / 使われる(依存される)側
     ・例: AWS SESを使ったメール送信機能を持つクラス、SendGridを使ったメール送信機能を持つクラスなど
    ・クライアント: サービスを利用するオブジェクト / 使う(依存する)側
     ・例: 上述のメール送信機能を利用するコントローラークラスなど
    ※以降のスライドで登場するサンプルコードの置き場所: https://github.com/itosho/x-cakephp-di-container
    (スライド内では重要な部分のみを抜粋しています)

    View full-size slide

  15. ■サービスのコード

    View full-size slide

  16. ■DIじゃないコード

    View full-size slide

  17. 問題点
    ・一言で言うと、クライアントとサービスが密結合になっている
    ・クライアントのテスト時にSESが必要になる(実際に送信されてしまう)
    ・SESからSendGridへ変更する場合、クライアントの修正が必須

    View full-size slide

  18. 問題点
    ・一言で言うと、クライアントとサービスが密結合になっている
    ・クライアントのテスト時にSESが必要になる(実際に送信されてしまう)
    ・SESからSendGridへ変更する場合、クライアントの修正が必須
    そこで登場するのがDI

    View full-size slide

  19. ■DIなコード(具体に依存)

    View full-size slide

  20. DIの特徴
    ・オブジェクトの生成と利用の分離
     ・これにより、クライアントの修正なしにSESの送信先を変更することが出来る
    ・制御の反転
     ・❌クライアントがサービスを呼ぶ
     ・⭕サービスが外部からクライアントに注入
     ・今回の注入方法は「コンストラクターインジェクション」
    ・クライアントが具体のサービスに依存していることには変わりがない

    View full-size slide

  21. ■サービスのコード(インタフェースあり)

    View full-size slide

  22. ■DIなコード(抽象に依存)

    View full-size slide

  23. 実装ではなく抽象に依存させる
    ・一言で言うと、クライアントとサービスが疎結合になっている
    ・モックを利用することができ、クライアントのテストが容易になる
    ・SESからSendGridへ変更してもクライアントの修正は不要
     ・実際にクライアントの修正が全く必要ないケースは稀だが、影響範囲は相対的に軽微になるはず

    View full-size slide

  24. DIの課題
    ・注入するオブジェクトが増えると…?
    ・オブジェクトの依存関係が複雑になると…?
    ・オブジェクトを生成するコードの管理が大変なことに!

    View full-size slide

  25. DIの課題
    ・注入するオブジェクトが増えると…?
    ・オブジェクトの依存関係が複雑になると…?
    ・オブジェクトを生成するコードの管理が大変なことに!
    そこで登場するのがDIコンテナ

    View full-size slide

  26. DIコンテナ
    ・アプリケーションにDI機能を提供する仕組み
    ・オブジェクトの生成を一手に引き受ける
    ・PHPでの活用 / 実装例: PSR-11, Pimple, league/container, PHP-DIなど

    View full-size slide

  27. ■DIコンテナ(league/container)を用いたコード

    View full-size slide

  28. ここまでのまとめ
    ・DIはソフトウェアを密結合から疎結合にする手法
     ・外部からオブジェクトを注入することでモジュール間の依存関係を薄くする
     ・具体の実装ではなく、抽象に依存させるのがポイント
    ・DIコンテナはDI対象となるオブジェクトの管理を一箇所にまとめた箱

    View full-size slide

  29. CakePHPのDIコンテナを試す
    Try a DI Container on CakePHP

    View full-size slide

  30. CakePHPとDIコンテナ
    ・CakePHPはこれまでDIコンテナとは距離を取っていた(と思う)
     ・下記はDIコンテナについてのIssueの冒頭: https://github.com/cakephp/cakephp/issues/14865

    View full-size slide

  31. CakePHPにおける依存関係管理の歴史
    ・Controllerなどに外部からオブジェクトを注入する場合、サービスロケー
    ター的な手法を採用してきた
     ・サービスロケーターと言い切っていいかは自信がない…(つぶやき)
    ・CakePHP2系: ClassRegistryというグローバルなレジストリを使用
    ・CakePHP3系: 局所的なレジストリを作る方針に変更
     ・Componentに対してはComponentRegistry、Behaviorに対してはBehaviorRegistryなど

    View full-size slide

  32. ■これまでのCakePHPの依存管理

    View full-size slide

  33. CakePHPにDIコンテナがやって来た!
    ・4.2系からDIコンテナが導入される!
     ・2020/12/11時点でRC1版がリリース
     ・ちなみにコンストラクターインジェクションではなく、メソッドインジェクションが採用された
    ・ライブラリとしては「league/container」を利用
     ・PSR-11に準拠していれば、ライブラリは差し替えることが出来そう
    ・「EntryPoint」(Controller, Command)のみDIすることが出来る
     ・View, Helper, Table, Mailer, Behaviorは出来ない(アプリケーション層から遠くDIする難易度が高いため)
     ・DIコンテナの持つ自由度とCakePHPの持つ制約を両立させた?

    View full-size slide

  34. CakePHPにDIコンテナがやって来た!
    ・4.2系からDIコンテナが導入される!
     ・2020/12/11時点でRC1版がリリース
     ・ちなみにコンストラクターインジェクションではなく、メソッドインジェクションが採用された
    ・ライブラリとしては「league/container」を利用
     ・PSR-11に準拠していれば、ライブラリは差し替えることが出来そう
    ・「EntryPoint」(Controller, Command)のみDIすることが出来る
     ・View, Helper, Table, Mailer, Behaviorは出来ない(アプリケーション層から遠くDIする難易度が高いため)
     ・DIコンテナの持つ自由度とCakePHPの持つ制約を両立させた?
    実際に試してみよう!

    View full-size slide

  35. ■DIコンテナを利用したCakePHPの依存管理(サービス)

    View full-size slide

  36. ■DIコンテナを使用したCakePHPの依存管理(DIコンテナ)

    View full-size slide

  37. ■DIコンテナを使用したCakePHPの依存管理(コントローラー)

    View full-size slide

  38. ここまでのまとめ
    ・CakePHPはこれまでサービスロケーター的な手法のみを採用してきた
    ・4.2系からDIコンテナを導入!
    ・DIコンテナ自体は比較的簡単に取り入れることが出来る
     ・サービスクラスを含めた設計の難しさは当然存在する

    View full-size slide

  39. DIコンテナが導入される意味を考える
    Think about adding a DI Container

    View full-size slide

  40. 改めて、CakePHPの特徴
    ・RailsライクなシンプルなMVCフレームワーク
    ・CoC(設定より規約)を重視
     ・Pros: チーム開発において「縛り」が効果的、どの案件でも似た構成でスキルのポータビリティ性が高い
     ・Cons: 「Cake Way」を学ぶイニシャルコスト、「Cake Way」をはみ出すと途端に苦しくなる
    ・「90%の解を目指す」(UNIXの哲学)
     ・密結合で速く走るためのフレームワーク
     ・Laravelのような自由度や柔軟性はない≒Fatなビジネス要件に対処することが相対的に難しい
     ・しかし、(いわゆるWeb系の世界では)シンプルなMVCの構成で十分なことが多い

    View full-size slide

  41. 改めて、CakePHPの特徴
    ・RailsライクなシンプルなMVCフレームワーク
    ・CoC(設定より規約)を重視
     ・Pros: チーム開発において「縛り」が効果的、どの案件でも似た構成でスキルのポータビリティ性が高い
     ・Cons: 「Cake Way」を学ぶイニシャルコスト、「Cake Way」をはみ出すと途端に苦しくなる
    ・「90%の解を目指す」(UNIXの哲学)
     ・密結合で速く走るためのフレームワーク
     ・Laravelのような自由度や柔軟性はない≒Fatなビジネス要件に対処することが相対的に難しい
     ・しかし、(いわゆるWeb系の世界では)シンプルなMVCの構成で十分なことが多い
    本当にそうなのか?

    View full-size slide

  42. CakePHPの歴史と周辺技術の変遷
    CakePHP 1.x~ CakePHP 2.x CakePHP 3.x~
    CakePHP
    4.x~
    2011
    2006 2015 2019
    PHP 7.x~
    PHP
    8.x~
    PHP 5.3.x~
    PHP ~5.3.x
    Web 2.0
    PHP
    ~5.0
    2004
    Microservices
    Ajax
    Laravel
    Hack
    BFF
    GraphQL
    スマートフォンアプリ
    jQuery
    アフターデジタル
    X-Tech
    Composer
    SoR / SoE
    C10K
    PHP-FIG
    HTML5
    Zend Framework
    Xdebug 2.0
    PSR-0 PSR-1, 2 PSR-7
    PSR-11
    PSR-15
    React
    REST
    ※時系列は正確ではありません(あくまで流れを掴む程度にご利用ください)
    ※当然ながら、全てを網羅しているわけでもありません(例: クラウド、IoTなど)
    Serverless

    View full-size slide

  43. 時代の流れ
    ・ここ10年ぐらいでソフトウェア開発は高度複雑化している
     ・技術のコモディティ化や抽象化が進み、敷居は下がったが「フルスタック」であることの難易度は上がった
     ・技術そのものの進化とソフトウェアが適用される分野が増えた
    ・ここ数年で「90%の解」が「80%」しか得られなくなってきた感覚がある
     ・この感覚自体は個人の感想ですが、昨今「SOLID」なフレームワークが求められているのは間違いない
    ・その失われた10%を取り戻すのが今回のDIコンテナの導入ではないか?
     ・Issueでも開発者のための機能と明言されている: https://github.com/cakephp/cakephp/issues/14865

    View full-size slide

  44. 今後どうなるのか?
    ・今の仕組み(サービスロケーター的な手法)を置き換えなかった
    ・あくまで実験的な機能としている
    ・CakePHPの思想を優先し、アドオン的な機能に留めた?
    ・アーキテクチャ観点で一定揺り戻しがあると考えた?
     ・Smart UIパターンが再評価される世界: https://onk.hatenablog.jp/entry/2020/11/11/024531

    View full-size slide

  45. 今後どうなるのか?
    ・今の仕組み(サービスロケーター的な手法)を置き換えなかった
    ・あくまで実験的な機能としている
    ・CakePHPの思想を優先し、アドオン的な機能に留めた?
    ・アーキテクチャ観点で一定揺り戻しがあると考えた?
     ・Smart UIパターンが再評価される世界: https://onk.hatenablog.jp/entry/2020/11/11/024531
    分からない/(^o^)\

    View full-size slide

  46. その上で、出来ること
    ・フレームワークを骨の髄まで味わい尽くす!
     ・開発効率を高めるには、フレームワークが持つポテンシャルを120%引き出す必要がある
     ・CakePHPに限った話ではないが、「CoC」系のフレームワークでは特に重要だと思う
    ・まずは、積極的にDIコンテナを使ってみる!
     ・公式がDIコンテナをサポートした意義は少なくない 
     ・恐らく、最初はDIコンテナとComponentの使い分けのプラクティスを整理するところからかな…?
    ・そして、その結果をコミュニティへフィードバックする!

    View full-size slide

  47. その上で、出来ること
    ・フレームワークを骨の髄まで味わい尽くす!
     ・開発効率を高めるには、フレームワークが持つポテンシャルを120%引き出す必要がある
     ・CakePHPに限った話ではないが、「CoC」系のフレームワークでは特に重要だと思う
    ・まずは、積極的にDIコンテナを使ってみる!
     ・公式がDIコンテナをサポートした意義は少なくない 
     ・恐らく、最初はDIコンテナとComponentの使い分けのプラクティスを整理するところからかな…?
    ・そして、その結果をコミュニティへフィードバックする!
     ・未来を予測する最善の方法は、それを発明することだ(by アラン・ケイ氏)
    よりよいソフトウェアを追求する旅路は続く…

    View full-size slide

  48. まとめ
    tl;dr

    View full-size slide

  49. 今北産業
    DIとDIコンテナについての概要
    ・DIはソフトウェアを密結合から疎結合にする手法
    ・DIコンテナはDI対象となるオブジェクトの管理を一箇所にまとめた箱
    CakePHPに新しく導入されるDIコンテナの使い方
    ・CakePHP4.2系から実験的にDIコンテナを導入!
    ・DIコンテナ自体は比較的簡単に取り入れることが出来る
    DIコンテナがCakePHPに導入される意味
    ・変化する時代の中で「失われた10%の解」を取り戻すための打ち手の一つ(なのでは?)
    ・進化を遂げたCakePHPの今後に期待!1エンジニアとしてもその進化に貢献していきたい!

    View full-size slide

  50. 参考資料1/2
    【DI / DIコンテナの理解を深めるために参考にさせていただいたみなさん】
    ・Inversion of ControlコンテナとDependency Injectionパターン: https://kakutani.com/trans/fowler/injection.html
    ・Google/Guice(DIコンテナ)のモチベーション: https://github.com/google/guice/wiki/Motivation
    ・History of Dependency Injection (DI): https://yauritux.wordpress.com/2011/04/03/history-of-dependency-injection-di/
    ・何故DIコンテナが必要なのか: https://qiita.com/kabosu3d/items/200d14c68b8c0e5b2092
    ・IoCとService LocatorとDIの関係: https://yotiky.hatenablog.com/entry/2018/09/28/IoCとService_LocatorとDIの関係
    ・やはりあなた方のDependency Injectionはまちがっている。
     http://blog.a-way-out.net/blog/2015/08/31/your-dependency-injection-is-wrong-as-I-expected/
    【アーキテクチャの変遷の理解を深めるために参考にさせていただいたみなさん】
    ・Smart UI パターンが再評価される世界: https://onk.hatenablog.jp/entry/2020/11/11/024531
    ・JetBrainsのPHP25周年インフォグラフィック: https://www.jetbrains.com/ja-jp/lp/php-25/

    View full-size slide

  51. 参考資料2/2
    【CakePHPの理解を深めるために参考にさせていただいたみなさん】
    ・CakePHPにDIコンテナが入った(る)と聞いて見学に行ってきました: https://daisuki.nichiyoubi.land/entry/cakephp-feature-di
    ・PSR-11対応のDIコンテナをCakePHP3で使う: https://nextat.co.jp/staff/archives/234
    【CakePHP公式情報のみなさん】
    ・DIコンテナについてのIssue: https://github.com/cakephp/cakephp/issues/14865
    ・DIの使い方をまとめたドキュメント: https://book.cakephp.org/4.next/en/development/dependency-injection.html
    ・Lead DeveloperであるMark Story氏の発表資料: https://www.slideshare.net/markstory/dependency-injection-in-cakephp

    View full-size slide

  52. おまけ
    Additional Time

    View full-size slide

  53. 最後に宣伝です!

    View full-size slide

  54. 与太話
    ・尻切れトンボを防ぐために、宣伝を本編の外部から注入しました
    ・これを登壇における「制御の反転」と言います(言いません)

    View full-size slide

  55. 会社紹介
    ・「あなたの家族像が実現できる社会をつくる」というビジョンを掲げ、
     ママの3人に1人(※)
    が利用する「ママリ」などを運営しています。
     ・12月1日にロゴを含めた会社のリブランディングを発表しました!
    ※:「ママリ」で2019年内に出産予定と設定したユーザー数と、厚生労働省発表「人口動態統計」の出生数から算出。

    View full-size slide

  56. エンジニア向けのミートアップイベントやります!
    ・12/17(木)19:30〜21:00
     ・https://connehito.connpass.com/event/197332/
    ・サービス開発の悩みをぶっちゃける会
     ・例: ぶっちゃけ上手くいかなかった施策は?
     ・オンライン開催ですが、みんなでわいわい話す場になります!
    ・サービス開発に興味があれば誰でもOK!
     ・もちろん、コネヒトに興味がある人でもOK!
     ・先日公開した「Connehito Tech Vision」についても話します
     ・https://connehito.com/recruit/tech/

    View full-size slide

  57. ご清聴ありがとうございました!

    View full-size slide