﻿1
00:00:00,680 --> 00:00:01,800
こんにちは。

2
00:00:01,960 --> 00:00:04,640
今日はメッセージの話をしようと思います。

3
00:00:04,800 --> 00:00:08,800
大量のメッセージと小さなメソッドの
利点をお見せします。

4
00:00:08,960 --> 00:00:11,520
多くの開発者は
反対なことを信じているようですが。

5
00:00:12,640 --> 00:00:16,120
このスライドはこの講義での
設計に関することを示しています。

6
00:00:16,640 --> 00:00:18,920
Pharo だけでなく

7
00:00:19,080 --> 00:00:22,280
あらゆるオブジェクト指向言語での
設計で有効なことです。

8
00:00:23,800 --> 00:00:27,240
知っての通り、メッセージ送信は
一種のフックで

9
00:00:27,400 --> 00:00:30,640
その振る舞いを定義する
場所になっています。

10
00:00:30,840 --> 00:00:35,680
開発者はよく大きなメソッドを好みます。

11
00:00:35,840 --> 00:00:37,760
そのほうが理解しやすいと言います。

12
00:00:37,920 --> 00:00:41,480
行を読んでコードを理解します。

13
00:00:41,640 --> 00:00:44,320
しかし、この講義では

14
00:00:44,480 --> 00:00:46,720
それは褒められたものではない
ということをお見せします。

15
00:00:46,880 --> 00:00:50,080
一般に大きなメソッドは悪い設計です。

16
00:00:51,280 --> 00:00:53,120
クラス階層や

17
00:00:53,280 --> 00:00:56,280
複数クラスでの同じメソッドの定義で

18
00:00:56,440 --> 00:00:58,480
場合分けを定義することができます。

19
00:00:59,000 --> 00:01:02,960
もし、あるクラスに大量の操作が
定義されて、肥大化していて

20
00:01:03,120 --> 00:01:07,320
状態に応じて適切な操作を
選ばなければならないとしたら

21
00:01:07,480 --> 00:01:11,240
「この状態の場合にはこの操作を実行して

22
00:01:11,400 --> 00:01:13,960
この状態のときにはあの操作を実行する」
のようなコードを書くことになります。

23
00:01:14,120 --> 00:01:16,680
結果、長大なコードに

24
00:01:16,840 --> 00:01:19,360
if があちこちに溢れかえります。

25
00:01:19,520 --> 00:01:22,520
つまり、新しい場合分けが必要な時に

26
00:01:22,680 --> 00:01:25,040
色々なメソッドのあちこちを
修正しなければならないということです。

27
00:01:25,400 --> 00:01:28,400
右側の設計では

28
00:01:29,200 --> 00:01:33,880
それぞれの場合についてクラスが対応付けられて
操作が定義されています。

29
00:01:34,240 --> 00:01:38,040
操作をおこなうメッセージを
オブジェクトに送るだけで

30
00:01:38,320 --> 00:01:41,280
条件分けがされます。

31
00:01:41,440 --> 00:01:45,320
プログラマが if を書く必要はありません。

32
00:01:46,640 --> 00:01:50,480
多態性の原理によって
自動的に行われます。

33
00:01:50,640 --> 00:01:55,920
次のスライドでは、1 つのプログラムを

34
00:01:56,080 --> 00:01:58,120
小さく分割することで改善する例を
お見せします。

35
00:01:58,640 --> 00:02:01,760
ここに巨大メソッドがあります。
理解しにくくて

36
00:02:01,920 --> 00:02:03,480
多くのことを行います。

37
00:02:03,640 --> 00:02:05,560
私がやりたいのは、これです。

38
00:02:06,280 --> 00:02:07,640
サブクラスで

39
00:02:07,800 --> 00:02:11,840
この変数に異なる値を与えます。

40
00:02:12,800 --> 00:02:14,720
つまりこういうことです。

41
00:02:14,880 --> 00:02:18,000
サブクラスを作って

42
00:02:18,160 --> 00:02:20,920
全てのコードをコピーして
同じコードを持たせて

43
00:02:21,080 --> 00:02:24,080
それぞれについて修正を加えます。

44
00:02:24,920 --> 00:02:27,480
Java のような

45
00:02:27,640 --> 00:02:29,160
private というキーワードを使う言語では

46
00:02:29,320 --> 00:02:32,560
メソッドで使われる属性が private の場合

47
00:02:32,720 --> 00:02:34,760
こうするのは不可能です。

48
00:02:35,000 --> 00:02:39,040
そのメソッドが private な
インスタンス変数を使っていると

49
00:02:39,200 --> 00:02:42,520
そのサブクラスは同じコードを使えません。

50
00:02:42,880 --> 00:02:46,960
いずれにせよコードの複製は
基本的に良くないのです。

51
00:02:47,480 --> 00:02:50,120
バグも複製してしまいます。

52
00:02:50,280 --> 00:02:54,560
元のメソッドにバグがあったら
その複製にもバグができることになります。

53
00:02:55,800 --> 00:03:00,640
そして一方を修正したら
全ての複製について修正する必要があります。

54
00:03:01,520 --> 00:03:03,760
開発者としては
余計な仕事をすることになります。

55
00:03:03,920 --> 00:03:07,200
しかも、色々なコピーの箇所を
覚えておく必要があるわけです。

56
00:03:08,760 --> 00:03:11,960
正しい解決策はメッセージ送信です。

57
00:03:12,320 --> 00:03:16,560
対応するメソッドの中身を
直接埋め込んで書くのではなく

58
00:03:16,720 --> 00:03:20,160
メッセージを送ることで

59
00:03:20,320 --> 00:03:22,920
サブクラスがその振る舞いを
オーバーライドすることができます。

60
00:03:24,160 --> 00:03:26,640
bar メソッドを見ると

61
00:03:26,800 --> 00:03:28,680
self に foo を送っています。

62
00:03:28,840 --> 00:03:30,960
クラス A では foo は 10 を返しますが

63
00:03:31,120 --> 00:03:33,880
サブクラスはこの値をオーバーライドして

64
00:03:34,040 --> 00:03:36,600
例えば 42 に置き換えることができます。

65
00:03:37,240 --> 00:03:40,720
今お見せしたコードを改良して

66
00:03:40,880 --> 00:03:44,360
複製ではなく継承機構を使うには

67
00:03:44,520 --> 00:03:46,320
どうしたら良いでしょう？

68
00:03:46,480 --> 00:03:50,520
この部分を抽出して
メッセージ送信にします。

69
00:03:50,680 --> 00:03:54,200
メソッドの抽出という
リファクタリング機能でできます。

70
00:03:54,360 --> 00:03:58,080
ツールがこのコードをこのコードに
変換してくれます。

71
00:03:59,200 --> 00:04:01,960
前のスライドで選択したコードが

72
00:04:02,120 --> 00:04:06,240
ratio という新しいメソッドとして
括り出されています。

73
00:04:07,800 --> 00:04:12,320
そしてコードが書かれていた部分は
メッセージ送信になっています。

74
00:04:13,240 --> 00:04:15,880
つまり、サブクラスでは

75
00:04:17,000 --> 00:04:20,360
この振る舞いを変えることができる
ということになります。

76
00:04:20,520 --> 00:04:22,440
完全に変えてしまっても良いですし

77
00:04:22,600 --> 00:04:26,640
スーパークラスの振る舞いを利用して
修正するのでも良いです。

78
00:04:26,800 --> 00:04:28,560
今やったことは

79
00:04:28,720 --> 00:04:30,720
super に ratio メッセージを送って

80
00:04:30,880 --> 00:04:34,760
スーパークラスにあるこのコードを実行して

81
00:04:34,920 --> 00:04:37,720
その結果に10を加えます。
これで元の目的を達成できます。

82
00:04:39,880 --> 00:04:44,760
もう 1 つの方法は
この部分を抽出して

83
00:04:44,920 --> 00:04:49,440
サブクラスがその振る舞いを
変更できるようにすることです。

84
00:04:50,360 --> 00:04:53,160
このコード片を

85
00:04:53,320 --> 00:04:55,640
メソッドにします。

86
00:04:56,200 --> 00:04:59,440
そして元のメソッドでは
メッセージを送ります。

87
00:05:02,120 --> 00:05:03,240
この場合

88
00:05:03,480 --> 00:05:07,520
クラスがハードコードされています。

89
00:05:07,680 --> 00:05:11,400
つまり、サブクラスが UINode クラスの
サブクラスなど

90
00:05:11,560 --> 00:05:14,160
別のクラスを使いたい場合に

91
00:05:14,320 --> 00:05:17,280
メソッド全体を複製しなければ
ならなくなるでしょう。

92
00:05:17,440 --> 00:05:19,600
ここで同じ方法で

93
00:05:19,760 --> 00:05:23,440
クラスをメソッドに括り出して

94
00:05:23,600 --> 00:05:27,040
サブクラスがそれを
変更できるようにします。


95
00:05:27,200 --> 00:05:28,840
それがこれです。

96
00:05:29,000 --> 00:05:32,440
メソッドにしたい部分を括り出して

97
00:05:34,720 --> 00:05:36,760
メッセージを送ります。

98
00:05:36,920 --> 00:05:40,560
メッセージを送ることで
サブクラスがその振る舞いを変えることができます。

99
00:05:40,920 --> 00:05:43,760
前に言ったように
プログラマーの中には

100
00:05:43,920 --> 00:05:46,440
このやり方に同意しない人たちもいます。

101
00:05:47,120 --> 00:05:51,520
細かく散らばったメソッドを読むのは
難しいと言います。

102
00:05:51,680 --> 00:05:54,280
それよりも大きなメソッドを
1 行ずつ読むのうが良いと言います。

103
00:05:54,440 --> 00:05:58,200
これは実践として良いやり方ではありません。
アプリケーションが大きくなると

104
00:05:58,360 --> 00:06:01,400
1 行ずつ読んでも解らなくなるからです。

105
00:06:01,560 --> 00:06:05,640
1 行ずつ読んでも全体で何が起こるのか
把握することはできません。

106
00:06:05,800 --> 00:06:10,440
これこそ抽象を使うべきところであり

107
00:06:10,600 --> 00:06:13,040
メソッドから一部を括り出すことの
意味があります。

108
00:06:13,200 --> 00:06:17,320
個々の詳細を理解しなくても
メソッド全体としての意味を理解できます。

109
00:06:18,040 --> 00:06:21,520
したがって、小さなメソッドは優れています。
いつでもそうすべきなのです。

110
00:06:22,400 --> 00:06:24,920
では続けましょう。

111
00:06:26,160 --> 00:06:30,240
ここに 55 という値が

112
00:06:30,400 --> 00:06:31,800
メソッドにハードコードされています。

113
00:06:31,960 --> 00:06:36,000
そのためにサブクラスは
例えば 100 に変更できません。

114
00:06:36,160 --> 00:06:40,480
そこで前にやったように
この値を括り出して

115
00:06:41,800 --> 00:06:46,600
別のメソッドにすることで
サブクラスが値を変えることができます。

116
00:06:47,440 --> 00:06:50,120
このやり方のもう 1 つの利点は

117
00:06:50,280 --> 00:06:52,520
ここに 55 という値が
書いてありましたが

118
00:06:52,680 --> 00:06:54,720
それを self averageRatio
とすることで

119
00:06:54,880 --> 00:06:58,560
数値ではなく名前を示していることです。

120
00:06:58,720 --> 00:07:02,200
これで 55 という値が何なのか
知ることができます。

121
00:07:02,360 --> 00:07:07,440
これで 55 は averageRatio だと
コードを読んで理解できるわけです。

122
00:07:07,600 --> 00:07:11,240
このように、小さなメソッドは
コードの読解の助けになります。

123
00:07:11,680 --> 00:07:14,800
55 を返す averageRatio メソッドを
定義することで

124
00:07:14,960 --> 00:07:17,720
サブクラスがその値を変えることが
できるようになります。

125
00:07:17,880 --> 00:07:21,640
では、クラスのユーザーがその値を
変えたい時はどうしたら良いでしょう？

126
00:07:22,000 --> 00:07:23,360
考えられる方法としては

127
00:07:23,520 --> 00:07:25,840
インスタンス変数を使います。

128
00:07:26,640 --> 00:07:30,600
前のスライドの
averageRatio メソッドが

129
00:07:30,760 --> 00:07:33,920
インスタンス変数の値を
返すようにします。

130
00:07:34,080 --> 00:07:38,480
インスタンス変数に値が設定されていなければ
デフォルト値を返します。

131
00:07:38,800 --> 00:07:40,920
デフォルト値は 55 です。

132
00:07:41,640 --> 00:07:45,120
これでのオブジェクトのユーザーは

133
00:07:45,280 --> 00:07:48,080
好きなように値を設定できます。

134
00:07:48,240 --> 00:07:49,680
この設計では

135
00:07:49,840 --> 00:07:54,520
サブクラスは defaultAverageRatio
をオーバーライドして

136
00:07:55,000 --> 00:07:56,320
値を変更することができます。

137
00:07:56,480 --> 00:08:01,120
そしてこのクラスのユーザーは
値を設定することができます。

138
00:08:01,640 --> 00:08:04,360
この手法はグリュイエール（チーズ）
指向プログラミングと呼ばれます。

139
00:08:05,400 --> 00:08:09,440
というのも、オブジェクト指向の
プログラムやメソッドは

140
00:08:09,600 --> 00:08:12,200
フックという穴を持っていて

141
00:08:12,360 --> 00:08:15,960
その穴をサブクラスが
埋めることができるからです。

142
00:08:16,800 --> 00:08:18,320
まとめると

143
00:08:18,480 --> 00:08:22,280
コードはサブクラスで再利用され
再定義されます。

144
00:08:22,440 --> 00:08:25,280
メッセージを送るたびに

145
00:08:25,440 --> 00:08:29,240
サブクラスにはスーパークラスの振る舞いを
変える機会を得ます。

146
00:08:29,400 --> 00:08:31,600
修正しても完全に変えても構いません。

147
00:08:32,560 --> 00:08:37,760
メソッドを小さくすることは良いことです。
それによって細かな式に名前を与え

148
00:08:38,080 --> 00:08:42,560
サブクラスにその式を変更する自由を
与えるからです。
