WEBVTT

00:00:00.680 --> 00:00:01.800 align:middle
こんにちは。

00:00:01.960 --> 00:00:04.640 align:middle
今日はメッセージの話をしようと思います。

00:00:04.800 --> 00:00:08.800 align:middle
大量のメッセージと小さなメソッドの
利点をお見せします。

00:00:08.960 --> 00:00:11.520 align:middle
多くの開発者は
反対なことを信じているようですが。

00:00:12.640 --> 00:00:16.120 align:middle
このスライドはこの講義での
設計に関することを示しています。

00:00:16.640 --> 00:00:18.920 align:middle
Pharo だけでなく

00:00:19.080 --> 00:00:22.280 align:middle
あらゆるオブジェクト指向言語での
設計で有効なことです。

00:00:23.800 --> 00:00:27.240 align:middle
知っての通り、メッセージ送信は
一種のフックで

00:00:27.400 --> 00:00:30.640 align:middle
その振る舞いを定義する
場所になっています。

00:00:30.840 --> 00:00:35.680 align:middle
開発者はよく大きなメソッドを好みます。

00:00:35.840 --> 00:00:37.760 align:middle
そのほうが理解しやすいと言います。

00:00:37.920 --> 00:00:41.480 align:middle
行を読んでコードを理解します。

00:00:41.640 --> 00:00:44.320 align:middle
しかし、この講義では

00:00:44.480 --> 00:00:46.720 align:middle
それは褒められたものではない
ということをお見せします。

00:00:46.880 --> 00:00:50.080 align:middle
一般に大きなメソッドは悪い設計です。

00:00:51.280 --> 00:00:53.120 align:middle
クラス階層や

00:00:53.280 --> 00:00:56.280 align:middle
複数クラスでの同じメソッドの定義で

00:00:56.440 --> 00:00:58.480 align:middle
場合分けを定義することができます。

00:00:59.000 --> 00:01:02.960 align:middle
もし、あるクラスに大量の操作が
定義されて、肥大化していて

00:01:03.120 --> 00:01:07.320 align:middle
状態に応じて適切な操作を
選ばなければならないとしたら

00:01:07.480 --> 00:01:11.240 align:middle
「この状態の場合にはこの操作を実行して

00:01:11.400 --> 00:01:13.960 align:middle
この状態のときにはあの操作を実行する」
のようなコードを書くことになります。

00:01:14.120 --> 00:01:16.680 align:middle
結果、長大なコードに

00:01:16.840 --> 00:01:19.360 align:middle
if があちこちに溢れかえります。

00:01:19.520 --> 00:01:22.520 align:middle
つまり、新しい場合分けが必要な時に

00:01:22.680 --> 00:01:25.040 align:middle
色々なメソッドのあちこちを
修正しなければならないということです。

00:01:25.400 --> 00:01:28.400 align:middle
右側の設計では

00:01:29.200 --> 00:01:33.880 align:middle
それぞれの場合についてクラスが対応付けられて
操作が定義されています。

00:01:34.240 --> 00:01:38.040 align:middle
操作をおこなうメッセージを
オブジェクトに送るだけで

00:01:38.320 --> 00:01:41.280 align:middle
条件分けがされます。

00:01:41.440 --> 00:01:45.320 align:middle
プログラマが if を書く必要はありません。

00:01:46.640 --> 00:01:50.480 align:middle
多態性の原理によって
自動的に行われます。

00:01:50.640 --> 00:01:55.920 align:middle
次のスライドでは、1 つのプログラムを

00:01:56.080 --> 00:01:58.120 align:middle
小さく分割することで改善する例を
お見せします。

00:01:58.640 --> 00:02:01.760 align:middle
ここに巨大メソッドがあります。
理解しにくくて

00:02:01.920 --> 00:02:03.480 align:middle
多くのことを行います。

00:02:03.640 --> 00:02:05.560 align:middle
私がやりたいのは、これです。

00:02:06.280 --> 00:02:07.640 align:middle
サブクラスで

00:02:07.800 --> 00:02:11.840 align:middle
この変数に異なる値を与えます。

00:02:12.800 --> 00:02:14.720 align:middle
つまりこういうことです。

00:02:14.880 --> 00:02:18.000 align:middle
サブクラスを作って

00:02:18.160 --> 00:02:20.920 align:middle
全てのコードをコピーして
同じコードを持たせて

00:02:21.080 --> 00:02:24.080 align:middle
それぞれについて修正を加えます。

00:02:24.920 --> 00:02:27.480 align:middle
Java のような

00:02:27.640 --> 00:02:29.160 align:middle
private というキーワードを使う言語では

00:02:29.320 --> 00:02:32.560 align:middle
メソッドで使われる属性が private の場合

00:02:32.720 --> 00:02:34.760 align:middle
こうするのは不可能です。

00:02:35.000 --> 00:02:39.040 align:middle
そのメソッドが private な
インスタンス変数を使っていると

00:02:39.200 --> 00:02:42.520 align:middle
そのサブクラスは同じコードを使えません。

00:02:42.880 --> 00:02:46.960 align:middle
いずれにせよコードの複製は
基本的に良くないのです。

00:02:47.480 --> 00:02:50.120 align:middle
バグも複製してしまいます。

00:02:50.280 --> 00:02:54.560 align:middle
元のメソッドにバグがあったら
その複製にもバグができることになります。

00:02:55.800 --> 00:03:00.640 align:middle
そして一方を修正したら
全ての複製について修正する必要があります。

00:03:01.520 --> 00:03:03.760 align:middle
開発者としては
余計な仕事をすることになります。

00:03:03.920 --> 00:03:07.200 align:middle
しかも、色々なコピーの箇所を
覚えておく必要があるわけです。

00:03:08.760 --> 00:03:11.960 align:middle
正しい解決策はメッセージ送信です。

00:03:12.320 --> 00:03:16.560 align:middle
対応するメソッドの中身を
直接埋め込んで書くのではなく

00:03:16.720 --> 00:03:20.160 align:middle
メッセージを送ることで

00:03:20.320 --> 00:03:22.920 align:middle
サブクラスがその振る舞いを
オーバーライドすることができます。

00:03:24.160 --> 00:03:26.640 align:middle
bar メソッドを見ると

00:03:26.800 --> 00:03:28.680 align:middle
self に foo を送っています。

00:03:28.840 --> 00:03:30.960 align:middle
クラス A では foo は 10 を返しますが

00:03:31.120 --> 00:03:33.880 align:middle
サブクラスはこの値をオーバーライドして

00:03:34.040 --> 00:03:36.600 align:middle
例えば 42 に置き換えることができます。

00:03:37.240 --> 00:03:40.720 align:middle
今お見せしたコードを改良して

00:03:40.880 --> 00:03:44.360 align:middle
複製ではなく継承機構を使うには

00:03:44.520 --> 00:03:46.320 align:middle
どうしたら良いでしょう？

00:03:46.480 --> 00:03:50.520 align:middle
この部分を抽出して
メッセージ送信にします。

00:03:50.680 --> 00:03:54.200 align:middle
メソッドの抽出という
リファクタリング機能でできます。

00:03:54.360 --> 00:03:58.080 align:middle
ツールがこのコードをこのコードに
変換してくれます。

00:03:59.200 --> 00:04:01.960 align:middle
前のスライドで選択したコードが

00:04:02.120 --> 00:04:06.240 align:middle
ratio という新しいメソッドとして
括り出されています。

00:04:07.800 --> 00:04:12.320 align:middle
そしてコードが書かれていた部分は
メッセージ送信になっています。

00:04:13.240 --> 00:04:15.880 align:middle
つまり、サブクラスでは

00:04:17.000 --> 00:04:20.360 align:middle
この振る舞いを変えることができる
ということになります。

00:04:20.520 --> 00:04:22.440 align:middle
完全に変えてしまっても良いですし

00:04:22.600 --> 00:04:26.640 align:middle
スーパークラスの振る舞いを利用して
修正するのでも良いです。

00:04:26.800 --> 00:04:28.560 align:middle
今やったことは

00:04:28.720 --> 00:04:30.720 align:middle
super に ratio メッセージを送って

00:04:30.880 --> 00:04:34.760 align:middle
スーパークラスにあるこのコードを実行して

00:04:34.920 --> 00:04:37.720 align:middle
その結果に10を加えます。
これで元の目的を達成できます。

00:04:39.880 --> 00:04:44.760 align:middle
もう 1 つの方法は
この部分を抽出して

00:04:44.920 --> 00:04:49.440 align:middle
サブクラスがその振る舞いを
変更できるようにすることです。

00:04:50.360 --> 00:04:53.160 align:middle
このコード片を

00:04:53.320 --> 00:04:55.640 align:middle
メソッドにします。

00:04:56.200 --> 00:04:59.440 align:middle
そして元のメソッドでは
メッセージを送ります。

00:05:02.120 --> 00:05:03.240 align:middle
この場合

00:05:03.480 --> 00:05:07.520 align:middle
クラスがハードコードされています。

00:05:07.680 --> 00:05:11.400 align:middle
つまり、サブクラスが UINode クラスの
サブクラスなど

00:05:11.560 --> 00:05:14.160 align:middle
別のクラスを使いたい場合に

00:05:14.320 --> 00:05:17.280 align:middle
メソッド全体を複製しなければ
ならなくなるでしょう。

00:05:17.440 --> 00:05:19.600 align:middle
ここで同じ方法で

00:05:19.760 --> 00:05:23.440 align:middle
クラスをメソッドに括り出して

00:05:23.600 --> 00:05:27.040 align:middle
サブクラスがそれを
変更できるようにします。

95 align:middle
00:05:27,200 --> 00:05:28,840
それがこれです。

00:05:29.000 --> 00:05:32.440 align:middle
メソッドにしたい部分を括り出して

00:05:34.720 --> 00:05:36.760 align:middle
メッセージを送ります。

00:05:36.920 --> 00:05:40.560 align:middle
メッセージを送ることで
サブクラスがその振る舞いを変えることができます。

00:05:40.920 --> 00:05:43.760 align:middle
前に言ったように
プログラマーの中には

00:05:43.920 --> 00:05:46.440 align:middle
このやり方に同意しない人たちもいます。

00:05:47.120 --> 00:05:51.520 align:middle
細かく散らばったメソッドを読むのは
難しいと言います。

00:05:51.680 --> 00:05:54.280 align:middle
それよりも大きなメソッドを
1 行ずつ読むのうが良いと言います。

00:05:54.440 --> 00:05:58.200 align:middle
これは実践として良いやり方ではありません。
アプリケーションが大きくなると

00:05:58.360 --> 00:06:01.400 align:middle
1 行ずつ読んでも解らなくなるからです。

00:06:01.560 --> 00:06:05.640 align:middle
1 行ずつ読んでも全体で何が起こるのか
把握することはできません。

00:06:05.800 --> 00:06:10.440 align:middle
これこそ抽象を使うべきところであり

00:06:10.600 --> 00:06:13.040 align:middle
メソッドから一部を括り出すことの
意味があります。

00:06:13.200 --> 00:06:17.320 align:middle
個々の詳細を理解しなくても
メソッド全体としての意味を理解できます。

00:06:18.040 --> 00:06:21.520 align:middle
したがって、小さなメソッドは優れています。
いつでもそうすべきなのです。

00:06:22.400 --> 00:06:24.920 align:middle
では続けましょう。

00:06:26.160 --> 00:06:30.240 align:middle
ここに 55 という値が

00:06:30.400 --> 00:06:31.800 align:middle
メソッドにハードコードされています。

00:06:31.960 --> 00:06:36.000 align:middle
そのためにサブクラスは
例えば 100 に変更できません。

00:06:36.160 --> 00:06:40.480 align:middle
そこで前にやったように
この値を括り出して

00:06:41.800 --> 00:06:46.600 align:middle
別のメソッドにすることで
サブクラスが値を変えることができます。

00:06:47.440 --> 00:06:50.120 align:middle
このやり方のもう 1 つの利点は

00:06:50.280 --> 00:06:52.520 align:middle
ここに 55 という値が
書いてありましたが

00:06:52.680 --> 00:06:54.720 align:middle
それを self averageRatio
とすることで

00:06:54.880 --> 00:06:58.560 align:middle
数値ではなく名前を示していることです。

00:06:58.720 --> 00:07:02.200 align:middle
これで 55 という値が何なのか
知ることができます。

00:07:02.360 --> 00:07:07.440 align:middle
これで 55 は averageRatio だと
コードを読んで理解できるわけです。

00:07:07.600 --> 00:07:11.240 align:middle
このように、小さなメソッドは
コードの読解の助けになります。

00:07:11.680 --> 00:07:14.800 align:middle
55 を返す averageRatio メソッドを
定義することで

00:07:14.960 --> 00:07:17.720 align:middle
サブクラスがその値を変えることが
できるようになります。

00:07:17.880 --> 00:07:21.640 align:middle
では、クラスのユーザーがその値を
変えたい時はどうしたら良いでしょう？

00:07:22.000 --> 00:07:23.360 align:middle
考えられる方法としては

00:07:23.520 --> 00:07:25.840 align:middle
インスタンス変数を使います。

00:07:26.640 --> 00:07:30.600 align:middle
前のスライドの
averageRatio メソッドが

00:07:30.760 --> 00:07:33.920 align:middle
インスタンス変数の値を
返すようにします。

00:07:34.080 --> 00:07:38.480 align:middle
インスタンス変数に値が設定されていなければ
デフォルト値を返します。

00:07:38.800 --> 00:07:40.920 align:middle
デフォルト値は 55 です。

00:07:41.640 --> 00:07:45.120 align:middle
これでのオブジェクトのユーザーは

00:07:45.280 --> 00:07:48.080 align:middle
好きなように値を設定できます。

00:07:48.240 --> 00:07:49.680 align:middle
この設計では

00:07:49.840 --> 00:07:54.520 align:middle
サブクラスは defaultAverageRatio
をオーバーライドして

00:07:55.000 --> 00:07:56.320 align:middle
値を変更することができます。

00:07:56.480 --> 00:08:01.120 align:middle
そしてこのクラスのユーザーは
値を設定することができます。

00:08:01.640 --> 00:08:04.360 align:middle
この手法はグリュイエール（チーズ）
指向プログラミングと呼ばれます。

00:08:05.400 --> 00:08:09.440 align:middle
というのも、オブジェクト指向の
プログラムやメソッドは

00:08:09.600 --> 00:08:12.200 align:middle
フックという穴を持っていて

00:08:12.360 --> 00:08:15.960 align:middle
その穴をサブクラスが
埋めることができるからです。

00:08:16.800 --> 00:08:18.320 align:middle
まとめると

00:08:18.480 --> 00:08:22.280 align:middle
コードはサブクラスで再利用され
再定義されます。

00:08:22.440 --> 00:08:25.280 align:middle
メッセージを送るたびに

00:08:25.440 --> 00:08:29.240 align:middle
サブクラスにはスーパークラスの振る舞いを
変える機会を得ます。

00:08:29.400 --> 00:08:31.600 align:middle
修正しても完全に変えても構いません。

00:08:32.560 --> 00:08:37.760 align:middle
メソッドを小さくすることは良いことです。
それによって細かな式に名前を与え

00:08:38.080 --> 00:08:42.560 align:middle
サブクラスにその式を変更する自由を
与えるからです。

