PHPerがこれから「型」とお付き合いしていくために

2564c99f616f1ecfc0f617a6fe87e2a9?s=47 penguin045
February 11, 2020

 PHPerがこれから「型」とお付き合いしていくために

PHPerKaigi 2020登壇資料

2564c99f616f1ecfc0f617a6fe87e2a9?s=128

penguin045

February 11, 2020
Tweet

Transcript

  1. PHPerがこれから「型」と お付き合いしていくために やなせ たかし

  2. 自己紹介 やなせ たかし 株式会社ラクスで働いています。 PHP 歴 1 年未満 Scala 大好きマン

    ギターを嗜みます。ギターと技術で何かしたい ( 願望 ) 2
  3. 今日話すこと • 型システムとは何なのか • 型システムとプログラミング言語 • PHP と型 • 今から型システムとお付き合いを始めるには

    3
  4. 型システムとは何なのか 4

  5. 型システムとは何なのか • 本セッションでの前提 • 定義 • 型システムでできること 5

  6. 型システムとは何なのか • 元は型理論という分野 ◦ コンピューターが存在する前からある ◦ 数学、論理学などで用いられる • ここでは、プログラミングに関することを話します 6

  7. 型システムとは何なのか • プログラムのふるまいを推論するためのツール • 始めは int と float の違いを区別するようなもの ◦

    効率よく計算するため • 1970 年ごろからより高度な概念が研究される ◦ 部分型 ◦ 再帰型 ◦ 多相 ◦ 高階型 ◦ などなど 7
  8. 型システムでできること • エラー検知 • 構造を明らかにする • 安全性を高める • プログラムの効率性を高める 8

  9. • データ構造の不整合を検知してくれる ◦ しかも実行前にわかる • 特定のバグがないことを保証できる ◦ 静的に型検査をしている場合 エラー検知 9

  10. • データ構造の不整合を許容しない ◦ 柔軟性を持たせるのには工夫が必要 ◦ とはいえ、全てを汎用的な型で実装すると恩恵が受けられない • 特定のバグがないことを保証しなければならない ◦ 絶対に実行されないコードのエラーも検知してしまう

    エラー検知(裏の顔) 10
  11. 構造を明らかにする • 利用側と実装を分離できる ◦ インターフェイスを型として扱うことで、利用する型を保証できる • ドキュメント化しやすい ◦ シグネチャーの型が正しいことは保証されている 11

  12. 安全性を高める • 自身が抽象化した操作を保護できる ◦ 型検査の時点で不整合があるとエラーになる ◦ たとえば、配列を使っているだけではメモリ破壊を起こさない 12

  13. 安全性を高める(裏の顔) • 多くの言語では、抜け道が存在する ◦ たとえば、メモリ操作 API があるとか ◦ 低レベル API

    はそういうのがありがち • 「安全」の定義がまちまち ◦ 型安全? ◦ メモリ安全? 13
  14. プログラムの効率性を高める • 実行時に効率的なバイトコードを生成する ◦ 静的型付き言語をコンパイルする ◦ 低レベルで最適化できるので効率が良くなる ◦ 動的型付き言語でも、 JIT

    をで型情報を集めてコンパイルしていることも 14
  15. 型システムがもたらすもの • 安全性と ( 実行時の ) 効率 • ただし、柔軟性とはトレードオフになりがち 15

  16. 型システムとプログラミング言語 16

  17. 型システムとプログラミング言語 17 • 静的型付け・動的型付けとは • 静的型付き言語 • 動的型付き言語 • 両者を比較してみる

  18. 静的型付け・動的型付けとは 型検査がいつ行われるかの違い • 静的型付けはコンパイル時に型検査が行われている • 動的型付けは実行時に型検査が行われている 18

  19. 静的型付き言語の特徴 • コンパイル時に型が検査されている • コンパイルされたら効率的なバイトコードになる • 型に不整合があるプログラムは実行できない • 型を書く必要がある言語もある ◦

    昔の Java とか • ( 一部 ) 型を書かなくてもいい言語もある ◦ Scala とか • 型を書くのがデメリットというわけではない 19
  20. コンパイルされたらどうなるの • コードが直接低レベルな命令に翻訳されている • 一方インタープリターはコードを解釈しながら実行 型がわかっていれば、翻訳時に最適化が効く。 => 何らかの原因で型検査が入ると効率が悪くなる • キャストやリフレクション

    20
  21. 動的型付き言語の特徴 • 型検査は実行時に行われる • 型の不整合は実行時にエラーとなる(こともある) • 型を書ける言語も増えてきた ◦ PHP も型を書けるようになってきましたね

    21
  22. 両者を比較してみる • 型を書くの?書かないの? • 型推論ってあるけど、動的言語と何が違うの? • 静的解析するから、静的型付き言語は不要では? • 結局どっちがいいの? 22

  23. 型を書くの?書かないの? 静的型付き言語 • 書くし、書かないこともある 動的型付き言語 • 書かないが、書くこともある 23

  24. 型をアノテーションへのモチベーション 静的型付き言語 • 自明なものは書かないでいいようにしていきたい 動的型付き言語 • 安全のために型を書こう 24

  25. 型推論ってあるけど、動的言語と何が違うの? 型推論 • 静的型付き言語で、コンパイラが型を推論する • 実行時は型検査のないただの命令に翻訳されている 動的型付き言語 • 実行時まで型が決まっていない •

    実行時に型検査をする 25
  26. 横道:型推論について • 右辺の型を計算し、左辺の型を推論します • var a = hoge; だけではない def

    map(ls, f) = ls match { case h::t => f(h) :: map(t, f) case Nil => Nil } • 上の疑似コードの型が決まるのが型推論のすごさ 26
  27. 静的解析するから、静的型付き言語は不要では? • 静的型付き言語と比較すると恩恵は限定的 • ある程度の恩恵は受けられる ◦ 静的解析できる範囲では型安全に実装できる ◦ 実行時の恩恵は受けられない =>

    漸進的型付け などと表現される 27
  28. 結局どうなの 優劣はない その場その場の有利不利はある プロダクトのフェーズによっても変わる 文化によっても変化する 多分いつまでも優劣はつかない ただし、超えられない壁はある(双方ともに) 28

  29. PHPと型 29

  30. PHPと型 • どういう言語 • PHP の型 • 漸進的型付けの言語として 30

  31. PHPってどういう言語 • 弱い型付けの動的型付き言語 ◦ ここが柔軟性に聞いてくる • インタープリターで実行される ◦ Opcache はあるけどね

    • 型に関する改修が最近多いのはご存知の通り 31
  32. 型システムを強化することへの期待 • 型宣言が性能を上げる ◦ JIT で型宣言の情報を使う ◦ タイプヒンティングをすると性能が悪いのは過去の話 ▪ すでに

    Opcache で性能向上に利用されている(と言えなくもない) • 開発のしやすさの向上 ◦ もちろん動的型付き言語のメリットはある程度犠牲になる ◦ プロダクトの長い成長に耐えるコードベースの基礎ができる 32
  33. PHPが型を手に入れるべきか 後方互換性との兼ね合いが心配 新規開発ならまだいいかも知れない 言語の進化としても気になるところがある。 => 進化がドラスティックなわりに、根本的な課題    array の扱いが難しいなど 33

  34. ケース1 設定 • 既存システムの開発者 • 動的型付き言語として普通に開発されていた • レガシーシステムかもしれない • 開発環境は

    phpStorm => 型宣言より phpDoc をまず書く 34
  35. ケース1 • 既存システムに型宣言を書くのは難しい ◦ 柔軟な運用をしている場合は特に • PHPDoc なら動作を制限しない ◦ しかし、

    IDE の支援は受けることができる => ある程度型システムの恩恵を受けられる 35
  36. ケース2 設定 • スクラッチ開発 • 既存コードなんてない => 型宣言を積極的に使っていく 36

  37. ケース3 設定 • 既存システム • 型は意識していない • 型宣言されたライブラリを使うことになった => オーバーロードする場合は注意

    型を明確にしたい場合は DTO 用意するのも良し 37
  38. ケースバイケース 38

  39. 以上 39

  40. Any Questions? 40