5.2K Views
September 16, 23
スライド概要
PHPカンファレンス沖縄 2023の登壇資料です。
PHP/Laravelをメインにお仕事しています。アプリケーションの設計とか好きです。
PHPのnull + nullはなぜ0にな るのか。PHPにおけるnullの扱 いを理解して仲良くなろう PHPカンファレンス 沖縄 2023年9月16日 tyamahori (ちゃまほり)/玉堀和輝
もくじ • 自己紹介 • 登壇背景 • nullとはなにか • null + nullの挙動 • PHP以外 • PHP • php-srcを読む • PHPの世界でのnullとの付き合い方 • まとめ
自己紹介
tyamahori(ちゃまほり) 本名 玉堀和輝(たまほり かずき) X(旧:Twitter) @tyamahori 生年月日 1989/09/24 出身/在住 千葉県香取市/千葉県船橋市 経歴 Webアプリケーション開発者(PHP/Laravel) 2017/05 ~ 所属 株式会社LITALICO 2022/08 ~ キーワード 設計/DDD/クリーンアーキテクチャ /Laravel/PHP/Docker/OrbStack/Jetbrains/P hpStorm/環境構築
WEB+DB PRESS Vol.135 で執筆しました https://amazon.co.jp/dp/429713571X/
【宣伝】
株式会社LITALICO 読み: りたりこ 由来: 利他(りた)と利己(りこ) • ビジョン「障害のない社会をつくる」 • 事業内容: 障害者福祉サービスに関するもの • エンジニア募集中 • 「技術の力で社会解決」したい方! • ぜひともお話しましょう! 詳細はこちら • HP: https://litalico.co.jp/
登壇背景
仕様の理解不足 • null + null = 0 の挙動を理解していなかった • バグ対応に時間を溶かし、悔しい思いをした • どういう挙動なのかが気になった
そもそもnullってなんだ?
ネット上での定義
トイレットペーパーの例 0より大きい null 0 null
つまり、nullとは? • 「なにもない」や「存在しない」 • 0ではない • 空文字ではない
他言語のnull + nullの挙動は?
Java
Ruby
Python
TypeScript
JavaScript
Go
Perl
比較結果 • null + null はエラーになることが多い • PHPとしてnullの演算はどう扱うのがただしいのかは論点にはなりそう • PHP,JavaScript,Perlの場合は0 Java Error Ruby Error Python Error TypeScript Error JavaScript 0 Go Error Perl 0
PHPのnullを使った四則演算
検証するPHPのバージョン
四則演算(足算、引算、掛算)
四則演算(割算)
nullを利用した比較演算、キャスト
PHPの挙動まとめ • 四則演算ではnullは0になる • null !== 0 • null !== ‘’ • (int)null === 0
php-srcでnull + nullの挙動をみる
php-src環境 リポジトリURL https://github.com/php/php-src ブランチ https://github.com/php/php-src/tree/PHP-8.2.8 PHP version PHP 8.2.8-dev (cli) (built: Aug 20 2023 23:11:51) (NTS DEBUG)
大まかな流れ 処理の起動 スクリプトの解析し、構造体を生成 構造体をもとにOpcode生成 Opcode実行 • php-srcを読んでみよう @tzm_freedomさん • PHPの関数実行とその計測(記事版) - Qiita @sji_chさん
null + null が0に置き換わる https://github.com/php/php-src/blob/PHP-8.2.8/Zend/zend_operators.c#L275
null + null; • nullの構造体とそのコピーがポインタ引数で渡る。 • 第一引数をもとに、型のチェックをし、nullの場合、コピーである第2 引数のデータ構造に対して、0を割り当てる • 後続処理で、0を割り当てたholderを利用する。
array_sum([null])におけるnullの変換 https://github.com/php/php-src/blob/PHP-8.2.8/Zend/zend_operators.c#L192
まとめ
PHPの null + null = 0の由来はどこから? • 歴史的経緯は不明 • メーリングリストやGitHubのissueにはそれらしい情報はに当たらず。。。 • PHPは当時は型が今ほど固くはなかったからか • 暗黙的にnull + nullは0に変換して処理を行うことが当時の思想にあっていた 説? • Perl, awkコマンドの影響を受けた説?
null+nullが0の問題点 • 暗黙的な型変換により、意図しな い処理結果になりうる • nullはどう扱う? • 本当にnull+nullは0で良いのか? • DBや外部APIからデータを持ってき たときnullがあったらどうする? • countするときにnullの数は?含 める含めない? • 平均値を出すときの分母変わる
null + null = 0 と付き合う • 数値を扱う場面でnullがある場合を考慮する • nullは外す、もしくは無視する • 何かしらの数値に置き換える • 例外を投げて処理をやめる • nullがどう変換されるかは、関係者で決める • 共通理解のもと、業務ロジックが組み立てられる。 • 型の相互変換(Type Juggling)の仕様は要チェックや! • https://www.php.net/manual/ja/language.types.type-juggling.php • 整数への変換ルール • `null は、常に0に変換されます。`との記載はある • https://www.php.net/manual/ja/language.types.integer.php#language.type s.integer.casting
あるべき姿について • nullのキャスト周りはエラーになるべき • 暗黙的な変換が行われるとバグの温床 • null と 0 は違う。
おわりに • PHPでは、null + nullは0です! • 仕様です。 • この挙動を理解した上で、PHPと付き合 っていこう! • nullのハンドリングはどうするかは、 関係者で共通認識を持とう! https://twitter.com/tyamahori/status/1685507147889782784
ご清聴ありがとうございました
参考資料 • • • • • • • • • • • • • • • • https://github.com/php/php-src https://github.com/nickdiego/compiledb https://speakerdeck.com/tzmfreedom/php-src-codereading https://3v4l.org/ https://dev.to/ramsey/using-clion-with-php-src-4me0 https://www.jetbrains.com/ja-jp/clion/ https://www.php.net/manual/ja/language.types.null.php https://blog.freedom-man.com/2022 https://blog.hanhans.net/2021/07/06/php-step-debug-clion/ https://www.slideshare.net/do_aki/phpsrc https://zenn.dev/hgsgtk/articles/fb9af8bfc64ec37bce2d https://wa3.i-3-i.info/word13709.html https://amazon.co.jp/dp/429713571X/ PHP の関数実行とその計測(記事版) - Qiita https://tech.respect-pal.jp/php-helloworld https://www.php.net/manual/en/language.types.type-juggling.php