SlideShare a Scribd company logo
導入から10 年、PHP のtrait は滅びるべきなのか

その適切な使いどころと弱点、将来について
五十嵐進士/ sji / sj-i / @sji_ch
自己紹介
@sji_ch
SNS 上でのアイコンはGitHub が自動生成した奴
生まれも育ちも仙台
PHP カンファレンス仙台とかやった
ふつうのサラリーマン


株式会社インフィニットループ仙台支社所属
スマホゲーのサーバサイドプログラマ
二歳児の父
かわいい
絵本好き
最近わりと会話が成立する
WEB+DB PRESS の現PHP 連載担当
昨年6 月からWEB+DB PRESS のPHP 連載
だいたいわりと真面目な話をしてる
Agenda
trait とは
trait の性質
trait の使いどころ
trait の将来
その前に
PHP 8.2 に日本人が乱数拡張入れてたよ!
twitter のTL にRFC の話とphpcon の話と両方同時にでてきた
そうだ締め切り駆動でPHP のRFC も投げよう??
よしTrait で定数定義できるようにしたろ!
議論フェーズに目立った反対もない、これは勝つる、投票開始や
ちょ待てよ
ちょ
投票が始まってから吹き上がる反対
なんやかんやあって結局PHP 8.2 への取り込みはされました!
trait とは
trait ってこういうやつ
2012 年リリースのPHP 5.4 で導入
クラスへ追加するメンバーを切り出して定義
プロパティ、メソッド、定数(8.2から)を定義可能
クラスやtrait、Enum からuse
use 先へコピペされたよう振る舞う
直接インスタンスを作れない
複数trait を同時にuse できる
型宣言に使えない


trait T { // トレイトの定義

public string $property = self::class;

public function method(): void {

echo $this->property, PHP_EOL;

}

}

class C {
use T; // トレイトの利用

}
trait の来歴
もともとPHP 専用とかではない
2002 年にNathanael Schärli らがECOOP2002 向けに出した論文で提案
いくつかの言語でアイディアが取り入れられた
https://www.cs.cmu.edu/~aldrich/courses/819/Scha03aTraits.pdf
単一継承と多重継承
単一継承: 一つの親クラスしか持てない
多重継承: 複数の親クラスを持てる
それぞれ別の面倒くささがある
多重継承の反省からtraitが生まれた
ちなみに当初論文の案ではtraitは状態を持たなかった
多重継承は状態の衝突への対応が難しいので、あえて外されてた
プロパティが定義できるのはPHP が独自に入れた変更
元論文ではtrait がabstract で実装クラス側へアクセッサ提供を要求する形を提案
それだとボイラープレートが増えるので辛いとはみんな思ってた
アカデミアのほうでもStateful Traits のような拡張が後追いで提案された
https://link.springer.com/chapter/10.1007/978-3-540-71836-9_4
trait の性質
ソフトウェアの部品が満たすべき性質: 品質について
trait はクラスの部品
クラスはプログラムの部品
プログラムは部品を組み合わせて作る
良いプログラムは良い部品の良い組み合わせ方で作られる
良いといっても基準は色々
合目的性と言い換えるとスッキリ?
良さは品質とも呼ばれる
品質とは
バートランド・メイヤーさんの『オブジェクト指向入門第2
版原則・コンセプト』(訳:酒匂寛さん)は品質とはなんぞ
やで始まる
品質: 外的要因+ 内的要因
外的要因: 性能とか使いやすさとか、ユーザが認識する部分
内的要因: 外的要因の達成に必要な専門家だけが見る部分
達成すべきは目標は外的要因
品質の外的要因
正確さ
頑丈さ
拡張性
再利用性
互換性
効率性
可搬性
使いやすさ
機能性
適時性
そのほか(実証性、統合性、修復性、経済性)
品質要因のトレードオフ
機能を増やそうとしたらお金がかかるとか
バランスをとる必要がある
特に気にする部分
信頼性
正確さ
頑丈さ
モジュール性
拡張性
再利用性
正確さ
仕様で定義されているとおりに仕事を実行するソフトウェア製品の能力
ちゃんと動かないと全部が台無し
仕様を厳密に記述するというのがまず難しい
仕様への合致度を検証する方法も必要
小分けに関心を分離して「この範囲では正しい」という保証を重ねる
テストとか型とかアサーションとか
頑丈さ
異常な条件に対して適切に対応するソフトウェアシステムの能力
仕様に書かれてないからって鼻から悪魔が出ていいわけがない
エラー吐いてさっさと行儀よく終了してくれるほうが嬉しかったり
拡張性
仕様の変更に対するソフトウェア製品の適応のしやすさ
自然のなりゆきでは規模が大きくなるほど修正の影響を見積もりづらくなる
より設計を単純に
より構成する部品それぞれの独立性を高く
再利用性
多数多様なアプリケーションの構築に使うことのできる、ソフトウェア要素の能力
コードが減ると他の品質にコストを使えるようにもなる
5 つの基準、5 つの規則、5 つの原則
『オブジェクト指向入門』の重点はモジュール性(拡張性と再利用性)
モジュール性についての5 * 3 の15 の確認事項
5 つの基準(criteria)
部品の設計手法に求められるもの
分解しやすさ
組み合わせやすさ
分かりやすさ
連続性
保護性
5 つの規則(rule)
5 つの基準から導き出されるもの
部品の良さを保証するために守らねばならないルール
問題領域の直接的な写像であること
少ないインタフェース
小さなインタフェース
明示的なインタフェース
情報隠蔽
5 つの原則(principle)
5 つの基準と5 つの規則から導き出されるもの
ソフトウェア構築にあたって守るべき原則
言語としてのモジュール単位の原則
自己文書化の原則
統一形式の原則
開放/閉鎖の原則
単一責任選択の原則
trait の性質をあてはめてみる
5 つの基準から見るtrait
分解しやすさ: ○
組み合わせやすさ: ○
分かりやすさ: ☓
traitは利用クラスの中でメンバの名前空間を共有
自身の中にスコープの閉じたメンバを持てない
プロパティは名前衝突時に定義がマージ
自身の定義したプロパティを操作するだけで他部品の不変
条件が壊れる可能性がある
連続性: ○
保護性: △


trait HeightModifiable { // 身長操作trait

private int $value;

public function modifyHeight(int $value): void {

$this->value += $value

}

}

trait WeightModifiable { // 体重操作trait

private int $value;

public function modifyWeight(int $value): void {

$this->value += $value

}

}

class C { // わかりづらいことが起きる!

use HeightModifiable, WeightModifiable;

}
5 つの規則から見るtrait
問題領域の直接的な写像: ○
少ないインタフェース: △
小さいインタフェース: ☓
利用クラス内で全てのメンバへのアクセスが全開放
同居する他trait のメンバにも自由にアクセス
明示的なインタフェース: ☓
利用クラス側のprivate メンバへのアクセスさえ断りなく可能
プロパティの名前衝突のマージに問題がある場合も気づけない
情報隠蔽: ☓
trait local なメンバを定義できない
private / protected / public は利用クラス側の可視性としてコピペ展開される
5 つの原則とtrait
5 つの原則とtrait: 言語としてのモジュール単位の原則: ○
部品は使用される言語の構文単位として表されなければならないという原則
trait はまさにそれそのもの
5 つの原則とtrait: 自己文書化の原則: ☓
部品についてのすべての情報を部品の一部として持つようにするという原則
かなりクラスに近い表現力はある
PHP 8.2 からは定数定義もできる
「特定のinterface を実装するために使われるもの」をコメントでしか書けない
信頼性高く書けるクラスより弱い
5 つの原則とtrait: 統一形式アクセスの原則: △
プロパティの値を読み書きする時もメソッドを呼ぶ時も同じ表記を使うという原則
できないが、クラスもできないのでクラスより悪くはない
将来クラスで可能になればtrait でも可能になる
internals でProperty Accessors の議論を進めている人もいる
5 つの原則とtrait: 開放/閉鎖の原則: ☓
既存の部品への修正をせず部品を拡張できるという原則
abstract メソッドでtrait 中心の部品構成でも一応可能
interface 側とtrait 側で同じシグネチャを記述するようなこ
とが起きがち
特定のinterface を実装していることの要求をできるクラス
とくらべるとやや弱い


trait T1 {

abstract public function f1(): void;

public function f2(): void {

f1();

}

}

trait T2 {

use T1;

public function f1(): void { echo 'T2';}

}

trait T3 {

use T1;

public function f1(): void { echo 'T3';}

}
5 つの原則とtrait: 単一責任選択の原則: ☓
選択肢を提供する際、システム内の1 つの部品だけがその選択肢のすべてを把握すべきという原則
言語的にサポートされているとは言い難い
どのtrait を使うかが利用側の各クラスなどへ静的にuse で分散して埋め込まれる
use 先を分岐するような仕組みがtrait にはない
trait の性質まとめ
クラス(の継承)より良いところ
部品を小分けにして組み合わせられる
ただしDI / 合成が同等の能力
クラス(の継承)より悪いところ
意図しない部品間の干渉を防ぐ仕組みが弱い
interface が付けられない
trait の使いどころ
その前に前提として
DI (合成)で済むならそっちのほうがよい
DTO っぽいのにちょっとデータ取得メソッド生やしたいとか
にはDI より向く
他に頼れるやつがいない時に使う最終兵器


// これより

class C1 {

use FunctionalityTrait1;

use FunctionalityTrait2;

}

// クラスのDIにするほうが楽

class C2 {

public function __construct(

private FunctionalityClass1 $functionality1,

private FunctionalityClass2 $functionality2,

) {

}

}
インタフェースのデフォルト実装
リッチインタフェースを利用者が扱いやすい形で採用可能
利用コードへ影響を与えずにインタフェースをあとから拡張
可能
PSR-3 のLoggerAwareInterface とLoggerAwareTrait、
LoggerInterface とLoggerTrait など


interface HogeInterface {

public function method1(): void;

}

trait HogeDefaultImplementation {

public function method1(): void {

echo 'hoge';

}

}

class Hoge implements HogeInterface {

use HogeDefaultImplementation;

}
インタフェースとあわせての実質的な多重継承の実現
trait は型を伴わない実装
interface は実装を伴わない型
2 つあわせて(だいたい)多重継承


// 単一継承だとこういうのを小分けにできない

// traitなら小分けに分割できる

class P {

public function common_function(): void {}

// A、Bにのみ必要な機能がC、Dにも導入

public function ab_function(): void {}

// C、Dにのみ必要な機能がA、Bにも導入

public function cd_function(): void {}

}

class A extends P {}

class B extends P {}

class C extends P {}

class D extends P {}
クラスの分割実装
機械生成コードに手書きのコードを足したい場合などに嬉し
い
直接修正するとスキーマ変更時の再生成で上書きされる
ORM とかIDL からのコード生成とかへデータアクセス用の
処理をちょっと足したいとか


// 機械生成コードをクラス側に置く構成も可

trait MachineGeneratedCodes {

// 中略(機械生成されたコード)

}

// ↓別ファイルで定義

// 手書きコードをトレイト側に置く構成も可

class HandWrittenCodes {

use MachineGeneratedCodes;

// 中略(手書きのコード)

}
類似機能を持つ他言語からのコード移植
Java やKotlin のinterface のメソッドデフォルト実装
C++ やPython の多重継承
Scala やRust のtrait
C# のpartial
偶然同じ機能を持つクラスの実装の共通化
複数のクラスへ同じ機能を与えたい
が、同じ型を与えたいわけではない
Laravel のMacroable など
コードのユーザに複数クラスの統一インタフェースを提供したいだけの時
trait の将来
たぶんなくなることはない
アカンけど捨てるわけにもいかんよね、はtrait 定数のRFC で再確認できた
メンバの可視性を縛る方法とかinterface と紐付ける機能とかほしい
おしまい
- 宣伝- 

WEB+DB PRESS vol.130 のPHP 連載でも

trait の扱いについて書いてます!
このトークと被る部分もありつつ、切り口は違い、文章としてまとめてあります
興味があればぜひ
https://gihyo.jp/magazine/wdpress/archive/2022/vol130

More Related Content

What's hot (20)

PDF
ドメイン駆動設計 本格入門
増田 亨
 
PDF
オブジェクト指向の設計と実装の学び方のコツ
増田 亨
 
PPTX
DevOpsにおけるAnsibleの立ち位置と使い所
Hidetoshi Hirokawa
 
PDF
それはYAGNIか? それとも思考停止か?
Yoshitaka Kawashima
 
PDF
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty
 
PDF
Docker Compose 徹底解説
Masahito Zembutsu
 
PPTX
本当は恐ろしい分散システムの話
Kumazaki Hiroki
 
PDF
View Customize Pluginで出来ること
onozaty
 
PDF
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
Koichiro Matsuoka
 
PDF
入社1年目のプログラミング初心者がSpringを学ぶための手引き
土岐 孝平
 
PDF
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
 
PPTX
マイクロサービスにおける 結果整合性との戦い
ota42y
 
PDF
ドメイン駆動設計のための Spring の上手な使い方
増田 亨
 
PDF
インフラエンジニアの綺麗で優しい手順書の書き方
Shohei Koyama
 
PPTX
BuildKitによる高速でセキュアなイメージビルド
Akihiro Suda
 
PDF
外部キー制約に伴うロックの小話
ichirin2501
 
PDF
ドメイン駆動設計のためのオブジェクト指向入門
増田 亨
 
PDF
ドメイン駆動設計 基本を理解する
増田 亨
 
PDF
こわくない Git
Kota Saito
 
PDF
Redmineをちょっと便利に! プログラミング無しで使ってみるREST API
Go Maeda
 
ドメイン駆動設計 本格入門
増田 亨
 
オブジェクト指向の設計と実装の学び方のコツ
増田 亨
 
DevOpsにおけるAnsibleの立ち位置と使い所
Hidetoshi Hirokawa
 
それはYAGNIか? それとも思考停止か?
Yoshitaka Kawashima
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
onozaty
 
Docker Compose 徹底解説
Masahito Zembutsu
 
本当は恐ろしい分散システムの話
Kumazaki Hiroki
 
View Customize Pluginで出来ること
onozaty
 
ドメイン駆動設計 モデリング_実装入門勉強会_2020.3.8
Koichiro Matsuoka
 
入社1年目のプログラミング初心者がSpringを学ぶための手引き
土岐 孝平
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
Y Watanabe
 
マイクロサービスにおける 結果整合性との戦い
ota42y
 
ドメイン駆動設計のための Spring の上手な使い方
増田 亨
 
インフラエンジニアの綺麗で優しい手順書の書き方
Shohei Koyama
 
BuildKitによる高速でセキュアなイメージビルド
Akihiro Suda
 
外部キー制約に伴うロックの小話
ichirin2501
 
ドメイン駆動設計のためのオブジェクト指向入門
増田 亨
 
ドメイン駆動設計 基本を理解する
増田 亨
 
こわくない Git
Kota Saito
 
Redmineをちょっと便利に! プログラミング無しで使ってみるREST API
Go Maeda
 

Similar to 導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について (6)

PDF
traitを使って楽したい話
infinite_loop
 
PDF
Phpではじめるオブジェクト指向(公開用)
VOYAGE GROUP
 
PDF
Introduce Groovy 2.3 trait
Uehara Junji
 
PDF
Trait in scala
Yuta Shimakawa
 
PDF
Scala勉強会 2015 02_03
Shuya Tsukamoto
 
PDF
Traitsについて
Tetsuji Koyama
 
traitを使って楽したい話
infinite_loop
 
Phpではじめるオブジェクト指向(公開用)
VOYAGE GROUP
 
Introduce Groovy 2.3 trait
Uehara Junji
 
Trait in scala
Yuta Shimakawa
 
Scala勉強会 2015 02_03
Shuya Tsukamoto
 
Traitsについて
Tetsuji Koyama
 
Ad

More from shinjiigarashi (6)

PDF
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
shinjiigarashi
 
PDF
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
shinjiigarashi
 
PDF
PHP でファイルシステムを作ろう
shinjiigarashi
 
PDF
PHP 8 で Web 以外の世界の扉を叩く
shinjiigarashi
 
PDF
PHP で実行中のスクリプトの動作を下から覗き見る
shinjiigarashi
 
PDF
PHPの関数実行とその計測
shinjiigarashi
 
モダン PHP テクニック 12 選 ―PsalmとPHP 8.1で今はこんなこともできる!―
shinjiigarashi
 
PHP 8 と V8 (JavaScript) で速さを見比べてみよう!
shinjiigarashi
 
PHP でファイルシステムを作ろう
shinjiigarashi
 
PHP 8 で Web 以外の世界の扉を叩く
shinjiigarashi
 
PHP で実行中のスクリプトの動作を下から覗き見る
shinjiigarashi
 
PHPの関数実行とその計測
shinjiigarashi
 
Ad

Recently uploaded (10)

PDF
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
PDF
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
PDF
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
PDF
SIG-AUDIO 2025 Vol.02 オンラインセミナー SIG-Audioプレゼン資料_オーディオプラグイン開発_塩澤達矢.pdf
IGDA Japan SIG-Audio
 
PDF
ABC2025S LT講演「世界の窓から Androidこんにちは2025」アプリ自動生成の将来?ロボティクスの夢再び?
嶋 是一 (Yoshikazu SHIMA)
 
PDF
20250630_aws_reinforce_2025_aws_sheild_network_security_director
uedayuki
 
PDF
生成AIパネルトーク(Interop25Tokyo APPS JAPAN M1-07,M2-07 嶋ポジショントーク)
嶋 是一 (Yoshikazu SHIMA)
 
PDF
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
PDF
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 
PDF
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 
[Hardening Designers Confernece 2025]ランサムウェアでの見えざるログ・見えるログ
kataware
 
プライバシ保護のためのインターネットアーキテクチャの進化 (2025-07-11)
Jun Kurihara
 
Hyperledger Fabric最新v3.x系での機能強化、変更点にキャッチアップ!
LFDT Tokyo Meetup
 
SIG-AUDIO 2025 Vol.02 オンラインセミナー SIG-Audioプレゼン資料_オーディオプラグイン開発_塩澤達矢.pdf
IGDA Japan SIG-Audio
 
ABC2025S LT講演「世界の窓から Androidこんにちは2025」アプリ自動生成の将来?ロボティクスの夢再び?
嶋 是一 (Yoshikazu SHIMA)
 
20250630_aws_reinforce_2025_aws_sheild_network_security_director
uedayuki
 
生成AIパネルトーク(Interop25Tokyo APPS JAPAN M1-07,M2-07 嶋ポジショントーク)
嶋 是一 (Yoshikazu SHIMA)
 
20250710_Devinで切り拓くDB革命_〜価値創出に集中せよ〜.pdf
Masaki Yamakawa
 
Hyperledger Fabric公式サンプル fabric-samples徹底解説
LFDT Tokyo Meetup
 
人気ブロックチェーン基盤「Hyperledger Fabric」最新版を動かしてみた!
LFDT Tokyo Meetup
 

導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について