Page 1
純粋 vs 副作用
PHPはなぜ難しいのか?
Pure vs. Side Effects: Navigating PHP's Complexities
pixiv Inc.
USAMI Kenta
2025-06-28 #phpcon PHPConference Japan 2025
公開日:
by USAMI Kenta@tadsan
に東京都大田区蒲田の大田区産業プラザ PiOで開催された『PHPカンファレンス2025』でレギュラートーク(25分)として発表しました。
2025-06-28 #phpcon PHPConference Japan 2025
お前誰よ
純粋関数 pure function
副作用 side effect
数学的な関数?
f(x) sin(x)
関数fのxに2を代入する
関数fのxに2を代入する
2に関数fを適用する
f(x)f(0)f(1)f(2)f(3)
2x
f(x)f(0)f(1)f(2)f(3)
2x
いつどこで計算しても結果は同じ!
プログラミングにおける関数
$f = function($x) {return 2 * $x;};
f(x)f(0)f(1)f(2)f(3)
2x
f(x)f(0)f(1)f(2)f(3)
2x
PHP関数
=数学の関数
PHP関数
≠数学の関数
$f = fn($x) => 2 * $x;
echo "f(2) = ", $f(2);echo "sin(0) = ", sin(0);
われわれはvar_dump() も関数と呼んでいる
$f = fn($x) => 2 * $x;
var_dump(["f(2)" => $f(2)]);var_dump(["sin(0)" => sin(0));
計算した結果をどこにも使わない
$f = fn($x) => 2 * $x;
計算資源の無駄!
$f(2);sin(0);
SDGsに反する!
画面に文字を表示する
文字列を生成して
printf("Hello, world!");sprintf("Hello, world!");
捨てている!
画面に文字を表示する(or HTTP出力)
作った文字列は受け取らないと意味ない
何かってなんだよ…
休憩
ユニットテストは好きですか?
好きかはともかくお得なことはいっぱい
テスト対象の関数
function twice(int $n): int {return $n * 2;}
期待値と結果を比較してチェック
function twice(int $n): int {return $n * 2;}
class TwiceFuncTest extends TestCase {function test(): void {$this->assertEquals(4, twice(2));}}
2025-06-28 #phpcon PHPConference Japan 2025
何かってなんだよ…
いつの間にかどこかの何かに影響を及ぼす
あるいは勝手にどこかの何かの影響を受ける
PHPの「関数」には罠がいっぱい!
不規則に副作用を起こすコードは容易に制御不能になる
秩序のないコードが人間に牙を剥く
閑話休題
ドラえもんご存じですか?
『大長編ドラえもん(7) のび太と鉄人兵団』著: 藤子・F・不二雄/藤子プロ1987年2月25日初版第1刷、2011年第86刷Kindle版 p97, p102より引用
みたことのある回路になおしゃいいんだよ!
のび太は技術者の鑑
制御できないものは制御できる部分にブレークダウンする
ヘキサゴナルアーキテクチャ(Hexagonal architecture翻訳)Alistair Cockburn著、tai2訳2015年10月9日公開、2025年6月28日閲覧より引用
クリーンアーキテクチャ(The Clean Architecture翻訳)Robert Martin著、tai2訳2015年10月9日公開、2025年6月28日閲覧より引用
テスト時にシンプルな偽物に差し替えてテストすることができる
制御できないものは制御できる部分にブレークダウンする
「なんたらアーキテクチャ」は構造をわかりやすく図示してくれるが、必須ではない
プログラム上で制御しやすい基本単位
#とは
純粋の反対語は不純(impure)
外部から観測できる影響を与えない
基本的に…
こんな関数は純粋じゃない!
計算した結果をどこにも使わない
$f = fn($x) => 2 * $x;
計算資源の無駄!
$f(2);sin(0);
SDGsに反する!
PHPDoc @pure タグ
「不純な純粋」というTig-HugなOxymoron
純粋じゃなくても戻り値が大事な関数はある
CurlHandler/リソースは外部から観測できない内部状態に依存するので純粋と言いがたい
PHP 8.5に導入される新機能
PHPランタイムがE_WARNINGを発生させてくれる
flock()とDateTimeImmutable::set*()のみ追加
計算した結果をどこにも使わない
$f = fn($x) => 2 * $x;
計算資源の無駄!
$f(2);sin(0);
SDGsに反する!無駄なので除去する
最適化
ではこれを実装すればうまくいくのか?
これは両方純粋なので警告されるべき
純粋な呼び出しなので警告されるべきではない
原因はわかっていて書きかけのPRがある
_人人人人人人人人人_> 僕の怠惰が原因 <‾Y^Y^Y^Y^Y^Y^Y‾
正直、体調不良と若干の燃えつきが重なっていた
PHPStanを理解している人は限られている
ガチでPHPStanを極めてみたい仲間を増やしたい!!!
