CodingDOJO
Clean Coder でググッてたら CodingDOJO なるソレがあるらしいことを知る。プロのプログラマになるための必読書「Clean Coder」というエントリによれば
ボブおじさんはコーディング道場(Coding Dojo)という名前でボウリングゲームのTDDを何回も、何年も実演しているらしい。これで、プログラミングがめちゃくちゃ上達したらしい。
空手でいうところの型らしい。ウォームアップというか、基本というか。そんな感じ。
プロのプログラマになるための必読書「Clean Coder」より引用
との記述がある。型ッスか。てことで CodingDOJO が以下。
KataBowling
見つつ Gauche で試験と実装を書いてみた。サイズ的に小さめで簡単に反復練習できそう。てか実装はリファクタリングしたいですがそのまま出します。
最初の一歩
パーフェクトから書いた。試験が以下なカンジ。
(use gauche.test) (add-load-path ".") (load "kataBowling") (test-start "kataBowling") (test-section "kataBowling") (test* "(bowling '(10 10 10 10 10 10 10 10 10 10 10 10))" 300 (bowling '(10 10 10 10 10 10 10 10 10 10 10 10))) (test-end)
で、最初の実装が以下。
(define bowling (lambda (l) (let f ((l l) (frame 0) (p 0)) (if (or (null? l) (>= frame 10)) p (cond ((= (car l) 10) (f (cdr l) (+ 1 frame) (+ p (car l) (cadr l) (caddr l)))) ))) ))
これを元にストライクとスペアが混在しているヤツとか
(test* "(bowling '(10 5 5 10 5 5 10 5 5 10 5 5 10 5 5 5))" (+ 20 20 20 20 20 20 20 20 20 15) (bowling '(10 5 5 10 5 5 10 5 5 10 5 5 10 5 5 5)))
5 点づつ取ってくスペアばっかのヤツとか
(test* "(bowling '(5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5))" (+ 15 15 15 15 15 15 15 15 15 15) (bowling '(5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5 5)))
ストライクもスペアもないやつとか
(test* "(bowling '(2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))" 5 (bowling '(2 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))) (test* "(bowling '(1 2 3 4 5 4 3 2 1 2 3 4 5 4 3 2 1 2 3 4))" (+ 3 7 9 5 3 7 9 5 3 7) (bowling '(1 2 3 4 5 4 3 2 1 2 3 4 5 4 3 2 1 2 3 4))) (test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 5))" 15 (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 5)))
あるいは全てが混在しているヤツとか
(test* "(bowling '(10 2 3 5 5 2 3 10 5 5 2 3 5 5 10 2 3))" (+ 15 5 12 5 20 12 5 20 15 5) (bowling '(10 2 3 5 5 2 3 10 5 5 2 3 5 5 10 2 3)))
実装てきにはスペアな分岐を書いて else を書いたらできちゃったカンジ。
(define bowling (lambda (l) (let f ((l l) (frame 0) (p 0)) (if (or (null? l) (>= frame 10)) p (cond ((= (car l) 10) (f (cdr l) (+ 1 frame) (+ p (car l) (cadr l) (caddr l)))) ((= (+ (car l) (cadr l)) 10) (f (cddr l) (+ 1 frame) (+ p 10 (caddr l)))) (else (f (cddr l) (+ 1 frame) (+ p (car l) (cadr l)))) ))) ))
時間的にもそんなにかかってません。Scheme が優秀なのかな。
でも試験にパスしてるとは言え、なんつーか微妙な違和感がある。何だろ。
てか
TDD とか XP とかって割にボッチソンになっちゃってる件orz
そりゃ良いのですが、1h 程度のセッションでヤッてみるのは良いかも、って思っております。Okinawa.rb でもやってみては如何かと。
CodingDOJO 追補
以下な手順で進める模様。
- プロジェクタに接続された1台のPCでコーディングする。
- ペアでコーディングする。
- 5〜10分間隔でペアの片方を交代する(筆者の経験では7分単位での交代がうまくいった)。
- コーディングを担当しているときは、自分が何をしているのかを説明しながらキーボードをタイプする。こうすることで聴衆も、何が起きているのかを理解できる。
- 聴衆は、テストがきちんと通っている場合にだけ、設計について意見を述べてもよい。テストが通っていない状態では、設計については質問しかできない。
- 聴衆が現在おこなわれている作業について混乱してきたら、コーディングしている人は手を止めて、自分がいまやっていることを説明しなければならない。
さらに追記
なんとなく違和感があったのでもう少し確認。例えば以下。
(test* "(bowling '(0 0 0 0 0 0 0 0 10 5 5 5))" (+ 20 15) (bowling '(0 0 0 0 0 0 0 0 10 5 5 5)))
ほら駄目。
test (bowling '(0 0 0 0 0 0 0 0 10 5 5 5)), expects 35 ==> ERROR: GOT #<<error> "pair required, but got ()">
あ、これは試験の方が駄目じゃん。以下か。
(test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 5 5 5))" (+ 20 15) (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 5 5 5)))
で、実装を以下に修正してます。
(define bowling (lambda (l) (let f ((l l) (frame 0) (p 0)) (cond ((or (null? l) (>= frame 10)) p) ((= frame 9) (f (cdr l) frame (+ p (car l)))) ((= (car l) 10) (f (cdr l) (+ 1 frame) (+ p (car l) (cadr l) (caddr l)))) ((= (+ (car l) (cadr l)) 10) (f (cddr l) (+ 1 frame) (+ p 10 (caddr l)))) (else (f (cddr l) (+ 1 frame) (+ p (car l) (cadr l)))) )) ))
一応試験パス。もう少し色々確認。以下とか。
(test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 2 5))" (+ 17 7) (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 2 5))) (test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 2 5))" (+ 12 7) (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 2 5))) (test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 5))" (+ 5 7) (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 2 5)))
パンチアウトなパターンも確認してみるか。
(test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 10))" (+ 30 30) (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 10 10 10 10))) (test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 10 10 10))" (+ 20 30) (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 5 5 10 10 10))) (test* "(bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 10 10 10))" (+ 5 30) (bowling '(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 3 10 10 10)))
よし。散歩に行ってこよ。
の前にもう少し
前の実装で動作確認してみたんですが試験パスしとるな。とりあえずリファクタ版、ってことにしておこうと思いますが、やっぱなんでちゃんと動いとるかが微妙に謎。
確認してみたのですが
最初の実装で十分だった模様です。いやはや。