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

改めて学ぶ Trait の使い方 / phpcon odawara 2025

meihei
April 12, 2025

改めて学ぶ Trait の使い方 / phpcon odawara 2025

meihei

April 12, 2025
Tweet

More Decks by meihei

Other Decks in Technology

Transcript

  1. © 2012-2025 BASE, Inc. 1 #phpcon_odawara #boko 改めて学ぶ Trait の使い方

    PHPカンファレンス小田原2025(2025/04/12)
  2. © 2012-2025 BASE, Inc. 2 #phpcon_odawara #boko 自己紹介 meihei |

    Yohei Ema BASE株式会社 BASE / Product Dev / Feature Dev 1 X: @app1e_s mixi2: @meihei2 GitHub: @meihei3
  3. キーノートセッション 🍥かま 10:20ー Saki Takamachi 改めて学ぶ Trait の使い方 🍥ぼこ 11:00ー meihei 新しいPHP拡張モジュールインストール方法

    「PHP Installer for Extensions (PIE)」 を使ってみよう! 🍥あじ 11:00ー 02 New RelicのAPMを活用した ECサービスにおけるメール遅延解消の舞台裏 🍥かま 15:10ー Futoshi Endo BASEで活躍するメンバーの登壇予定 スポンサーセッション 川口 将貴 🍥かま 11:55ー
  4. © 2012-2025 BASE, Inc. 5 #phpcon_odawara #boko • トレイトの使い所を見極められるようにする •

    よりトレイトを使いこなすヒントを知る Non goal • 明日からトレイトを使いたい!と思わせる事 このトークのゴール ※ それと、プロポーザルに書いていた「実務のコードで合った良い・悪い使われ方」は時間に収まらなかったので Ask the speaker とかで話しましょう 🙇
  5. © 2012-2025 BASE, Inc. 6 #phpcon_odawara #boko アジェンダ トレイトについて知ろう OSS

    ライブラリでの使われ方 トレイトのテストの書き方 1 2 3
  6. © 2012-2025 BASE, Inc. 7 #phpcon_odawara #boko アジェンダ トレイトについて知ろう OSS

    ライブラリでの使われ方 トレイトのテストの書き方 1 2 3
  7. © 2012-2025 BASE, Inc. 8 #phpcon_odawara #boko ざっくり説明 • コードを再利用するため仕組み

    • クラスに似て、メソッドやプロパティが書ける • 優先順位は現在のクラス → トレイト → 継承元のクラス となる ◦ デフォルト実装を容易する目的で利用される trait Hello { public function sayHello() { echo 'Hello '; } } class HelloWorld { use Hello; public function sayHello() { parent::sayHello(); echo 'World!'; } }
  8. © 2012-2025 BASE, Inc. 9 #phpcon_odawara #boko もっと詳しい話は • PHP

    Conference Japan 2022 での sji さんの発表 • トレイト自体の来歴、性質、使いどこ ろについてより詳しく学べます https://www.slideshare.net/slideshow/10-php-trait/253165328
  9. © 2012-2025 BASE, Inc. 10 © 2012-2025 BASE, Inc. 10

    ” その前に前提として DI(合成)で済むならそっちの ほうがいい [出典] 五十嵐進士 「導入から 10 年、PHP の trait は滅びるべきなのか ーーその適切な使いどころと弱点、将来について」P51 https://www.slideshare.net/slideshow/10-php-trait/253165328
  10. © 2012-2025 BASE, Inc. 13 #phpcon_odawara #boko 現実からその例を見つける • 釣り竿としての契約:仕掛けを少し離れ

    たポイントに投げ入れることが出来る • 投げ竿としての契約:糸を伸ばしたり巻 いたりして、より遠くまで仕掛けを投げ 入れることが出来る endo(@Fendo181)さんが撮影してくれました
  11. © 2012-2025 BASE, Inc. 14 #phpcon_odawara #boko 現実からその例を見つける • 釣り竿としての契約:仕掛けを少し離れ

    たポイントに投げ入れることが出来る • 投げ竿としての契約:糸を伸ばしたり巻 いたりして、より遠くまで仕掛けを投げ 入れることが出来る
  12. © 2012-2025 BASE, Inc. 17 #phpcon_odawara #boko DI(依存性注入)を見つける • 投げ竿としての契約:糸を伸ばしたり巻

    いたりして、より遠くまで仕掛けを投げ 入れることが出来る • リールオブジェクトを合成することで、 この釣り竿は投げ竿オブジェクトとして の振る舞いが出来る • 投げ竿はリールの取り替えが容易
  13. © 2012-2025 BASE, Inc. 18 #phpcon_odawara #boko DI(依存性注入)を見つける • 投げ竿としての契約:糸を伸ばしたり巻

    いたりして、より遠くまで仕掛けを投げ 入れることが出来る • リールオブジェクトを合成することで、 この釣り竿は投げ竿オブジェクトとして の振る舞いが出来る • 投げ竿はリールの取り替えが容易
  14. © 2012-2025 BASE, Inc. 19 #phpcon_odawara #boko トレイトを見つける • トレイトは釣り竿オブジェクトを作る

    部品の一部(契約はない) • 別のオブジェクトでも共通して使うこと がある • この部品は簡単に取り替えることができ ない(困難)
  15. © 2012-2025 BASE, Inc. 20 #phpcon_odawara #boko トレイトを見つける • トレイトは釣り竿オブジェクトを作る

    部品の一部(契約はない) • 別のオブジェクトでも共通して使うこと がある • この部品は簡単に取り替えることができ ない(困難)
  16. © 2012-2025 BASE, Inc. 21 #phpcon_odawara #boko DI とトレイトの違いをまとめると トレイト

    • クラスに「便利な振る舞い」を静的に くっつける • 再利用には便利だが、柔軟性に欠け、 依存が見えにくい • テストや差し替えが難しくなる DI(依存性注入) • オブジェクトの振る舞いを外部から与 える • 依存を明示できるため、差し替え・テ ストがしやすい
  17. © 2012-2025 BASE, Inc. 22 #phpcon_odawara #boko • クラスに役割ではなく振る舞いを一時的に貸したいとき ◦

    「このオブジェクトが何かを担う」よりも「何かできるようにする」 ◦ Notifiable, EventStorable など • 複数のクラスに横断的に補助的な機能を提供したいとき ◦ ドメインロジックの中心ではない部分の共通化 ◦ DTO の toArray() など • Interfaceのデフォルト実装を提供したいとき ◦ 最も王道のパターン ◦ 「責務はインターフェースに定義」「振る舞いはトレイトで補助」 トレイトの使い所
  18. © 2012-2025 BASE, Inc. 23 © 2012-2025 BASE, Inc. 23

    逆にトレイトの使い所以外で トレイトを使うと、悪い方に進む なので、ここぞという時以外は使わない。
  19. © 2012-2025 BASE, Inc. 24 #phpcon_odawara #boko アジェンダ トレイトについて知ろう OSS

    ライブラリでの使われ方 トレイトのテストの書き方 1 2 3
  20. © 2012-2025 BASE, Inc. 25 #phpcon_odawara #boko 多分前半の話が長いので記事を紹介 • OSS

    ライブラリを調べてまとめた記事 • 時間的にこの発表では喋れない部分を 紹介しています • 実際に我々が書くコードでは3つの使 い方と3つのテストパターンになる https://zenn.dev/meihei/articles/0191f119-65f9-7bb5-ad43-c35d120b8425
  21. © 2012-2025 BASE, Inc. 26 #phpcon_odawara #boko • インターフェースのデフォルト実装 ◦

    aws/aws-sdk-php の S3ClientTrait ◦ guzzle/psr7 の MessageTrait • クラスの分割実装 ◦ briannesbitt/Carbon の Comparison や Rounding • 偶然同じ機能を持つクラスの実装の共通化 ◦ laravel/framework の Macroable OSS ライブラリで使われているトレイト
  22. © 2012-2025 BASE, Inc. 27 #phpcon_odawara #boko • クラスに役割ではなく振る舞いを一時的に貸したいとき ◦

    偶然同じ機能を持つクラスの実装の共通化 • 複数のクラスに横断的に補助的な機能を提供したいとき ◦ 偶然同じ機能を持つクラスの実装の共通化 • Interfaceのデフォルト実装を提供したいとき ◦ そのままインターフェースのデフォルト実装 トレイトの使い所と使い方
  23. © 2012-2025 BASE, Inc. 28 #phpcon_odawara #boko • クラスに役割ではなく振る舞いを一時的に貸したいとき ◦

    偶然同じ機能を持つクラスの実装の共通化 • 複数のクラスに横断的に補助的な機能を提供したいとき ◦ 偶然同じ機能を持つクラスの実装の共通化 • Interfaceのデフォルト実装を提供したいとき ◦ そのままインターフェースのデフォルト実装 トレイトの使い所と使い方 ライブラリの提供 する側でよく見る
  24. © 2012-2025 BASE, Inc. 29 #phpcon_odawara #boko アジェンダ トレイトについて知ろう OSS

    ライブラリでの使われ方 トレイトのテストの書き方 1 2 3
  25. © 2012-2025 BASE, Inc. 30 #phpcon_odawara #boko • トレイトを use

    したクラスをそのままテストする • テスト専用のクラスを作成してテストする • 無名クラスを作成してテストする トレイトのテストの書き方(オススメ)
  26. © 2012-2025 BASE, Inc. 31 #phpcon_odawara #boko • テストの対象をクラスやインターフェー ス単位で見ている

    • テストからはトレイトの存在を知ること はない ◦ 実装の詳細に依存しないテストが書ける • 参考実装 ◦ guzzle/psr7, aws/aws-sdk-php トレイトを use したクラスをそのままテストする
  27. © 2012-2025 BASE, Inc. 32 #phpcon_odawara #boko • テストの対象をトレイト単位で見ている ◦

    実装の詳細にも関心がある • 定義したテスト専用クラスに名前をつけ たい場合に有効 • 参考実装 ◦ laravel/framework テスト専用のクラスを作成してテストする
  28. © 2012-2025 BASE, Inc. 33 #phpcon_odawara #boko • テストの対象をトレイト単位で見ている ◦

    テスト専用のクラスを作成してテストする 場合と同じ • 定義したテスト専用クラスに名前をつけ たく無い場合に有効 • 参考実装 ◦ symfony/symfony, googleapis/google-auth-library-php 無名クラスを作成してテストする
  29. © 2012-2025 BASE, Inc. 34 #phpcon_odawara #boko • テストコードからトレイトを use

    する ◦ トレイトの振る舞いをテストコードが持つことになり、テストクラスの責任が不明確になる • TestCase::getMockForTrait, TestCase::getObjectForTrait を使う ◦ PHPUnit12で削除された • トレイトの private / protected メソッドをテストする ◦ トレイトをクラスの実装の一部と見ると、クラスの private / protected メソッドを テストすることがおかしいとわかる NGなトレイトのテストの書き方
  30. © 2012-2025 BASE, Inc. 35 #phpcon_odawara #boko • トレイトは「便利な振る舞い」を再利用するために使う ◦

    が、ほとんどの場合は DI (依存性注入)がいい • トレイトの使い所としては3つ ◦ クラスに役割ではなく振る舞いを一時的に貸したいとき ◦ 複数のクラスに横断的に補助的な機能を提供したいとき ◦ Interfaceのデフォルト実装を提供したいとき • トレイトのテスト(オススメ)は3つ ◦ トレイトを use したクラスをそのままテストする ◦ テスト専用のクラスを作成してテストする ◦ 無名クラスを作成してテストする まとめ
  31. © 2012-2025 BASE, Inc. 36 © 2012-2025 BASE, Inc. 36

    トレイトか 用法守れば まあ便利 —— meihei 心の一句