@require: class-slydifi/theme/akasaka @require: code-printer/code-design @require: code-printer/code-printer @require: code-printer/code-syntax @require: code-printer/code-theme @require: figbox/figbox let-block +code-block-c source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.c CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let-block +code-block-cpp source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.cpp CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let-block +code-block-java source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.java CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let-block +code-block-go source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.go CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let-block +code-block-rust source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.rust CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let-block +code-block-php source = '< +code-printer?:( CodePrinter.make-config CodeSyntax.php CodeTheme.iceberg-light |> CodePrinter.set-number-fun CodeDesign.number-fun-null )(source); > let-inline \bad = { \text-color(Color.rgb 0.75 0.25 0.25){Bad} } let-inline \good = { \text-color(Color.rgb 0.1 0.5 0.1){Good} } open FigBox in document '< +set-config(| SlydifiThemeAkasaka.default-config with color-emph = Color.black; |); +make-title(| title = { |言語間で比較する |エラーの通知と処理 |}; author = {|nsfisis (いまむら)|}; date = {|第154回PHP勉強会@東京|}; |); %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +frame{自己紹介}< +fig-center(vconcat [ gap 75pt; hconcat [ textbox{nsfisis (いまむら)}; gap 20pt; include-image 50pt `assets/me.jpeg`; ]; gap 20pt; textbox{\@ デジタルサーカス株式会社}; ]); > +frame{話すこと、話さないこと}< +listing{ * 話すこと ** 様々な言語におけるエラー通知の方法 * 話さないこと ** 君たちはどう生きるか (PHP におけるベストプラクティス) } > +frame{取り上げる言語}< +listing{ * C * C++ * Java * Go * Rust } > %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +section{|C|}< +frame{C: 成功/失敗を戻り値で表す}< +code-block-c(`#include bool do_something() { // ... if (success) { return true; } else { return false; } } `); +p{ PHP では \inline-code(`mkdir()`); など } > +frame{C: 成功/失敗を戻り値で表す}< +listing{ * \bad; 処理結果があるときに使えない * \bad; エラーに情報を載せられない * \bad; エラーハンドリングを省略できる ** \bad; 省略したとき、後続の処理が一切止まらない } > +frame{C: 引数で処理結果を受け取る}< +code-block-c(`#include bool do_something(something* result) { // ... if (success) { *result = ...; return true; } else { return false; } } `); +p{ PHP では \inline-code(`preg_match()`); など } > +frame{C: 引数で処理結果を受け取る}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \bad; エラーハンドリングを省略できる ** \good; 省略したとき、処理結果を使おうとすると止まる ** \bad; 省略したとき、後続の処理が進みうる } > +frame{C: 処理結果または失敗を返す}< +code-block-c(`something* do_something() { // ... if (success) { return result; } else { return NULL; } } `); +p{ PHP では \inline-code(`fopen()`); など } > +frame{C: 処理結果または失敗を返す}< +listing{ * \good; 処理結果があるときに使える * \bad; エラーに情報を載せられない ** 注: 動的型付き言語の場合はその限りでない * \bad; エラーハンドリングを省略できる ** \good; 省略したとき、処理結果を使おうとすると止まる ** \bad; 省略したとき、後続の処理が進みうる } > +frame{C: グローバル状態から通知する}< +code-block-c(`some_error error; void do_something() { // ... if (success) { error = 0; } else { error = 42; } } some_error get_error() { return error; } `); +p{ PHP では \inline-code(`json_decode()`); と \inline-code(`json_last_error()`); など } > +frame{C: グローバル状態から通知する}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \bad; エラーハンドリングを省略できる ** \bad; 省略したとき、後続の処理が一切止まらない } > > +section{|C++|}< +frame{C++: 例外を投げる}< +code-block-cpp(`#include void do_something() { // ... if (!success) { throw std::runtime_error{"..."}; } } `); +p{ PHP では \inline-code(`DateTimeImmutable::__construct()`); など } > +frame{C++: 例外を投げる}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \bad; エラーハンドリングを省略できる ** \good; 省略したとき、そこで止まる } > > +section{|Java|}< +frame{Java: 検査例外}< +code-block-java(`void doSomething() throws SomeException { // ... if (!success) { throw new SomeException(...); } } `); +p{ PHP では \inline-code(`@throws`); が (一応) 近い } > +frame{Java: 検査例外}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \good; エラーハンドリングを省略するとコンパイルエラーになる ** \good; 省略ができない } > +frame{Java: 検査例外}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \good; エラーハンドリングを省略するとコンパイルエラーになる ** \good; 省略ができない * \bad; どこでどの例外が投げられるのかわかりにくい ** 注: 例外自体の問題ではなく、C++ や Java が採用している文法の問題 * \bad; 大域脱出は処理の動きが複雑になる * \bad; 例外クラスの継承ツリー設計が困難 * \bad; 回復不能なエラーまで例外で表される * 検査例外固有の問題がいくつかある (ここでは割愛) } > > +section{|Go|}< +frame{Go: 多値返却}< +code-block-go(`func doSomething() (int, error) { // ... if success { return 42, nil } else { return 0, errors.New("...") } } result, err := doSomething() if err != nil { // ... } `); > +frame{Go: 多値返却}< +code-block-php(` +frame{Go: 多値返却}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \bad; エラーハンドリングを省略できる ** \good; linter での検知は可能 } > +frame{Go: panic}< +code-block-go(`func doSomething() int { // ... if !success { panic("...") } return 42 } `); +p{ 回復不能なエラー。(基本的には) 捕まえられない } > +frame{Go: 多値返却 + panic}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \bad; エラーハンドリングを省略できる ** \good; linter での検知は可能 * \good; 特殊な構文なし、大域脱出なし * \good; エラー値のカテゴライズに継承が使われない * \good; 回復可能なエラーと回復不能なエラーを区別できる * \bad; 静的型付き言語以外だと、C と同レベルの安全性になる } > > +section{|Rust|}< +frame{Rust: 代数的データ型}< +code-block-rust(`fn do_something() -> Result { // ... if success { Ok(42) } else { Err(SomeError::new()) } } `); +p{ PHP では union 型が一番近い } > +frame{Rust: 代数的データ型 + panic}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \good; エラーハンドリングを省略するとコンパイルエラーになる ** \good; 処理結果がない場合でも、linter での検知は可能 * \good; 特殊な構文なし、大域脱出なし * \good; エラー値のカテゴライズに継承が使われない * \good; 回復可能なエラーと回復不能なエラーを区別できる } > +frame{Rust: 代数的データ型 + panic}< +listing{ * \good; 処理結果があるときに使える * \good; エラーに情報を載せられる * \good; エラーハンドリングを省略するとコンパイルエラーになる ** \good; 処理結果がない場合でも、linter での検知は可能 * \good; 特殊な構文なし、大域脱出なし * \good; エラー値のカテゴライズに継承が使われない * \good; 回復可能なエラーと回復不能なエラーを区別できる * \bad; 静的型付き言語以外だと、C と同レベルの安全性になる * \bad; 言語側にそれ相応のシンタックスシュガーがないと書きづらい } > > +section{|PHP|}< +frame{我らが PHP は...}< +p{ C 言語の素朴な値による通知と例外をミックスしたキメラ } +p{ どう設計すべきかは今回のスコープ外 } > +frame{我らが PHP は...}< +p{ C 言語の素朴な値による通知と例外をミックスしたキメラ } +p{ どう設計すべきかは今回のスコープ外 } +p{ 君たちはどう生きるか } > > >