Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

自己紹介 やなせ たかし 株式会社ラクスで働いています。 PHP 歴 1 年未満 Scala 大好きマン ギターを嗜みます。ギターと技術で何かしたい ( 願望 ) 2

Slide 3

Slide 3 text

今日話すこと ● 型システムとは何なのか ● 型システムとプログラミング言語 ● PHP と型 ● 今から型システムとお付き合いを始めるには 3

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

型システムとは何なのか ● プログラムのふるまいを推論するためのツール ● 始めは int と float の違いを区別するようなもの ○ 効率よく計算するため ● 1970 年ごろからより高度な概念が研究される ○ 部分型 ○ 再帰型 ○ 多相 ○ 高階型 ○ などなど 7

Slide 8

Slide 8 text

型システムでできること ● エラー検知 ● 構造を明らかにする ● 安全性を高める ● プログラムの効率性を高める 8

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

構造を明らかにする ● 利用側と実装を分離できる ○ インターフェイスを型として扱うことで、利用する型を保証できる ● ドキュメント化しやすい ○ シグネチャーの型が正しいことは保証されている 11

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

安全性を高める(裏の顔) ● 多くの言語では、抜け道が存在する ○ たとえば、メモリ操作 API があるとか ○ 低レベル API はそういうのがありがち ● 「安全」の定義がまちまち ○ 型安全? ○ メモリ安全? 13

Slide 14

Slide 14 text

プログラムの効率性を高める ● 実行時に効率的なバイトコードを生成する ○ 静的型付き言語をコンパイルする ○ 低レベルで最適化できるので効率が良くなる ○ 動的型付き言語でも、 JIT をで型情報を集めてコンパイルしていることも 14

Slide 15

Slide 15 text

型システムがもたらすもの ● 安全性と ( 実行時の ) 効率 ● ただし、柔軟性とはトレードオフになりがち 15

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

静的型付き言語の特徴 ● コンパイル時に型が検査されている ● コンパイルされたら効率的なバイトコードになる ● 型に不整合があるプログラムは実行できない ● 型を書く必要がある言語もある ○ 昔の Java とか ● ( 一部 ) 型を書かなくてもいい言語もある ○ Scala とか ● 型を書くのがデメリットというわけではない 19

Slide 20

Slide 20 text

コンパイルされたらどうなるの ● コードが直接低レベルな命令に翻訳されている ● 一方インタープリターはコードを解釈しながら実行 型がわかっていれば、翻訳時に最適化が効く。 => 何らかの原因で型検査が入ると効率が悪くなる ● キャストやリフレクション 20

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

横道:型推論について ● 右辺の型を計算し、左辺の型を推論します ● var a = hoge; だけではない def map(ls, f) = ls match { case h::t => f(h) :: map(t, f) case Nil => Nil } ● 上の疑似コードの型が決まるのが型推論のすごさ 26

Slide 27

Slide 27 text

静的解析するから、静的型付き言語は不要では? ● 静的型付き言語と比較すると恩恵は限定的 ● ある程度の恩恵は受けられる ○ 静的解析できる範囲では型安全に実装できる ○ 実行時の恩恵は受けられない => 漸進的型付け などと表現される 27

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

PHPと型 29

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

PHPってどういう言語 ● 弱い型付けの動的型付き言語 ○ ここが柔軟性に聞いてくる ● インタープリターで実行される ○ Opcache はあるけどね ● 型に関する改修が最近多いのはご存知の通り 31

Slide 32

Slide 32 text

型システムを強化することへの期待 ● 型宣言が性能を上げる ○ JIT で型宣言の情報を使う ○ タイプヒンティングをすると性能が悪いのは過去の話 ■ すでに Opcache で性能向上に利用されている(と言えなくもない) ● 開発のしやすさの向上 ○ もちろん動的型付き言語のメリットはある程度犠牲になる ○ プロダクトの長い成長に耐えるコードベースの基礎ができる 32

Slide 33

Slide 33 text

PHPが型を手に入れるべきか 後方互換性との兼ね合いが心配 新規開発ならまだいいかも知れない 言語の進化としても気になるところがある。 => 進化がドラスティックなわりに、根本的な課題    array の扱いが難しいなど 33

Slide 34

Slide 34 text

ケース1 設定 ● 既存システムの開発者 ● 動的型付き言語として普通に開発されていた ● レガシーシステムかもしれない ● 開発環境は phpStorm => 型宣言より phpDoc をまず書く 34

Slide 35

Slide 35 text

ケース1 ● 既存システムに型宣言を書くのは難しい ○ 柔軟な運用をしている場合は特に ● PHPDoc なら動作を制限しない ○ しかし、 IDE の支援は受けることができる => ある程度型システムの恩恵を受けられる 35

Slide 36

Slide 36 text

ケース2 設定 ● スクラッチ開発 ● 既存コードなんてない => 型宣言を積極的に使っていく 36

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

ケースバイケース 38

Slide 39

Slide 39 text

以上 39

Slide 40

Slide 40 text

Any Questions? 40