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

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

Ad4c3c738e57a9bbcb800871e81c232d?s=47 itosho
December 12, 2020

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

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

Ad4c3c738e57a9bbcb800871e81c232d?s=128

itosho

December 12, 2020
Tweet

Transcript

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

  2. こんにちは!

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

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

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

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

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

  8. 自己紹介 ・伊藤 翔 @itoho  ・コネヒト株式会社 執行役員兼CTO ・Backend Engineer / CakePHP

    Contributor  ・エンジニアキャリア(12年): 金融系SIer->Web系受託->CGMサービス->コネヒト(コミュニティサービス)  ・FW遍歴: 独自のFW->Ruby on Rails->CakePHP->echo ・バイアスがあると思うので、切り口の一つとして聞いてください  ・議論のきっかけになればいいなと思っています!
  9. DIとDIコンテナを知る What’s a DI and a DI Container?

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

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

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

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

  14. 用語の整理 ・サービス: 特定の機能を提供するオブジェクト / 使われる(依存される)側  ・例: AWS SESを使ったメール送信機能を持つクラス、SendGridを使ったメール送信機能を持つクラスなど ・クライアント: サービスを利用するオブジェクト

    / 使う(依存する)側  ・例: 上述のメール送信機能を利用するコントローラークラスなど ※以降のスライドで登場するサンプルコードの置き場所: https://github.com/itosho/x-cakephp-di-container (スライド内では重要な部分のみを抜粋しています)
  15. ▪サービスのコード

  16. ▪DIじゃないコード

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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の持つ制約を両立させた?
  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の持つ制約を両立させた? 実際に試してみよう!
  35. ▪DIコンテナを利用したCakePHPの依存管理(サービス)

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

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

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

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

  40. 改めて、CakePHPの特徴 ・RailsライクなシンプルなMVCフレームワーク ・CoC(設定より規約)を重視  ・Pros: チーム開発において「縛り」が効果的、どの案件でも似た構成でスキルのポータビリティ性が高い  ・Cons: 「Cake Way」を学ぶイニシャルコスト、「Cake Way」をはみ出すと途端に苦しくなる ・「90%の解を目指す」(UNIXの哲学)

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

     ・密結合で速く走るためのフレームワーク  ・Laravelのような自由度や柔軟性はない≒Fatなビジネス要件に対処することが相対的に難しい  ・しかし、(いわゆるWeb系の世界では)シンプルなMVCの構成で十分なことが多い 本当にそうなのか?
  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
  43. 時代の流れ ・ここ10年ぐらいでソフトウェア開発は高度複雑化している  ・技術のコモディティ化や抽象化が進み、敷居は下がったが「フルスタック」であることの難易度は上がった  ・技術そのものの進化とソフトウェアが適用される分野が増えた ・ここ数年で「90%の解」が「80%」しか得られなくなってきた感覚がある  ・この感覚自体は個人の感想ですが、昨今「SOLID」なフレームワークが求められているのは間違いない ・その失われた10%を取り戻すのが今回のDIコンテナの導入ではないか?  ・Issueでも開発者のための機能と明言されている: https://github.com/cakephp/cakephp/issues/14865

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

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

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

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

    よりよいソフトウェアを追求する旅路は続く…
  48. まとめ tl;dr

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

  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/
  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
  52. おまけ Additional Time

  53. 最後に宣伝です!

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

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

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

    Tech Vision」についても話します  ・https://connehito.com/recruit/tech/
  57. ご清聴ありがとうございました!