tokyo rubykaigi 01 t-wada
DESCRIPTION
TRANSCRIPT
![Page 1: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/1.jpg)
それRubyでもやりたい
ライブラリ移植と機能拡張のためのパターンランゲージ
和田 卓人 (a.k.a id:t-wada)
Aug, 21, 2008 @TokyoRubyKaigi 01
![Page 2: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/2.jpg)
![Page 3: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/3.jpg)
多様性
![Page 4: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/4.jpg)
RegionalRubyKaigiに光あれ
![Page 5: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/5.jpg)
続け!
![Page 6: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/6.jpg)
自己紹介名前: 和田 卓人 (わだ たくと)
メール: [email protected]
ブログ: http://d.hatena.ne.jp/t-wada
Twitter: t_wada
Wassr: twada
![Page 7: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/7.jpg)
自己紹介タワーズ・クエスト株式会社 プログラマ 兼 取締役社長
![Page 8: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/8.jpg)
これまで書いたものWEB + DB PRESSvol.35 「実演! テスト駆動開発」vol.37 「実演! リファクタリング」vol.42 「現場で使えるREST」LifeHacks PRESSオープンソースマガジン(リレーコラム)他いろいろ
![Page 9: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/9.jpg)
gihyoコラボ企画『[動画で解説]和田卓人の“テスト駆動開発”講座』http://gihyo.jp/dev/serial/01/tdd/全20回すべて動画付き解説ニコニコ動画でも見れます
WEB+DB過去記事の特設サイトや動画
![Page 10: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/10.jpg)
デブサミ• デベロッパーテスティング・ライブ - 自信を持ってコードを書
くための心・技・体 -
• 【徹底討論】テストなんていらない?!-テストを、どこまでやるべきか?
• そしてデブサミ 2009 へ
• テストトラックのコンテンツ委員になりました
![Page 11: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/11.jpg)
よろしくおねがいします
![Page 12: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/12.jpg)
Agenda
•移植した中身のこと•移植する方法のこと•Q & A
![Page 13: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/13.jpg)
第一部移植した中身のこと
![Page 14: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/14.jpg)
背景
![Page 15: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/15.jpg)
始めに問題意識ありき•複雑な テーブル構造•既にレールに乗れない•多くのテーブルを JOIN しなければならない要件
![Page 16: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/16.jpg)
餅は餅屋
•CASE句•UNION ALL•RDBMS固有の関数
![Page 17: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/17.jpg)
SQL書きたい
![Page 18: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/18.jpg)
S2Dao•80:20•2WaySQL•手書きのSQL をサポート•SQL を知っていれば書ける
![Page 19: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/19.jpg)
2 Way SQL
![Page 20: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/20.jpg)
代入コメント(1)
![Page 21: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/21.jpg)
SELECT *FROM empWHERE job = /*ctx[:job]*/'CLERK'AND deptno = /*ctx[:deptno]*/20
外部SQL
![Page 22: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/22.jpg)
SELECT *FROM empWHERE job = /*ctx[:job]*/'CLERK'AND deptno = /*ctx[:deptno]*/20
からくり
![Page 23: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/23.jpg)
SELECT *FROM empWHERE job = /*ctx[:job]*/'CLERK'AND deptno = /*ctx[:deptno]*/20
Given
![Page 24: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/24.jpg)
ctx[:job] = 'MANAGER'ctx[:deptno] = 30
When
![Page 25: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/25.jpg)
SELECT *FROM empWHERE job = ?AND deptno = ?
Then
と、 ['MANAGER', 30]
![Page 26: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/26.jpg)
代入コメント(2)
![Page 27: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/27.jpg)
SELECT *FROM empWHERE job = /*ctx[:job]*/'CLERK'AND id IN /*ctx[:ids]*/(10,11)
Given
![Page 28: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/28.jpg)
ctx[:job] = 'MANAGER'ctx[:ids] = [30,40,50]
When
![Page 29: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/29.jpg)
SELECT *FROM empWHERE job = ?AND ids IN (?, ?, ?)
Then [ 'MANAGER', 30, 40, 50 ]
![Page 30: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/30.jpg)
IF コメント
![Page 31: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/31.jpg)
SELECT * FROM empWHERE job = /*ctx[:job]*/'CLERK' /*IF ctx[:age]*/AND age > /*ctx[:age]*/20/*END*/
Given
![Page 32: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/32.jpg)
ctx[:job] = 'MANAGER'ctx[:age] = 30
When
![Page 33: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/33.jpg)
SELECT * FROM empWHERE job = ? AND age > ?
Then
と、 ['MANAGER', 30]
![Page 34: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/34.jpg)
SELECT * FROM empWHERE job = /*ctx[:job]*/'CLERK' /*IF ctx[:age]*/AND age > /*ctx[:age]*/20/*END*/
Given
![Page 35: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/35.jpg)
ctx[:job] = 'MANAGER'ctx[:age] = nil
When
![Page 36: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/36.jpg)
SELECT * FROM empWHERE job = /*ctx[:job]*/'CLERK' /*IF ctx[:age]*/AND age > /*ctx[:age]*/20/*END*/
Then
![Page 37: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/37.jpg)
SELECT * FROM empWHERE job = ?
Then
と、 ['MANAGER']
![Page 38: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/38.jpg)
BEGINコメント
![Page 39: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/39.jpg)
SELECT * FROM emp/*BEGIN*/WHERE /*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/ /*IF ctx[:age]*/AND age > /*ctx[:age]*/25/*END*//*END*/
Given
![Page 40: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/40.jpg)
ctx[:job] = nilctx[:age] = 35
When
![Page 41: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/41.jpg)
SELECT * FROM emp/*BEGIN*/WHERE /*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/ /*IF ctx[:age]*/AND age > /*ctx[:age]*/25/*END*//*END*/
Then
![Page 42: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/42.jpg)
SELECT * FROM empWHERE age > ?
Then
と、 [35]
![Page 43: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/43.jpg)
SELECT * FROM emp/*BEGIN*/WHERE /*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/ /*IF ctx[:age]*/AND age > /*ctx[:age]*/25/*END*//*END*/
Given
![Page 44: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/44.jpg)
ctx[:job] = nilctx[:age] = nil
When
![Page 45: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/45.jpg)
SELECT * FROM emp/*BEGIN*/WHERE /*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/ /*IF ctx[:age]*/AND age > /*ctx[:age]*/25/*END*//*END*/
Then
![Page 46: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/46.jpg)
SELECT * FROM emp
Then
と、 [ ]
![Page 47: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/47.jpg)
第一部完
![Page 48: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/48.jpg)
第二部移植する方法のこと
![Page 49: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/49.jpg)
検討
![Page 50: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/50.jpg)
本当に移植すべきか?•定番ライブラリではダメか•代替案はないのか•早急に結論を出す前に、定番を調べるべし
![Page 51: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/51.jpg)
全部移植すべきか?
•対象ライブラリの美点は何か•既にあるライブラリでも実現できることは何か
![Page 52: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/52.jpg)
移植
![Page 53: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/53.jpg)
最初に確認すること
•対象コードのテストはあるか•対象機能(の美点)は切り出し可能か
![Page 54: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/54.jpg)
テストが無い場合
• 残念ながら、レガシーコードです
• 本日は詳細は割愛
• WEwLC 読書会を行っています
• http://groups.google.co.jp/group/legacy-code
![Page 55: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/55.jpg)
大原則:一度に複数を相手にしない
![Page 56: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/56.jpg)
動作する、きれいなコードへ
きれい
汚い
(すぐには)動かない 動作する
二つの道がある
![Page 57: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/57.jpg)
逐語訳的移植
Context 言語間で移植しようとしている
Force ともかくまず動くところまで持っていきたい
Solution 設計や名前を変えずに、まず言語間の移植のみに集中する
![Page 58: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/58.jpg)
逐語訳的テスト移植
Context テストコードを移植しようとしている
Force 安全に移植したいが、テストのテストは存在しない
Solution テストの設計や語彙を変えずに、まず言語間の移植に集中
![Page 59: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/59.jpg)
変えないもの•xUnit という共通語彙•設計•クラスやメソッドの名前•クラス構造 (interface除く)
![Page 60: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/60.jpg)
変えたもの•言語間の違い•静的型付けから動的型付けへ•予約語•xUnit の方言
![Page 61: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/61.jpg)
Java コードpublic void testNext() throws Exception { String sql = "SELECT * FROM emp"; SqlTokenizer tokenizer = new SqlTokenizerImpl(sql); assertEquals("1", SqlTokenizer.SQL, tokenizer.next()); assertEquals("2", sql, tokenizer.getToken()); assertEquals("3", SqlTokenizer.EOF, tokenizer.next()); assertEquals("4", null, tokenizer.getToken());}
![Page 62: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/62.jpg)
Ruby コードdef testNext sql = "SELECT * FROM emp" tokenizer = SqlTokenizer.new(sql) assert_equal(SqlTokenizer::SQL, tokenizer.go_next(), "1") assert_equal(sql, tokenizer.getToken(), "2") assert_equal(SqlTokenizer::EOF, tokenizer.go_next(), "3") assert_nil(tokenizer.getToken(), "4")end
![Page 63: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/63.jpg)
PTSCTCPWPort The Simplest Case That Could Possibly Work
Context 逐語訳的テスト移植を終えた
Force グリーンが見たいが、レッドになるテストが多すぎる
Solution 最も単純なテストケースから実装し、それ以外は pending
![Page 64: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/64.jpg)
Context 移行元コードに不明点がある
Force 不明点をおいたまま先に進めたくない
Solution 移行元コードの現在の振る舞いを自動テストに落とし込む
Characterization Test
![Page 65: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/65.jpg)
洗練
![Page 66: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/66.jpg)
TDDのサイクル1. テストを書き2. そのテストを実行して失敗させ(Red)3. 目的のコードを書き4. 1で書いたテストを成功させ(Green)5. テストが通るままでリファクタリングを行う(Refactor)
6. 1~5を繰り返す
![Page 67: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/67.jpg)
TDDとコード
きれい
汚い
(すぐには)動かない 動作する
Red
Green
Refactoring
![Page 68: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/68.jpg)
TDDと黄金の回転
きれい
汚い
(すぐには)動かない 動作する
Red
Green
Refactoring
![Page 69: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/69.jpg)
実装のテストから仕様のテストへ
Context 移植の最初のステップが終わったので、内部を改善したい
Force 実装内部を思う存分変更したい
Solution ホワイトボックステストをブラックボックステストに変換
![Page 70: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/70.jpg)
例えば、RSpec を使ってみる
![Page 71: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/71.jpg)
郷に入っては郷に従え
Context 逐語訳的移植を終えた
Force コードをきれいにしたい
Solution 移植対象言語のイディオム、ベストプラクティスで書き換える
![Page 72: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/72.jpg)
王道を知る
Context 逐語訳的移植を終えた
Force コードをきれいにしたい
Solution設計の王道を調べ、移植対象言語に実装が存在したら使用を検
討する
![Page 73: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/73.jpg)
パーサジェネレータracc
![Page 74: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/74.jpg)
ご存知、な (ry
ごめんなさいごめんなさい
![Page 75: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/75.jpg)
raccデカルチャー
ごめんなさいごめんなさい
![Page 76: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/76.jpg)
割愛ごめんなさいごめんなさい
![Page 77: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/77.jpg)
そして移植の最後に
![Page 78: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/78.jpg)
恩返し
![Page 79: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/79.jpg)
第二部完
![Page 80: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/80.jpg)
Q & A
![Page 81: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/81.jpg)
おわりに
![Page 82: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/82.jpg)
大原則:一度に複数を相手にしない
![Page 83: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/83.jpg)
TDDと黄金の回転
きれい
汚い
(すぐには)動かない 動作する
Red
Green
Refactoring
![Page 84: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/84.jpg)
続け!
![Page 85: Tokyo Rubykaigi 01 t-wada](https://reader034.vdocuments.site/reader034/viewer/2022051609/5465ec00b4af9f5d3f8b5229/html5/thumbnails/85.jpg)
ご清聴ありがとうございました