1 00:00:00,440 --> 00:00:02,600 こんにちは。 前回のセッションでは 2 00:00:02,760 --> 00:00:06,880 真偽値の not と or の 実装方法をみてきました。 3 00:00:07,040 --> 00:00:11,960 3つ目の問題が残っています。 一体なぜこれらの問題をやるのか? 4 00:00:12,120 --> 00:00:13,880 それを学びます。 5 00:00:14,760 --> 00:00:20,120 実装を振り返ってみましょう。 not について。2つのオブジェクトがありました。 6 00:00:20,280 --> 00:00:22,400 true と false です。 7 00:00:22,560 --> 00:00:25,440 True クラスと False クラスのインスタンスでした。 8 00:00:25,600 --> 00:00:27,200 not メッセージを送ると 9 00:00:27,360 --> 00:00:31,640 それぞれに対応するクラスに問い合わせて メソッドを実行しました。 10 00:00:32,560 --> 00:00:34,080 問題ないですね。 11 00:00:35,120 --> 00:00:37,240 伝えたことは 12 00:00:37,400 --> 00:00:39,720 何かと言うと 13 00:00:39,880 --> 00:00:42,920 まず第一に、レシーバーに決めさせること。 14 00:00:43,080 --> 00:00:46,080 つまり、自分では何も決めないで 15 00:00:46,240 --> 00:00:49,320 メッセージを送ることで解決します。 16 00:00:49,480 --> 00:00:53,840 経験則が2つありました。 レシーバーに決めさせること。 17 00:00:54,000 --> 00:00:57,320 そして、「求めるな、命じよ」です。 18 00:00:57,480 --> 00:00:58,960 これについては、後でまた出てきます。 19 00:00:59,120 --> 00:01:02,480 では、練習問題自体を見てみましょう。 20 00:01:03,080 --> 00:01:04,720 さて、これは何なのでしょう? 21 00:01:04,880 --> 00:01:08,240 あなたが今後人生において 真偽値を実装することは決してないでしょう。 22 00:01:08,400 --> 00:01:10,080 少なくとも、私はそう願います。 23 00:01:10,240 --> 00:01:13,000 では全く使い道がないことでしょうか? 24 00:01:13,160 --> 00:01:15,920 背後にある教えは、何でしょうか? 25 00:01:16,080 --> 00:01:19,240 私はこの問題を問うことは とても重要なことだと考えています。 26 00:01:19,400 --> 00:01:23,600 実装はあんな感じだとして だからどうだというのでしょう? 27 00:01:24,560 --> 00:01:29,360 メッセージ送信をする時にはいつも 28 00:01:29,520 --> 00:01:33,640 case 文を実行しているということです。 29 00:01:35,000 --> 00:01:38,800 C プログラミング等によくあることです。 30 00:01:39,880 --> 00:01:42,840 メッセージを送ることは 複数の選択肢から選ぶということです。 31 00:01:44,160 --> 00:01:46,880 興味深いことは メッセージを送ると 32 00:01:47,040 --> 00:01:50,720 単なる case 文ではないということです。 動的な case 文になっています。 33 00:01:50,880 --> 00:01:54,960 実際、メッセージ送信はロードされている クラスや生成されたインスタンスに依存します。 34 00:01:55,720 --> 00:01:58,640 Java でプログラムを書く時にはよく 35 00:01:58,800 --> 00:02:02,040 x.f() を書くことで 36 00:02:02,200 --> 00:02:04,080 メソッド f を実行します。 37 00:02:04,240 --> 00:02:07,240 ここで説明していることは、つまり このピリオド(.)は 38 00:02:08,000 --> 00:02:09,560 選択をおこなう演算子だということです。 39 00:02:10,840 --> 00:02:12,600 とても大事なことは 40 00:02:13,400 --> 00:02:15,360 この選択は動的だということです。 41 00:02:15,520 --> 00:02:17,800 これまであまり言ってきませんでしたが 42 00:02:17,960 --> 00:02:22,960 これこそが、例をもって示したかったことなのです。 43 00:02:23,120 --> 00:02:25,840 まとめると メッセージを送ることは 44 00:02:26,000 --> 00:02:29,360 動的な case 文のような機能を果たします。 45 00:02:29,520 --> 00:02:33,120 動的というのは ロードされているクラスに依存するという意味です。 46 00:02:33,280 --> 00:02:36,440 この真偽値の例題では 2つのインスタンスと2つのクラスを扱いました。 47 00:02:36,600 --> 00:02:39,600 たとえ50個だったとしても 同じように動きます。 48 00:02:40,320 --> 00:02:43,920 バーチャルマシンにメッセージを送ることで 49 00:02:44,080 --> 00:02:47,400 (Pharo は Java や C# のように  バーチャルマシンを使います) 50 00:02:47,560 --> 00:02:50,520 バーチャルマシンの実行装置が 51 00:02:50,680 --> 00:02:54,400 レシーバーのクラスに応じて 正しいメソッドを選択します。 52 00:02:54,560 --> 00:02:58,160 したがって、メッセージ送信は 選択演算子なのです。 53 00:02:58,320 --> 00:03:00,520 条件分岐を使うたびに 54 00:03:00,680 --> 00:03:04,360 それを 55 00:03:04,520 --> 00:03:07,920 バーチャルマシンによる選択に 置き換えることができます。 56 00:03:08,800 --> 00:03:11,400 つまり、not についての解答は 57 00:03:11,560 --> 00:03:13,560 プログラムを実装する時には 58 00:03:13,720 --> 00:03:17,240 バーチャルマシンによる選択を 使うべきだということです。 59 00:03:17,400 --> 00:03:19,720 if 文を使う必要はありません。 60 00:03:19,880 --> 00:03:24,240 なぜなら、メッセージを送ることが if や条件分岐と同じ意味になるのです。 61 00:03:24,400 --> 00:03:26,920 ここで疑問に思うかもしれません。 62 00:03:27,080 --> 00:03:31,160 最初の練習問題を全く別の方法で実装していたら どうなのだろうか?と。 63 00:03:31,320 --> 00:03:35,160 もし練習問題が「Boolean クラスに 64 00:03:35,320 --> 00:03:37,000 not や or を実装しなさい」だったら どうでしょう? 65 00:03:37,160 --> 00:03:39,400 今回の解答のやり方では うまくいかないでしょう。 66 00:03:40,200 --> 00:03:42,720 おかしいですね。 どういうことでしょうか? 67 00:03:42,880 --> 00:03:45,680 クラスが1つあるか複数あるかは アプリケーションの設計に 68 00:03:45,840 --> 00:03:48,400 とても大きな影響を与えます。 69 00:03:49,120 --> 00:03:50,120 まったくもって 70 00:03:51,440 --> 00:03:56,560 クラスは分岐や選択の役割を 担っているのです。 71 00:03:56,720 --> 00:03:59,080 ヨーグルトを選ぼうとしているとして 72 00:03:59,240 --> 00:04:03,200 店にヨーグルトのポットが1つしかなければ そのヨーグルトを選ぶしかないのです。 73 00:04:03,360 --> 00:04:04,400 そういうことなのです。 74 00:04:04,560 --> 00:04:06,520 つまり、クラスは 75 00:04:07,520 --> 00:04:09,440 継承木の中での1つの case を表しています。 76 00:04:09,600 --> 00:04:10,880 それが意味することは 77 00:04:11,040 --> 00:04:14,040 1つの大きく太ったクラスに メソッドが沢山あるような 78 00:04:14,200 --> 00:04:17,160 そんなデザインがあれば 79 00:04:17,320 --> 00:04:20,920 それと同じことを階層を使って表現できる ということです。 80 00:04:21,080 --> 00:04:25,280 そのほうが良い設計です。 よりモジュール化されています。 81 00:04:25,440 --> 00:04:29,680 必要ならば別の選択肢を加えることも 簡単にできます。 82 00:04:29,840 --> 00:04:32,760 「これは悪くないが 83 00:04:32,920 --> 00:04:35,960 新しい選択肢を持てるように改良できるね」 と言って拡張するのです。 84 00:04:36,120 --> 00:04:38,880 さらに複雑度を減らすことができます。 85 00:04:39,040 --> 00:04:43,840 1つのクラスに集中することができます。 あまりにも多くの条件を抱えたものではなく。 86 00:04:44,800 --> 00:04:49,000 片方の手には選択演算子があり 87 00:04:49,160 --> 00:04:52,640 もう一方の手には選択肢を表したものを持っています。 88 00:04:52,800 --> 00:04:57,640 それらをくっつけると 良い品質の OOP になります。 89 00:04:57,800 --> 00:05:00,040 さらに良いことに 90 00:05:00,200 --> 00:05:03,520 階層による解決を使うと 91 00:05:03,680 --> 00:05:07,120 それをパッケージ化することができます。 92 00:05:07,280 --> 00:05:11,480 つまり、ある部分はコアとしてパッケージして 別の部分をプラグインとしてパッケージできます。 93 00:05:11,640 --> 00:05:14,640 そして顧客に言うのです。 「この機能が必要であれば 94 00:05:14,800 --> 00:05:17,720 この有償プラグインをダウンロードしてください」 95 00:05:17,880 --> 00:05:20,360 そしてそのコードを動的にロードします。 96 00:05:20,520 --> 00:05:23,760 このクラスのインスタンスを生成すると 97 00:05:25,400 --> 00:05:27,840 オペレーションメッセージを送れば 98 00:05:28,520 --> 00:05:31,840 プラグインのコードがシステムの中で 実行されます。 99 00:05:32,000 --> 00:05:36,440 それが OOP のエッセンスです。 100 00:05:36,600 --> 00:05:40,120 メッセージを送ると 正しいメソッドが選択される 101 00:05:40,960 --> 00:05:45,040 そしてシステムが正しいメソッドを 選択することを知っていることで 102 00:05:45,200 --> 00:05:47,960 よりエレガントな実装をすることができます。 103 00:05:48,120 --> 00:05:50,320 何を学んだのでしょうか? 104 00:05:50,480 --> 00:05:55,040 学んだことは、メッセージを送ることで レシーバーに選択させて何かを決めさせることです。 105 00:05:55,200 --> 00:05:58,400 クライアントは何も決める必要ありません。 106 00:05:58,560 --> 00:06:00,760 クライアントコードは宣言的です。 107 00:06:00,920 --> 00:06:04,800 条件分岐はありません。命令を与えるのです。 「これをやれ」「あれをやれ」「開け」「閉じろ」と。 108 00:06:04,960 --> 00:06:09,280 「このクラスに属していますか?」や 「閉じられていますか?」ではなく。 109 00:06:09,440 --> 00:06:12,520 違いはレシーバーが動的に置き換えられる 可能性があることです。 110 00:06:12,680 --> 00:06:15,840 このことは後でまた出てきます。 ただし直接ではありません。暗黙に。 111 00:06:16,560 --> 00:06:20,240 そういうことで、多くの場合 if 文を書くことを避けるようにしてください。 112 00:06:21,240 --> 00:06:23,560 できるだけオブジェクトとメッセージを使うように。 113 00:06:23,720 --> 00:06:27,760 いつもそうだというわけではないですが 少なくともできるだけ使うようにしてください。 114 00:06:29,280 --> 00:06:31,880 実行エンジン バーチャルマシンは 115 00:06:32,040 --> 00:06:37,120 メッセージを送るたびに 条件スイッチとして動作します。 116 00:06:37,680 --> 00:06:39,000 それを使うことです。 117 00:06:39,160 --> 00:06:41,960 キーボードを打つ時はいつも アンチ if キャンペーンを楽しんでください。 118 00:06:42,120 --> 00:06:46,800 if 文を書くのをやめさせるために プログラマー達がこのキャンペーンを立ち上げました。 119 00:06:48,760 --> 00:06:50,960 さて、このセッションでは何を学んだでしょうか? 120 00:06:51,120 --> 00:06:53,280 2つのことがありました。 Java や Pharo で 121 00:06:53,440 --> 00:06:57,720 x.f() と書いたら 122 00:06:58,600 --> 00:07:02,400 選択肢を作ることになります。 123 00:07:02,560 --> 00:07:06,080 レシーバーに応じて実行されるべき メソッド f が選択されます。 124 00:07:06,840 --> 00:07:08,640 つまり選択演算子ということです。 125 00:07:08,800 --> 00:07:12,000 そして階層が可能な選択肢を表現します。 126 00:07:12,160 --> 00:07:16,560 つまりどんな選択が可能かを決める 枠組みだということです。 127 00:07:16,720 --> 00:07:20,800 結果として条件分岐のない 拡張性のあるプログラムを書くことができます。 128 00:07:21,800 --> 00:07:24,480 これで Pharo でのオブジェクト設計についての 129 00:07:24,640 --> 00:07:27,160 最初のセッションを終わります。 130 00:07:28,160 --> 00:07:30,520 次のセッションでもオブジェクト設計について さらに見ていきます。