Slide 1

Slide 1 text

© 2012-2025 BASE, Inc. 1 #phpcon_odawara #boko 改めて学ぶ Trait の使い方 PHPカンファレンス小田原2025(2025/04/12)

Slide 2

Slide 2 text

© 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

Slide 3

Slide 3 text

キーノートセッション 🍥かま 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ー

Slide 4

Slide 4 text

No content

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

© 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!'; } }

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

© 2012-2025 BASE, Inc. 10 © 2012-2025 BASE, Inc. 10 ” その前に前提として DI(合成)で済むならそっちの ほうがいい [出典] 五十嵐進士 「導入から 10 年、PHP の trait は滅びるべきなのか ーーその適切な使いどころと弱点、将来について」P51 https://www.slideshare.net/slideshow/10-php-trait/253165328

Slide 11

Slide 11 text

© 2012-2025 BASE, Inc. 11 #phpcon_odawara #boko DI(依存性注入)とトレイト の違いを知り 使い分け方を知る

Slide 12

Slide 12 text

© 2012-2025 BASE, Inc. 12 #phpcon_odawara #boko 現実からその例を見つける endo(@Fendo181)さんが撮影してくれました

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

© 2012-2025 BASE, Inc. 15 #phpcon_odawara #boko DI(依存性注入)を見つける

Slide 16

Slide 16 text

© 2012-2025 BASE, Inc. 16 #phpcon_odawara #boko DI(依存性注入)を見つける

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

© 2012-2025 BASE, Inc. 23 © 2012-2025 BASE, Inc. 23 逆にトレイトの使い所以外で トレイトを使うと、悪い方に進む なので、ここぞという時以外は使わない。

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

© 2012-2025 BASE, Inc. 26 #phpcon_odawara #boko ● インターフェースのデフォルト実装 ○ aws/aws-sdk-php の S3ClientTrait ○ guzzle/psr7 の MessageTrait ● クラスの分割実装 ○ briannesbitt/Carbon の Comparison や Rounding ● 偶然同じ機能を持つクラスの実装の共通化 ○ laravel/framework の Macroable OSS ライブラリで使われているトレイト

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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

Slide 30

Slide 30 text

© 2012-2025 BASE, Inc. 30 #phpcon_odawara #boko ● トレイトを use したクラスをそのままテストする ● テスト専用のクラスを作成してテストする ● 無名クラスを作成してテストする トレイトのテストの書き方(オススメ)

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

© 2012-2025 BASE, Inc. 33 #phpcon_odawara #boko ● テストの対象をトレイト単位で見ている ○ テスト専用のクラスを作成してテストする 場合と同じ ● 定義したテスト専用クラスに名前をつけ たく無い場合に有効 ● 参考実装 ○ symfony/symfony, googleapis/google-auth-library-php 無名クラスを作成してテストする

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

© 2012-2025 BASE, Inc. 36 © 2012-2025 BASE, Inc. 36 トレイトか 用法守れば まあ便利 —— meihei 心の一句