1
00:00:00,520 --> 00:00:03,800
こんにちは。このクラスでは
Pharo の強力な例外をお見せします。

2
00:00:03,960 --> 00:00:06,400
概要をお見せします。

3
00:00:06,600 --> 00:00:09,160
例外で何ができるのでしょう？
例外から復帰(resume)できます。

4
00:00:09,520 --> 00:00:11,840
再実行(restart)もできます。
新しい例外としてシグナルします。

5
00:00:12,000 --> 00:00:16,240
例外を最初に使うための
実用上役にたつものだけを

6
00:00:16,400 --> 00:00:17,840
お見せしましょう。

7
00:00:18,000 --> 00:00:20,840
しかし、これが全てだというのでは
ありません。

8
00:00:21,000 --> 00:00:24,600
例外には 2 種類あります。
致命的なものが多いエラーと

9
00:00:24,760 --> 00:00:27,680
通知です。
通知は要らないということができ

10
00:00:27,840 --> 00:00:29,160
参考のためにあります。

11
00:00:30,320 --> 00:00:32,800
もし、例外についての

12
00:00:32,960 --> 00:00:35,800
完璧なリファレンスが必要であれば

13
00:00:35,960 --> 00:00:39,640
この書籍 Deep Into Pharo の
章が 1 つまるまるあります。

14
00:00:39,800 --> 00:00:45,040
この Mooc のウェブサイト上で
無料で提供されています。

15
00:00:45,600 --> 00:00:50,640
では何を学ぶのかというと
例外を挙げて捕捉することと

16
00:00:50,800 --> 00:00:54,400
普段から使うことができる
便利なヘルパーメソッドです。

17
00:00:54,960 --> 00:00:55,800
基本的には

18
00:00:56,000 --> 00:00:58,440
この講義でやることは全て
このページに書いてあります。

19
00:00:58,800 --> 00:01:02,360
例外を捕捉するための
ハンドラをインストールします。

20
00:01:02,520 --> 00:01:03,480
例外をシグナルして

21
00:01:03,640 --> 00:01:08,280
2 つの便利なメッセージをやります。
ensure: と ifCurtailed: です。

22
00:01:09,400 --> 00:01:11,280
では見てみましょう。

23
00:01:11,840 --> 00:01:14,680
例外を捕捉したいとしましょう。

24
00:01:14,840 --> 00:01:16,880
on:do: メッセージを使います。

25
00:01:17,040 --> 00:01:20,120
ブロックを用意しておいて何かしていて

26
00:01:20,280 --> 00:01:23,160
例外が起きたらどうなるでしょう。

27
00:01:23,320 --> 00:01:27,280
ここで something をします。
例外が引数として渡されます。

28
00:01:27,920 --> 00:01:31,520
ゼロ除算の例を見てみます。

29
00:01:31,680 --> 00:01:34,960
7 を 0 で割ると

30
00:01:35,600 --> 00:01:38,120
ゼロ除算で何が起こるかというと

31
00:01:38,280 --> 00:01:41,640
ゼロ除算があるぞ！と言います。

32
00:01:41,800 --> 00:01:47,160
ここで注目することは
この例外クラスのインスタンスが

33
00:01:48,360 --> 00:01:49,840
引数として渡されて

34
00:01:50,000 --> 00:01:52,600
例外に質問したりメッセージを送ることが
できるということです。

35
00:01:52,760 --> 00:01:54,680
なぜなら、Pharo では例外は
オブジェクトだからです。

36
00:01:54,840 --> 00:01:56,600
例外の中でメッセージを送って

37
00:01:56,760 --> 00:02:00,400
何かをして、0 となります。

38
00:02:00,800 --> 00:02:02,920
では、どうやって例外を起こすのでしょう？

39
00:02:03,240 --> 00:02:07,400
基本的に、例外を生成して
それに signal メッセージを送ります。

40
00:02:07,560 --> 00:02:10,840
ここでは、警告を与えたい場合には
Warning new

41
00:02:11,000 --> 00:02:15,240
例外を生成して、カスタマイズして
メッセージを設定します。

42
00:02:15,400 --> 00:02:16,760
そして signal メッセージを送ります。

43
00:02:16,920 --> 00:02:21,000
著者名を尋ねる例外
AuthorNameRequest クラスがあり

44
00:02:21,160 --> 00:02:23,000
メソッドを書けば

45
00:02:23,160 --> 00:02:24,720
他の API として使えます。

46
00:02:24,880 --> 00:02:28,240
AuthorNameRequest がこの API を
定義するからです。

47
00:02:28,400 --> 00:02:30,440
そこで 文字列 'Stef' を渡して
signal します。

48
00:02:30,600 --> 00:02:33,080
通常は

49
00:02:33,240 --> 00:02:38,040
クラスが signal するショートカットを
提供して、生成せずに済むようにします。


50
00:02:38,200 --> 00:02:41,640
OutOfMemory はクラスです。
このクラスに signal メッセージを送ります。

51
00:02:41,800 --> 00:02:44,800
通常は警告文をつけて
Warning new なんとかかんとか、とはしません。

52
00:02:44,960 --> 00:02:48,840
Warning signal: として文字列をつけます。
そのほうが短く書けます。

53
00:02:49,000 --> 00:02:51,160
ただし例外によります。

54
00:02:51,720 --> 00:02:56,800
ユニットテストをするアジャイルな
プログラミングや

55
00:02:57,000 --> 00:03:00,080
テスト駆動なプログラミングで

56
00:03:00,240 --> 00:03:04,440
例外が起こったことをどうやって
テストしたら良いでしょう？

57
00:03:04,600 --> 00:03:08,840
shouldnt:raise や should:raise:
を使います。

58
00:03:09,000 --> 00:03:10,440
一緒に読んでみましょう。

59
00:03:10,600 --> 00:03:13,640
ここで

60
00:03:13,800 --> 00:03:15,840
2 月の日付を生成する時に

61
00:03:16,000 --> 00:03:18,240
SubscriptOutOfBounds 例外は

62
00:03:18,400 --> 00:03:21,640
挙がって欲しくない、と書きます。

63
00:03:21,800 --> 00:03:25,200
では、13 月の日付を生成する時には

64
00:03:25,360 --> 00:03:29,040
エラーが発生しなければならない
とします。

65
00:03:29,200 --> 00:03:32,240
まあ普通はそんな日付はないですね。

66
00:03:32,400 --> 00:03:35,560
そこで should:raise: を使います。

67
00:03:35,720 --> 00:03:37,080
つまり

68
00:03:37,240 --> 00:03:40,960
13 月の日付を作るとエラーになる
ということです。

69
00:03:41,120 --> 00:03:44,000
こうすることで例外についての

70
00:03:44,160 --> 00:03:46,280
ユニットテストを書くことができます。

71
00:03:46,440 --> 00:03:48,400
細かなことではありますが

72
00:03:48,560 --> 00:03:51,120
これら 2 つのヘルパーメソッドを
知ることは重要です。

73
00:03:52,120 --> 00:03:54,360
Pharo での例外には

74
00:03:54,560 --> 00:03:56,040
Error があります。

75
00:03:56,200 --> 00:03:59,360
メッセージを理解できない
添字エラー、ゼロ除算など。

76
00:03:59,520 --> 00:04:03,280
Halt があります。
デバッグする時に見ることになります。

77
00:04:03,440 --> 00:04:04,840
ブレークポイントを置いて

78
00:04:05,000 --> 00:04:07,480
システムの実行を止めることができます。

79
00:04:07,640 --> 00:04:10,760
Notification があります。
致命的でないものです。

80
00:04:10,920 --> 00:04:15,400
例えば 廃止（Deprecation）です。
このメソッドは使うな。他のを使えと。

81
00:04:15,560 --> 00:04:16,880
警告やタイムアウトもです。

82
00:04:17,040 --> 00:04:19,760
おもしろいのは

83
00:04:19,920 --> 00:04:22,240
UnhandledError です。

84
00:04:22,400 --> 00:04:25,240
これがデバッガーを起動します。

85
00:04:25,400 --> 00:04:28,680
通常は UnhandledError は使いませんが
UnhandledError も Error の一種だと

86
00:04:28,840 --> 00:04:31,360
いうことは知っておいてください。

87
00:04:32,080 --> 00:04:34,720
例外は本物のオブジェクトです。

88
00:04:34,920 --> 00:04:37,920
doesNotUnderstand: メッセージが

89
00:04:38,120 --> 00:04:41,600
ProtoObject でどう定義されているか
Pharo ブラウザで見ることができます。

90
00:04:41,760 --> 00:04:43,920
そこでは
MessageNotUnderstood new

91
00:04:44,080 --> 00:04:48,960
message: と receiver: を送って
signal します。

92
00:04:49,120 --> 00:04:53,480
この例外は
Point new strangeAndBizarre で起こります。

93
00:04:53,640 --> 00:04:56,160
strangeAndBizarre メッセージは
知らないので。

94
00:04:56,320 --> 00:04:57,920
そこで例外を作ります。

95
00:04:59,440 --> 00:05:01,880
Deprecationは 例えば

96
00:05:02,040 --> 00:05:05,040
まだ成長している API を使っていて

97
00:05:05,200 --> 00:05:08,200
もう有効ではないと
Pharo が決めた場合です。

98
00:05:08,360 --> 00:05:09,520
実際…

99
00:05:09,680 --> 00:05:15,000
Pharo では deprecated:on:in:
を使います。

100
00:05:15,160 --> 00:05:17,360
分かりやすい例を選んでみました。

101
00:05:17,520 --> 00:05:19,680
menuItem title:
は何を言っているかというと

102
00:05:19,840 --> 00:05:23,880
title: のかわりに
addTitle: を使えということです。

103
00:05:25,200 --> 00:05:26,960
どう実装されているかというと

104
00:05:27,120 --> 00:05:30,480
deprecated:... は

105
00:05:30,640 --> 00:05:33,960
Deprecation という

106
00:05:34,120 --> 00:05:35,280
例外を生成して

107
00:05:35,440 --> 00:05:39,960
その例外オブジェクトに
メソッドや説明を与えて

108
00:05:40,120 --> 00:05:42,680
signal します。

109
00:05:42,840 --> 00:05:46,800
deprecation も　messageNotUnderstood も
例外で、例外を生成して挙げているということです。

110
00:05:48,320 --> 00:05:52,080
これは細かいことになりますが
例外の集合 ExceptionSet もあります。

111
00:05:52,240 --> 00:05:54,960
ZeroDivide や Warning が起こったら
という記述ができます。

112
00:05:55,120 --> 00:05:59,080
あるいはコンマで区切ることで

113
00:05:59,240 --> 00:06:02,800
例外の集合を生成することができます。

114
00:06:02,960 --> 00:06:06,200
これを使って
これらの例外に反応する、と書けます。

115
00:06:06,360 --> 00:06:11,000
滅多に使われません。
一通り見せるために説明しています。

116
00:06:11,720 --> 00:06:14,840
では、より頻繁に使われる

117
00:06:15,520 --> 00:06:17,320
便利なメソッドを見てみましょう。

118
00:06:17,480 --> 00:06:20,680
ある表現式について
プログラムがその手前で失敗しても。

119
00:06:20,840 --> 00:06:24,360
その表現式が必ず実行されるとどうやって
確証を得ることができるでしょうか？

120
00:06:24,520 --> 00:06:27,320
ensure: を使います。
ensure: は

121
00:06:27,480 --> 00:06:29,120
何かをやっていて

122
00:06:29,280 --> 00:06:33,520
別のブロックが実行されることを
保証します。

123
00:06:33,680 --> 00:06:38,800
とても強力です。
例えば自動的にファイルをクローズできます。

124
00:06:39,400 --> 00:06:43,160
Pharo のプロファイラーの
spyOn: を見てみましょう。

125
00:06:43,320 --> 00:06:46,680
プロファイリングを開始して

126
00:06:46,840 --> 00:06:49,640
プロファイリング対象の
このブロックを実行します。

127
00:06:49,800 --> 00:06:52,160
そしてプロファイルを停止することを
保証します。

128
00:06:52,320 --> 00:06:55,200
たとえプロファイル対象として渡された
ブロックがエラーを起こしても。

129
00:06:55,400 --> 00:06:57,480
もう1つ、とても便利なヘルパーがあります。

130
00:06:57,680 --> 00:07:00,000
ある表現式が

131
00:07:00,160 --> 00:07:04,680
プログラムが失敗した時だけ
実行されることを保証します。

132
00:07:05,440 --> 00:07:09,320
何か変なことが起こったら

133
00:07:09,480 --> 00:07:13,880
これを実行する、というものです。

134
00:07:14,040 --> 00:07:16,680
wait の例は低レベルのもので

135
00:07:16,840 --> 00:07:20,800
プロセッサーのスケジューリングを
変えるものです。

136
00:07:21,520 --> 00:07:26,800
システムがセマフォをスケジュールして

137
00:07:26,960 --> 00:07:30,320
何か不具合があったら

138
00:07:30,480 --> 00:07:32,520
システムがスケジューラから

139
00:07:32,680 --> 00:07:36,160
外すことを保証します。

140
00:07:36,320 --> 00:07:40,080
これらのメソッドは
とても手軽でパワフルです。

141
00:07:40,480 --> 00:07:45,280
メソッド探索がどう動くかを説明する

142
00:07:45,440 --> 00:07:47,120
スライドを

143
00:07:47,320 --> 00:07:48,480
お見せしましたが

144
00:07:48,680 --> 00:07:50,440
ここでは...

145
00:07:50,600 --> 00:07:53,600
Pharo での例外では

146
00:07:53,760 --> 00:07:59,160
別の結果を返したり
再実行したりできます。

147
00:07:59,320 --> 00:08:01,320
プログラムの実行を変更して

148
00:08:01,480 --> 00:08:05,320
例外が起こらなかったかのように
動くようにすることが

149
00:08:05,480 --> 00:08:07,800
resume を使ってできます。

150
00:08:07,960 --> 00:08:11,600
この例外はこのレベルでは扱いたくないから

151
00:08:11,760 --> 00:08:13,280
より上位で扱ってほしい、ということが

152
00:08:13,440 --> 00:08:14,920
例外を pass することで可能です。

153
00:08:15,080 --> 00:08:18,840
古い例外を新しい例外で置き換えることも

154
00:08:19,000 --> 00:08:19,880
resignal でできます。

155
00:08:20,040 --> 00:08:23,520
これが必要な時には
あなたは何をやっているか分かっているでしょう。

156
00:08:23,680 --> 00:08:28,400
この章を読んで
こういうことができるこということを

157
00:08:28,600 --> 00:08:30,520
知っておいてください。

158
00:08:30,720 --> 00:08:33,600
例外から別の返り値を返す時は
return: を使います。

159
00:08:33,760 --> 00:08:38,160
これを見てわかるように
この値を返すブロックを渡して

160
00:08:38,320 --> 00:08:41,400
例外を挙げると、最終的には

161
00:08:41,560 --> 00:08:45,400
ブロックが返したこの値が返ってきます。
これが return: です。

162
00:08:45,560 --> 00:08:48,400
では、resume: は何かというと

163
00:08:48,560 --> 00:08:50,920
resume: では

164
00:08:51,080 --> 00:08:54,240
ここで起こされた例外について

165
00:08:54,400 --> 00:08:58,560
resume: すると

166
00:08:58,720 --> 00:09:02,120
このハンドラで与えた値ではなく
次の値になります。

167
00:09:02,280 --> 00:09:07,360
例外が発生した箇所から継続するのです。
なので、ここから再開します。

168
00:09:07,520 --> 00:09:10,120
そしてこの値が得られます。

169
00:09:11,240 --> 00:09:14,000
ではまとめます。

170
00:09:14,200 --> 00:09:16,960
Pharo の例外は強力です。
ええ、いいですね。

171
00:09:17,120 --> 00:09:20,840
とてもシンプルな API があります。
例外を挙げる signal と

172
00:09:21,000 --> 00:09:22,720
例外を捕捉する on:do: と

173
00:09:22,880 --> 00:09:27,880
この表現式が必ず実行されるように
保証する ensure: と

174
00:09:28,040 --> 00:09:30,280
問題が発生するか否かで

175
00:09:30,440 --> 00:09:32,720
発生した時に実行する ifCurtailed:

176
00:09:32,880 --> 00:09:35,720
doSomething の中で問題が発生したら
onProblem を実行します。

177
00:09:35,880 --> 00:09:38,760
例外を使い始めるために必要なことは
これで全てです。
