aboutsummaryrefslogtreecommitdiffhomepage
path: root/slide.saty
blob: 5d5c12388159f8c3f55bd2a96d96c003f0c976b8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
@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 <stdbool.h>

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 <stdbool.h>

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 <stdexcept>

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(`<?php
function do_something(): array {
    // ...
    if ($success) {
        return [42, null];
    } else {
        return [null, new SomeError(...)];
    }
}

[$result, $err] = do_something();
if (isset($err)) {
    // ...
}
      `);
    >

    +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<i32, SomeError> {
    // ...
    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{
        君たちはどう生きるか
      }
    >
  >

>