1 00:00:01,910 --> 00:00:04,410 このビデオは本MOOCでの反復です。 2 00:00:04,577 --> 00:00:07,030 ここでの反復というのは 自分でやってみることです。 3 00:00:07,520 --> 00:00:09,540 ビデオを見て見たものを 1つ1つ実行することです。 4 00:00:10,060 --> 00:00:13,470 我々がプログラムする方法を見ることを お勧めする意味もあります。 5 00:00:13,720 --> 00:00:17,680 台本通りに忠実には進まないかもしれませんが 6 00:00:17,847 --> 00:00:20,060 できるだけ、そうしましょう。 しかしバグを見つけたり 7 00:00:20,227 --> 00:00:23,090 そんなことがあったら その都度対処しましょう。 8 00:00:24,870 --> 00:00:29,130 このビデオでは 簡単な言語をプログラムします。 9 00:00:29,297 --> 00:00:32,040 ロールプレイングゲームにあるような 感じの言語です。 10 00:00:32,207 --> 00:00:35,930 ダンジョンズ&ドラゴンズのような。 例えば 11 00:00:36,097 --> 00:00:38,800 この記述を手にした人は 12 00:00:38,967 --> 00:00:40,010 どういう風に読み取ったらいいのでしょう? 13 00:00:40,420 --> 00:00:45,380 こういう意味です。 2つの20面ダイスと1つの4面ダイスを振りなさい。 14 00:00:45,547 --> 00:00:47,420 これが Pharo の表現式になることが おわかりでしょうか。 15 00:00:48,000 --> 00:00:52,490 つまり、このビデオでは 16 00:00:52,657 --> 00:00:55,170 ダイスを表現するクラスと 17 00:00:55,337 --> 00:00:57,420 ダイスのハンドルを表現するクラスを 実装します。 18 00:00:58,660 --> 00:00:59,770 では始めましょう。 19 00:01:00,870 --> 00:01:04,290 始めに、パッケージを定義します。 20 00:01:05,710 --> 00:01:06,790 Dice と呼ぶことにします。 21 00:01:06,957 --> 00:01:11,860 他のものは見たくないので 22 00:01:12,027 --> 00:01:16,660 このビデオでは 23 00:01:16,827 --> 00:01:19,450 コードをデバッガーで書くやり方は しないつもりです。 24 00:01:19,617 --> 00:01:22,210 ほかのビデオでお見せした方法ですが 25 00:01:22,377 --> 00:01:24,410 ケースバイケースで、そうすべき機会があれば そうすることもあるでしょう。 26 00:01:25,490 --> 00:01:30,030 ここで、Die クラスを定義します。 27 00:01:30,197 --> 00:01:31,370 面の数 faces を持っています。 28 00:01:32,100 --> 00:01:35,630 コンパイルします。 クラスコメントを追加します。 29 00:01:43,380 --> 00:01:45,890 当面は大したことはありません。 とてもとても単純なものですから。 30 00:01:47,550 --> 00:01:52,360 このオブジェクトの初期化を 31 00:01:52,527 --> 00:01:53,950 作る作業を始めてみましょう。 32 00:02:00,450 --> 00:02:02,260 こんな風にやります。 33 00:02:10,190 --> 00:02:13,560 スーパークラスの初期化を呼んで 34 00:02:13,727 --> 00:02:18,140 面の数のデフォルト値として6を代入します。 35 00:02:18,307 --> 00:02:19,140 それが最も一般的なダイスなので。 36 00:02:19,820 --> 00:02:22,530 ここでテストクラスを作り始めます。 37 00:02:22,697 --> 00:02:25,640 一旦作ったものを 38 00:02:25,807 --> 00:02:26,900 壊してしまわないようにするためです。 39 00:02:27,260 --> 00:02:30,450 テストクラスは TestCaseクラスのサブクラスです。 40 00:02:30,617 --> 00:02:34,100 DieTest クラスとします。 41 00:02:34,370 --> 00:02:37,510 これでテストクラスができました。 42 00:02:37,790 --> 00:02:40,220 最初にやるべきテストの1つとして 43 00:02:40,387 --> 00:02:42,480 いつもそうする必要はありませんが 44 00:02:42,647 --> 00:02:46,650 ちゃんと動くテストから始めたいのです。 45 00:02:47,840 --> 00:02:52,120 今の所、あまり多くのものはないので 初期化はOKだと言いたいです。 46 00:02:53,820 --> 00:02:56,160 ここでお見せするのは 47 00:02:56,327 --> 00:02:59,770 例外が出てくることを確認するテストや 48 00:02:59,937 --> 00:03:01,440 例外が出ないことを確認するテストの 例にもなっています。 49 00:03:02,180 --> 00:03:04,590 では書いてみます。 50 00:03:04,757 --> 00:03:06,460 Die new は Error を投げてはいけない。 51 00:03:18,120 --> 00:03:19,170 どういう意味でしょう? 52 00:03:19,337 --> 00:03:23,290 「Die new というコードを実行した時に 53 00:03:23,457 --> 00:03:25,600 エラーが発生してはいけない」 という意味です。 54 00:03:28,170 --> 00:03:32,560 このテストを分類して実行します。 55 00:03:32,727 --> 00:03:35,550 グリーンです。ばっちりです。 56 00:03:36,000 --> 00:03:40,020 ではここで 57 00:03:40,187 --> 00:03:44,540 ダイスを振るメソッドを定義します。 58 00:03:44,707 --> 00:03:48,610 Pharo には 59 00:03:48,777 --> 00:03:49,720 atRandom というメソッドがあります。 60 00:03:49,887 --> 00:03:53,940 atRandomは何をするのでしょうか? 61 00:03:54,480 --> 00:03:57,780 そのメソッドの機能は…そうですね 62 00:03:58,310 --> 00:04:00,770 実装を見て確認してみましょう。 63 00:04:00,937 --> 00:04:03,620 atRandomは何をするのでしょう? 64 00:04:04,870 --> 00:04:09,070 それは 1 から self までの ランダムな整数を返します。ピッタリですね。 65 00:04:10,910 --> 00:04:13,910 なので、新しいメソッドを 66 00:04:15,290 --> 00:04:19,220 operationsに定義します。 67 00:04:21,160 --> 00:04:22,230 何をしましょうか? 68 00:04:22,397 --> 00:04:26,640 roll(転がす)です。 69 00:04:27,570 --> 00:04:28,203 「ランダムな出目を返す」ということです。 70 00:04:35,750 --> 00:04:37,400 そこでこのメソッドのテストを書きます。 71 00:04:40,490 --> 00:04:43,590 testRolling 何をするのでしょう? 72 00:04:44,120 --> 00:04:49,040 ダイスを作ります。 73 00:04:49,207 --> 00:04:49,840 d:= Die new 74 00:04:51,210 --> 00:04:53,140 そして 1000 timesRepeat: 75 00:04:54,420 --> 00:04:58,240 何を? d roll 76 00:05:03,620 --> 00:05:07,580 そしてこれが 1 から 6 の間であってほしいのです。 77 00:05:07,747 --> 00:05:12,640 between: and: いいですね。 78 00:05:12,807 --> 00:05:15,560 between: 1 and: 6 79 00:05:15,820 --> 00:05:18,510 これはあまり良くないです。 というのも、ここでは 80 00:05:18,677 --> 00:05:22,470 6面ダイスのテストしか書いていません。 81 00:05:22,637 --> 00:05:25,310 ダイスの面の数に従って動くべきです。 82 00:05:25,640 --> 00:05:26,580 それは後回しにしましょう。 83 00:05:26,830 --> 00:05:27,463 なのでコンパイルします。 84 00:05:32,840 --> 00:05:35,620 エラーになりました。こうです。 85 00:05:37,910 --> 00:05:39,170 これでテストができました。 86 00:05:39,337 --> 00:05:41,460 ここで保存しましょう。 Dice パッケージがあるので 87 00:05:41,627 --> 00:05:44,590 ローカルに保存します。 Save です。 88 00:05:44,757 --> 00:05:49,000 練習で他のものをいくつか作ったので 89 00:05:49,167 --> 00:05:51,710 新しいものを作ります。 「新しいバージョン 90 00:05:56,530 --> 00:06:00,780 ダイスを振るのとテスト」 これで良し、と。 91 00:06:01,030 --> 00:06:02,370 はい、これで保存されました。 92 00:06:11,480 --> 00:06:14,610 ここで、インスタンス生成の インターフェイスを変えようと思います。 93 00:06:14,777 --> 00:06:18,890 まずはカテゴリーを整理します。 94 00:06:19,810 --> 00:06:22,200 インスタンス生成を少し変えたい。 95 00:06:22,367 --> 00:06:26,390 ダイスを作るときに 96 00:06:26,557 --> 00:06:28,090 面の数をつかいたい。 97 00:06:39,290 --> 00:06:42,610 もう解ったはずですが この式の中で 98 00:06:42,777 --> 00:06:46,030 faces は Die クラスへ 送られたメッセージであって 99 00:06:46,197 --> 00:06:48,610 Die クラスのインスタンスへの メッセージでははありません。 100 00:06:49,090 --> 00:06:51,880 インスタンスへのメッセージは今のところ roll メソッドかまたは別のクラスのメソッドだけです。 101 00:06:52,047 --> 00:06:55,040 これで理解してほしいのは 102 00:06:55,207 --> 00:06:58,900 いつクラスレベルへ行くべきか、あるいは 行くべきでないか、ということです。 103 00:06:59,350 --> 00:07:00,710 まずはテストを書きましょう。 104 00:07:03,050 --> 00:07:06,420 betterInterface 105 00:07:08,790 --> 00:07:10,200 同じロジックで続けると 106 00:07:12,230 --> 00:07:18,080 testBetterCreationInterface 107 00:07:18,247 --> 00:07:20,950 ここで例えばこんなことをしたいのです。 108 00:07:22,680 --> 00:07:23,640 そしてこれは faces です。 109 00:07:30,620 --> 00:07:32,420 ゆっくりやります。 110 00:07:32,950 --> 00:07:36,840 ここに行ってinstance creation と入力して faces: anInteger 111 00:07:46,560 --> 00:07:49,000 短く書くこともできますが ここでは 112 00:07:49,167 --> 00:07:50,530 「穏やかな」やり方をします。 113 00:07:51,000 --> 00:07:52,940 ダイスを作ります。 114 00:07:53,890 --> 00:07:57,740 self new と書きます。 ここでの self は Die クラス自身です。 115 00:07:58,220 --> 00:08:00,410 インスタンスを作る と伝えます。 116 00:08:00,577 --> 00:08:03,620 そして このインスタンスに対して 117 00:08:03,787 --> 00:08:08,410 アクセサーを使って 引数として渡された値を代入します。 118 00:08:08,577 --> 00:08:12,130 当然、今まさに作ったダイスを返します。 119 00:08:13,860 --> 00:08:16,920 このコードが実行して ちゃんと動きません。 120 00:08:17,087 --> 00:08:19,950 faces はまだ存在していないからです。 なので心配しなくていいです。 121 00:08:20,117 --> 00:08:22,760 テストが OK ではないですが 122 00:08:22,927 --> 00:08:27,720 正常なことです。これを実行すれば execute this 123 00:08:27,887 --> 00:08:29,520 例えば、デバッグして見てみれば 124 00:08:33,640 --> 00:08:38,360 Over をクリックすると 125 00:08:38,527 --> 00:08:41,430 faces というメッセージがわからない と言ってきます。 126 00:08:41,910 --> 00:08:45,770 ここでは「穏やかな」やり方でいくので デバッガではやりません。 127 00:08:46,830 --> 00:08:49,600 その通りで アクセサーを追加する必要があります。 128 00:08:52,910 --> 00:08:57,390 faces: anInteger と書いて 129 00:08:57,557 --> 00:09:01,520 faces := anInteger と書きます。 130 00:09:05,020 --> 00:09:08,110 ついでに読み出しのアクセサーを書きます。 131 00:09:09,330 --> 00:09:11,500 これを返します。 132 00:09:13,250 --> 00:09:14,450 これでテストはグリーンです。 133 00:09:15,240 --> 00:09:19,180 なので保存します。 save 134 00:09:19,347 --> 00:09:22,250 ダイスのより良い生成メソッドと テスト 135 00:09:22,417 --> 00:09:23,050 よしと。 136 00:09:31,610 --> 00:09:33,670 これで 137 00:09:33,837 --> 00:09:37,650 ダイスハンドルの定義を 始めることができます。 138 00:09:38,690 --> 00:09:42,050 ダイスハンドルについて 139 00:09:42,217 --> 00:09:44,000 どんな風に書きたいでしょうか? 140 00:09:44,167 --> 00:09:45,450 DiceHandle new addDie: みたいに書きたいと思います。 141 00:09:49,300 --> 00:09:53,290 そして新しいダイスを作るわけです。 die faces: 6; addDie: 142 00:09:55,210 --> 00:09:59,680 Die faces: 10 143 00:10:07,260 --> 00:10:12,040 今回は 144 00:10:12,207 --> 00:10:13,580 テストクラスから書き始めたいと思います。 145 00:10:15,250 --> 00:10:19,930 なので TestCase から継承した新しいクラスです。 146 00:10:20,290 --> 00:10:22,330 よし。 新しいテストクラスができました。 147 00:10:24,000 --> 00:10:26,730 そしてテストを定義します。 148 00:10:30,220 --> 00:10:32,850 ハンドルを作って 149 00:10:33,017 --> 00:10:35,140 正しいダイスが入っているか チェックします。 150 00:10:35,307 --> 00:10:39,380 testAdding コードを再利用します。 151 00:10:39,547 --> 00:10:43,730 そうしない理由はないですよね。 152 00:10:45,530 --> 00:10:48,060 なのでここで 153 00:10:54,310 --> 00:10:58,940 handle さらに yourself 154 00:10:59,107 --> 00:11:01,960 メッセージレシーバーが欲しいので。 つまりハンドルであって 155 00:11:02,127 --> 00:11:03,690 渡した引数ではなく。 156 00:11:04,500 --> 00:11:08,260 さあ、何をしたらいいでしょう? 157 00:11:08,427 --> 00:11:12,520 self assert: [h diceNumber 158 00:11:13,960 --> 00:11:14,593 equals 2 159 00:11:20,700 --> 00:11:23,380 コンパイルします。 明らかなことですが、システムが 160 00:11:23,547 --> 00:11:25,930 変数 DiceHandle を知らないと言っています。 161 00:11:26,097 --> 00:11:26,730 そういうクラスが欲しいのですか?と。 162 00:11:26,897 --> 00:11:27,960 はい、クラスです。 163 00:11:28,560 --> 00:11:29,750 これで定義されます。 164 00:11:29,917 --> 00:11:31,340 いずれダイスを持たないといけないことは もう分かっていることなので 165 00:11:31,507 --> 00:11:36,440 ちょうどいい機会なので 166 00:11:36,870 --> 00:11:39,580 ここでインスタンス変数を入れます。 167 00:11:39,747 --> 00:11:40,860 これをコンパイルします。 168 00:11:41,790 --> 00:11:45,720 これで(テストは)レッドです。 addDie: が定義されていないからです。 169 00:11:47,620 --> 00:11:48,570 なので定義しましょう。 170 00:11:48,737 --> 00:11:51,620 その前に ハンドルを初期化しておいたほうがいいですね。 171 00:11:54,240 --> 00:11:56,660 こんな風にします。 172 00:11:56,827 --> 00:11:57,890 後々のバグを予防できます。 173 00:12:02,890 --> 00:12:04,560 dice : = OrderedCollection new. 174 00:12:04,727 --> 00:12:05,360 Recategorize(分類し直し) 175 00:12:21,880 --> 00:12:24,760 そして、これでテストできるはずです。 176 00:12:24,927 --> 00:12:27,730 で、クラッシュします。 はいはい、大丈夫です。 177 00:12:27,897 --> 00:12:30,200 addDie: を作ります。 178 00:12:30,530 --> 00:12:31,163 adding です。 179 00:12:35,330 --> 00:12:38,030 このメソッドを実装しなければならない と言ってきます。 180 00:12:38,197 --> 00:12:39,080 まあその通りです。 181 00:12:39,247 --> 00:12:42,430 dice add: aDie と書きます。 182 00:12:43,590 --> 00:12:45,920 はい、ばっちりです。 テストはまだ動きません。 183 00:12:46,087 --> 00:12:48,150 diceNumberをまだ定義していないからです。 184 00:12:48,317 --> 00:12:52,120 では定義しましょう。 はい、diceNumber です。 185 00:12:52,287 --> 00:12:56,780 今回は accessing に定義します。 186 00:12:57,350 --> 00:12:58,800 そして diceNumber ですが 何をしましょうか? 187 00:12:58,967 --> 00:13:00,330 返さないといけないのは 188 00:13:06,290 --> 00:13:08,110 ダイスの個数です。またコンパイルします。 テストを進めるとグリーンになるはずです。 189 00:13:09,940 --> 00:13:12,510 テストはグリーンになったので 190 00:13:12,677 --> 00:13:14,860 保存します。 191 00:13:17,250 --> 00:13:18,580 addDie とテスト。 192 00:13:24,560 --> 00:13:28,090 テストを改良することもできます。 193 00:13:28,257 --> 00:13:31,900 ここでは 2つのダイスをくわえていますが 194 00:13:32,067 --> 00:13:35,180 同じダイスを2回追加しても 195 00:13:35,347 --> 00:13:37,610 大丈夫かチェックします。 196 00:13:38,280 --> 00:13:39,340 testAddingTwiceTheSameDieIsOK と。 197 00:13:49,040 --> 00:13:50,290 ここで何をしましょう? 198 00:13:50,457 --> 00:13:54,530 6面ダイスと6面ダイスを足したら ダイスは2つになるはずです。 199 00:13:57,030 --> 00:13:59,940 これでテストを実行します。 グリーンです。素晴らしい。 200 00:14:01,230 --> 00:14:04,700 さて、ここで 201 00:14:05,880 --> 00:14:08,960 2 つのダイスを追加することを定義できたら 202 00:14:11,240 --> 00:14:14,900 よいのですが、その前に やっておくことがあります。 203 00:14:15,067 --> 00:14:17,210 見てください。気に入らないのは 204 00:14:17,377 --> 00:14:19,030 例えばこれをインスペクトすると 205 00:14:23,950 --> 00:14:28,740 ダイスの中身がわかりません。 206 00:14:28,907 --> 00:14:31,530 それでデバッグするのは実践的ではないですね。 207 00:14:31,697 --> 00:14:33,030 デバッガーではこれが見えないのです。 208 00:14:33,370 --> 00:14:36,090 なので、先に進める前に これを改良しておきたいのです。 209 00:14:36,257 --> 00:14:38,370 printing プロトコルに メソッドを追加します。 210 00:14:38,660 --> 00:14:41,710 printOn: メソッドです。 211 00:14:44,220 --> 00:14:46,840 システムの全てのオブジェクトに 定義されているメソッドで 212 00:14:47,007 --> 00:14:50,380 オブジェクトを 213 00:14:50,547 --> 00:14:53,490 テキスト表現に変換して 214 00:14:55,380 --> 00:14:58,780 ストリームに渡します。 215 00:14:58,947 --> 00:15:00,420 今回は表現をより詳細にします。 216 00:15:01,890 --> 00:15:03,500 こうすると何もしないのと同じです。 217 00:15:03,667 --> 00:15:07,630 super printOn: をすると 前と何も変わりません。 218 00:15:07,797 --> 00:15:09,230 そしてさらに 219 00:15:09,397 --> 00:15:13,220 aStream nextPutAll: で文字をストリームに入れていきます。 put characters in the 220 00:15:13,387 --> 00:15:15,220 まず何を入れましょう? 221 00:15:16,090 --> 00:15:18,330 空白と括弧を書きます。 222 00:15:18,497 --> 00:15:19,880 このほうが良い感じでしょう。 223 00:15:20,450 --> 00:15:23,550 そして faces をどうするかですが 224 00:15:23,717 --> 00:15:27,780 数値を文字列に変換して 全部を連結して 225 00:15:28,360 --> 00:15:30,760 括弧を閉じます。 226 00:15:31,150 --> 00:15:34,930 こうして、インスペクターを閉じて もう一度開きます。 227 00:15:35,850 --> 00:15:38,630 6面ダイスと 228 00:15:38,797 --> 00:15:40,480 10面ダイスがあります。 much 229 00:15:40,647 --> 00:15:44,140 見ての通り、前よりも良いです。 バグが出てきた時に、きっと手助けになるでしょう。 230 00:15:44,850 --> 00:15:48,140 大したことは何もしていないので テストは動いています。 231 00:15:49,450 --> 00:15:53,340 また保存します。大した手間ではありません。 表示、と。 232 00:15:55,220 --> 00:15:56,400 Die の printOn: と。 233 00:16:03,030 --> 00:16:08,000 これでよし。ではテストを作りましょう。 234 00:16:08,167 --> 00:16:09,580 いや、テストを作るのではなく 直接やりましょう。 235 00:16:10,080 --> 00:16:12,490 operations プロトコルで 236 00:16:13,600 --> 00:16:17,890 さて 237 00:16:18,057 --> 00:16:22,530 これを定義する方法はいくつかあります。 238 00:16:22,820 --> 00:16:25,040 そのうち1つをお見せします。 一番良い方法というわけではありませんが 239 00:16:25,207 --> 00:16:27,160 おそらく一番解りやすい方法です。 240 00:16:27,530 --> 00:16:29,130 コンパクトに 241 00:16:29,297 --> 00:16:31,490 1行で書くこともできますが 242 00:16:31,657 --> 00:16:33,150 inject:into:のようなイテレーターを使います。 今回はループを使います。 243 00:16:33,550 --> 00:16:34,210 では何をしましょうか? 244 00:16:34,377 --> 00:16:36,860 0 で初期化された変数を使って 245 00:16:37,390 --> 00:16:42,320 全てのダイスについてループして 246 00:16:42,487 --> 00:16:47,120 ループのそれぞれの周回で ダイスを取り出して 247 00:16:47,287 --> 00:16:47,920 このダイスで何をしましょう? 248 00:16:48,120 --> 00:16:51,900 ダイスを振って 結果を変数に 249 00:16:52,067 --> 00:16:53,440 足していきます。 250 00:16:55,640 --> 00:17:00,310 何も大したことのないですが とても、とても明示的です。 251 00:17:02,000 --> 00:17:05,380 ここでインスペクトして 252 00:17:05,547 --> 00:17:10,510 roll します。5 です。 これだけでは動いている証明にはなりません。 253 00:17:11,210 --> 00:17:12,140 もう一度やってみます。 254 00:17:12,307 --> 00:17:13,140 11 です。いいでしょう、動いています。 255 00:17:13,950 --> 00:17:16,120 テストを書いてみます。 256 00:17:16,287 --> 00:17:19,920 そうしない理由はないので テストします。 257 00:17:21,590 --> 00:17:22,940 これを使って ここは Rolling としましょう。 258 00:17:26,960 --> 00:17:30,940 では、これをどうテストしましょうか? 259 00:17:31,107 --> 00:17:35,760 1からダイスの最大値の間のはずです。 It has to be between one and the maximum of the number of dice. 260 00:17:38,000 --> 00:17:42,100 なので、こうしましょう。 So we will do this. 261 00:17:42,267 --> 00:17:42,900 これをする We 262 00:17:48,280 --> 00:17:49,930 メソッドを定義できますね。 could define a method doing this. 263 00:17:50,240 --> 00:17:53,040 最大値を求めるメソッドを作りましょう。 Let's create a method defining the maximum. 264 00:17:56,720 --> 00:18:00,100 operations の maxValue です。 "Operation maxValue". 265 00:18:02,480 --> 00:18:03,240 最大値とは何でしょう? 266 00:18:03,407 --> 00:18:05,020 これに似ているはずです。 It is very close to this. 267 00:18:05,780 --> 00:18:10,000 ここではダイスを「振る」かわりに 268 00:18:11,440 --> 00:18:12,430 面の数を訊きます。 I will ask for the faces. 269 00:18:16,560 --> 00:18:20,490 ではチェックしてみましょう。 インスペクトして Let's check. If I do "Inspect", there 270 00:18:21,830 --> 00:18:24,820 maxValue します。16 です。 I do "maxValue", "16". 271 00:18:28,490 --> 00:18:30,480 はい、10 と 6 なので正しいです。 Yes, it's right 10 and 6. 272 00:18:30,647 --> 00:18:33,090 では maxVallue のテストを書きましょう。 273 00:18:37,010 --> 00:18:41,600 これを使って maxValue は 274 00:18:41,767 --> 00:18:42,400 16 になるはずです。 275 00:18:45,320 --> 00:18:48,150 見ての通り テストではとても汚いコードを書きましたが 276 00:18:48,317 --> 00:18:51,320 最終的には 277 00:18:51,487 --> 00:18:53,690 メソッドを書いて使った方が良いです。 278 00:18:54,080 --> 00:18:58,370 ではここで roll メソッドのテストに戻ります。 279 00:18:58,820 --> 00:19:02,340 roll をします。 280 00:19:05,900 --> 00:19:08,770 そしてその結果は 281 00:19:08,937 --> 00:19:11,000 1 から h maxValue の間 282 00:19:14,230 --> 00:19:15,690 でなければなりません。 283 00:19:24,080 --> 00:19:26,000 実行すると、はい、動きます。 284 00:19:28,120 --> 00:19:30,870 あまり統計的な根拠はないですが This is not very statistical, so here we could do 285 00:19:31,037 --> 00:19:35,800 something like 1000 timesRepeat: のようなこともできます。 286 00:19:36,000 --> 00:19:38,560 オッケーです。これで 287 00:19:42,220 --> 00:19:46,680 1000回テストができました。 288 00:19:47,740 --> 00:19:49,330 では保存します。素晴らしい。 289 00:19:49,497 --> 00:19:52,440 maxValue と 290 00:19:54,610 --> 00:19:56,030 rollとテストを追加。 291 00:20:03,940 --> 00:20:08,380 これでほとんど完成です。 292 00:20:08,547 --> 00:20:11,070 表現として 293 00:20:11,237 --> 00:20:13,680 Die faces: 6 ではなく 294 00:20:16,290 --> 00:20:17,670 1 D6 のように表現したいと思います。 295 00:20:17,837 --> 00:20:18,470 そして 296 00:20:25,510 --> 00:20:27,630 これは詰まるところ 297 00:20:27,797 --> 00:20:31,050 整数オブジェクトにメッセージ D6 を送る ということです。 298 00:20:31,770 --> 00:20:34,540 なので、Integerクラスを見てみましょう。 299 00:20:34,707 --> 00:20:39,620 これからやろうとしていることは 300 00:20:39,787 --> 00:20:43,660 クラスへの拡張を定義することです。 301 00:20:43,827 --> 00:20:45,010 クラスへの拡張とは? 302 00:20:45,890 --> 00:20:50,350 メソッドをパッケージと同じ名前で パッケージングするのですが 303 00:20:50,800 --> 00:20:53,360 これからお見せします。 304 00:20:53,527 --> 00:20:57,420 プロトコルを追加します。 先頭に * を付けます。 305 00:20:57,587 --> 00:21:00,780 *Dice とすることで 灰色の表示になります。 306 00:21:00,947 --> 00:21:02,900 これはこのメソッドは このパッケージといっしょに 307 00:21:03,067 --> 00:21:04,460 パッケージされるということです。 やってみましょう。 308 00:21:04,900 --> 00:21:08,950 想像してみましょう。 D6とは何でしょう? 309 00:21:10,000 --> 00:21:13,570 D6... ちょっと考えなければなりません。 310 00:21:21,050 --> 00:21:24,250 まずはハンドルを作ります。 311 00:21:24,417 --> 00:21:25,510 2 D6 とかの場合もありますから。 312 00:21:27,210 --> 00:21:31,930 なので、handle と。 313 00:21:32,097 --> 00:21:32,730 DiceHandle new 314 00:21:37,120 --> 00:21:38,280 はい、これでできました。 315 00:21:39,380 --> 00:21:42,110 これで、レシーバー回数ということで I will do 316 00:21:42,277 --> 00:21:45,430 self つまり自分の整数で timesRepeat: 317 00:21:46,370 --> 00:21:50,140 timesRepeat: を本当に多く使いましたが こんなことは珍しいです。 318 00:21:51,900 --> 00:21:54,120 timesRepeat: [handle addDie: で、何でしょう。 319 00:21:56,790 --> 00:22:01,150 Die faces: そして 320 00:22:02,000 --> 00:22:03,720 6 ですよね。 321 00:22:05,890 --> 00:22:09,830 これでハンドルを返せば良さそうですね。 322 00:22:11,220 --> 00:22:12,330 さあ動くでしょうか? 323 00:22:12,497 --> 00:22:14,950 こんな風にテストをして テストを書きます。 324 00:22:15,470 --> 00:22:20,380 しかし 2 D6 インスペクトすると、ほら 325 00:22:20,547 --> 00:22:22,390 2つの D6 が得られます。すごい。 326 00:22:23,190 --> 00:22:24,290 テストを書きましょう。 327 00:22:25,640 --> 00:22:27,140 これらのテストを分類しておきます。 328 00:22:28,150 --> 00:22:29,330 testNewSyntax と書きます。 329 00:22:33,950 --> 00:22:36,420 ここで今は D6 しかありません。 後で一般化します。 330 00:22:38,010 --> 00:22:40,000 これと全く同じことをしたいわけです。 331 00:22:40,167 --> 00:22:44,440 そしてハンドルが得られるはず。 では、2 D6 として 332 00:22:47,020 --> 00:22:49,620 self assert: と。 333 00:22:53,310 --> 00:22:54,430 何をテストしましょう? 334 00:22:54,597 --> 00:22:56,470 diceNumber は 2 のはずです。 335 00:23:02,880 --> 00:23:05,420 お気付きかもしれませんが 336 00:23:05,587 --> 00:23:09,160 ここは = 2 とすることもできます。 337 00:23:09,810 --> 00:23:12,080 一般には、assert:equals: を使う方が良いです。 338 00:23:12,540 --> 00:23:14,310 というのも、このように エラーになった時に 339 00:23:14,477 --> 00:23:18,020 「これを期待していたのに、これが得られた」 とシステムが言ってくれます。 340 00:23:18,630 --> 00:23:22,910 = を使うと、システムは 「間違ってます」としか言えません。 341 00:23:23,680 --> 00:23:26,480 この場合には 342 00:23:26,647 --> 00:23:28,850 開発者としてはassert:equals:を使った方が 良いです。 343 00:23:30,580 --> 00:23:33,340 「2 を期待していましたが、3 が得られました」 344 00:23:33,560 --> 00:23:34,680 のようになるので。 345 00:23:35,860 --> 00:23:37,060 ここは、こうします。 346 00:23:37,510 --> 00:23:38,780 はい、動きました。 347 00:23:39,320 --> 00:23:41,940 もっと賢い方法で 348 00:23:42,107 --> 00:23:43,090 このテストができるでしょうか? 349 00:23:43,257 --> 00:23:44,240 今のところ、これで十分です。 350 00:23:44,860 --> 00:23:46,640 今、このパッケージには 351 00:23:46,807 --> 00:23:50,200 D6 という拡張があることがわかります。 352 00:23:50,690 --> 00:23:55,480 これを後で一般化して with 353 00:23:56,120 --> 00:23:57,550 D: aNumberOfFaces とします。 354 00:24:01,360 --> 00:24:03,870 ここが aNumberOfFaces になります。 355 00:24:05,200 --> 00:24:08,000 そして D6 を書き直します。 356 00:24:08,137 --> 00:24:12,580 D6 をこんな風に書きます。 このほうが良いです。 357 00:24:12,747 --> 00:24:16,660 self D: 6 を返します。 358 00:24:19,050 --> 00:24:20,750 他もやってしまいます。 359 00:24:20,917 --> 00:24:24,370 D4 360 00:24:26,020 --> 00:24:30,870 D2。 ダイスというよりコインですね。 361 00:24:31,220 --> 00:24:35,640 D10 と D20. 362 00:24:36,440 --> 00:24:37,570 これが原則です。 363 00:24:41,540 --> 00:24:45,930 ではテストを走らせましょう。 実装を変更したのですから。 364 00:24:47,010 --> 00:24:49,370 2 D6... 動いています。 365 00:24:49,830 --> 00:24:50,690 では保存しましょう。 366 00:24:59,670 --> 00:25:03,320 やり残したことはあるでしょうか? 367 00:25:03,680 --> 00:25:08,030 あります。 ハンドル同士を足し合わせることです。 368 00:25:09,300 --> 00:25:11,600 何をテストしましょうか? 369 00:25:11,767 --> 00:25:14,640 今回確認したいのは ハンドルを足すことなので 370 00:25:18,710 --> 00:25:23,240 testAddingHandles 371 00:25:23,407 --> 00:25:25,590 (ここで新しい表現を使うことができるのは 372 00:25:25,757 --> 00:25:26,440 良いですね) 373 00:25:26,960 --> 00:25:28,940 テストしたいことは 374 00:25:29,107 --> 00:25:33,820 2 D20 + 3 D5 375 00:25:34,000 --> 00:25:38,570 いや、3 D6 にしましょう。 (問題を複雑にしないようにしましょう) 376 00:25:38,737 --> 00:25:42,050 いくつあるでしょうか? 377 00:25:43,160 --> 00:25:46,770 diceNumber は 5 のはずです。 378 00:25:48,180 --> 00:25:52,270 ここで、+ 演算子を定義しなければなりませんね。 379 00:25:52,870 --> 00:25:55,520 Pharo では、+ は演算子ではありません。 単なるメッセージです。 380 00:25:55,687 --> 00:25:59,230 なので DiceHandle クラスにメッセージを定義します。 381 00:26:00,530 --> 00:26:02,850 + と書きます。 382 00:26:04,650 --> 00:26:05,520 で、 aDiceHandle です。 383 00:26:07,530 --> 00:26:09,410 ここで考えてみましょう。 384 00:26:09,577 --> 00:26:11,770 レシーバー(ハンドル)を書き変える方法と 385 00:26:11,937 --> 00:26:12,840 関数的な方法があります。 386 00:26:13,130 --> 00:26:14,740 関数的な方法のほうが好みです。 387 00:26:14,907 --> 00:26:17,470 関数的な方法では新しいハンドルを作ります。 388 00:26:20,180 --> 00:26:23,690 そこで新しいハンドルを作ります。 389 00:26:26,060 --> 00:26:27,650 handle := self class new 390 00:26:29,540 --> 00:26:34,060 ここでは DiceHandle と書くのを避けました。 391 00:26:34,227 --> 00:26:36,360 後でその理由を説明するレッスンがあります。 392 00:26:36,527 --> 00:26:37,770 それほど先ではありません。 393 00:26:37,937 --> 00:26:39,800 一般的に、クラス名をハードコードすべきではない ということです。 394 00:26:40,430 --> 00:26:42,530 第7週かその辺りで 395 00:26:42,697 --> 00:26:44,040 きちんと説明します。 396 00:26:44,740 --> 00:26:49,660 self dice do: とすると 397 00:26:49,827 --> 00:26:53,480 自分が持つダイスを列挙します。 そしてそれをハンドルに加えていきます。 398 00:26:53,647 --> 00:26:55,610 handle addDie: each 399 00:26:59,780 --> 00:27:03,660 そして同じことをします。 400 00:27:03,827 --> 00:27:05,720 こちらでは self ではなく… 401 00:27:05,887 --> 00:27:07,420 ああ、このメッセージはわかりませんね。 システムがそう言っています。 402 00:27:07,587 --> 00:27:09,370 それで気付いたのですが まだ定義していません。 403 00:27:09,820 --> 00:27:12,790 なので diceHandle にも動かないわけですが 404 00:27:15,630 --> 00:27:20,480 とりあえず、まずはコンパイルしてしまって 後で直しましょう。 405 00:27:21,230 --> 00:27:22,450 どういうことかというと 406 00:27:22,617 --> 00:27:24,790 アクセサーが足りません。diceです。 407 00:27:25,280 --> 00:27:28,770 なのでここで dice を書きましょう。 408 00:27:28,937 --> 00:27:32,060 dice は 自分のダイスのコレクションを返します。 409 00:27:32,227 --> 00:27:35,280 これでテストしてみます。 410 00:27:35,700 --> 00:27:38,690 テストは大丈夫です。素晴らしい。 完成が近いということです。 411 00:27:38,857 --> 00:27:43,610 保存します。 ハンドル同士の足し算 412 00:27:44,810 --> 00:27:46,690 はい、オッケーです。 413 00:27:49,820 --> 00:27:53,770 つまりこれで 414 00:27:57,300 --> 00:28:02,210 2 D4 と書いて 415 00:28:02,377 --> 00:28:06,380 roll つまり振ることができます。 そして数が返ってきます。 416 00:28:08,000 --> 00:28:10,400 さあ、これでダンジョンズ&ドラゴンズを プレーすることができます。 417 00:28:11,200 --> 00:28:15,870 ここまでやったことは 418 00:28:17,570 --> 00:28:19,480 メソッドを書いて テストを書いて 419 00:28:19,647 --> 00:28:23,010 テストを走らせて システムクラスを拡張しました。 420 00:28:23,177 --> 00:28:27,000 Integerクラスにこのパッケージにリンクした 拡張をつけることで 421 00:28:27,167 --> 00:28:30,590 このパッケージがロードされた時のみ 見えます。 422 00:28:32,290 --> 00:28:34,580 そして演算子のオーバーロードもしました。 423 00:28:34,747 --> 00:28:39,320 実際には単に + メッセージの 新しい定義をしただけです。 424 00:28:39,487 --> 00:28:43,600 Pharo では足し算は単なるメッセージなので。 425 00:28:43,767 --> 00:28:48,160 これによって良い感じのDSLで 記述できるようになりました。 426 00:28:49,900 --> 00:28:50,850 さあ、あなたがコードを書く番です!