Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
それRubyでも
やりたい
ライブラリ移植と機能拡張のためのパターンランゲージ
和田 卓人 (a.k.a id:t-wada)
Aug, 21, 2008 @TokyoRubyKaigi 01
多様性
Regional
RubyKaigi
に光あれ
続け!
自己紹介
名前: 和田 卓人 (わだ たくと)
メール: takuto.wada@towersquest.jp
ブログ: http://d.hatena.ne.jp/t-wada
Twitter: t_wada
Wassr: twada
自己紹介
タワーズ・クエスト株式会社
プログラマ 兼 取締役社長
これまで書いたもの
WEB + DB PRESS
vol.35 「実演! テスト駆動開発」
vol.37 「実演! リファクタリング」
vol.42 「現場で使えるREST」
LifeHacks PRESS
オープンソースマガジン(リレーコラム...
gihyoコラボ企画
『[動画で解説]和田卓人の テスト駆動開発 講座』
http://gihyo.jp/dev/serial/01/tdd/
全20回すべて動画付き解説
ニコニコ動画でも見れます
WEB+DB過去記事の特設サイトや動画
デブサミ
• デベロッパーテスティング・ライブ - 自信を持ってコードを書
くための心・技・体 -
• 【徹底討論】テストなんていらない?!-テストを、どこ
までやるべきか?
• そしてデブサミ 2009 へ
• テストトラックのコンテンツ委員...
よろしく
おねがい
します
Agenda
•移植した中身のこと
•移植する方法のこと
•Q & A
第一部
移植した
中身のこと
背景
始めに問題意識ありき
•複雑な テーブル構造
•既にレールに乗れない
•多くのテーブルを JOIN しな
ければならない要件
餅は餅屋
•CASE句
•UNION ALL
•RDBMS固有の関数
SQL書きたい
S2Dao
•80:20
•2WaySQL
•手書きのSQL をサポート
•SQL を知っていれば書ける
2 Way SQL
代入コメント
(1)
SELECT
*
FROM
emp
WHERE
job = /*ctx[:job]*/'CLERK'
AND
deptno = /*ctx[:deptno]*/20
外部SQL
SELECT
*
FROM
emp
WHERE
job = /*ctx[:job]*/'CLERK'
AND
deptno = /*ctx[:deptno]*/20
からくり
SELECT
*
FROM
emp
WHERE
job = /*ctx[:job]*/'CLERK'
AND
deptno = /*ctx[:deptno]*/20
Given
ctx[:job] = 'MANAGER'
ctx[:deptno] = 30
When
SELECT
*
FROM
emp
WHERE
job = ?
AND
deptno = ?
Then
と、 ['MANAGER', 30]
代入コメント
(2)
SELECT
*
FROM
emp
WHERE
job = /*ctx[:job]*/'CLERK'
AND
id IN /*ctx[:ids]*/(10,11)
Given
ctx[:job] = 'MANAGER'
ctx[:ids] = [30,40,50]
When
SELECT
*
FROM
emp
WHERE
job = ?
AND
ids IN (?, ?, ?)
Then
[ 'MANAGER',
30,
40,
50 ]
IF コメント
SELECT * FROM emp
WHERE
job = /*ctx[:job]*/'CLERK'
/*IF ctx[:age]*/AND age > /
*ctx[:age]*/20/*END*/
Given
ctx[:job] = 'MANAGER'
ctx[:age] = 30
When
SELECT * FROM emp
WHERE
job = ?
AND age > ?
Then
と、 ['MANAGER', 30]
SELECT * FROM emp
WHERE
job = /*ctx[:job]*/'CLERK'
/*IF ctx[:age]*/AND age > /
*ctx[:age]*/20/*END*/
Given
ctx[:job] = 'MANAGER'
ctx[:age] = nil
When
SELECT * FROM emp
WHERE
job = /*ctx[:job]*/'CLERK'
/*IF ctx[:age]*/AND age > /
*ctx[:age]*/20/*END*/
Then
SELECT * FROM emp
WHERE
job = ?
Then
と、 ['MANAGER']
BEGIN
コメント
SELECT * FROM emp
/*BEGIN*/WHERE
/*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/
/*IF ctx[:age]*/AND age > /*ctx[:age]*...
ctx[:job] = nil
ctx[:age] = 35
When
SELECT * FROM emp
/*BEGIN*/WHERE
/*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/
/*IF ctx[:age]*/AND age > /*ctx[:age]*...
SELECT * FROM emp
WHERE
age > ?
Then
と、 [35]
SELECT * FROM emp
/*BEGIN*/WHERE
/*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/
/*IF ctx[:age]*/AND age > /*ctx[:age]*...
ctx[:job] = nil
ctx[:age] = nil
When
SELECT * FROM emp
/*BEGIN*/WHERE
/*IF ctx[:job]*/ job = /*ctx[:job]*/'CLERK'/*END*/
/*IF ctx[:age]*/AND age > /*ctx[:age]*...
SELECT * FROM emp
Then
と、 [ ]
第一部
完
第二部
移植する
方法のこと
検討
本当に移植すべきか?
•定番ライブラリではダメか
•代替案はないのか
•早急に結論を出す前に、定番を
調べるべし
全部移植すべきか?
•対象ライブラリの美点は何か
•既にあるライブラリでも実現で
きることは何か
移植
最初に確認すること
•対象コードのテストはあるか
•対象機能(の美点)は切り出し可
能か
テストが無い場合
• 残念ながら、レガシーコードです
• 本日は詳細は割愛
• WEwLC 読書会を行っています
• http://groups.google.co.jp/group/legacy-code
大原則:
一度に複数を
相手にしない
動作する、きれいなコードへ
きれい
汚い
(すぐには)動かない 動作する
二つの道がある
逐語訳的移植
Context 言語間で移植しようとしている
Force
ともかくまず動くところまで
持っていきたい
Solution
設計や名前を変えずに、まず言
語間の移植のみに集中する
逐語訳的テスト移植
Context
テストコードを移植しようとし
ている
Force
安全に移植したいが、
テストのテストは存在しない
Solution
テストの設計や語彙を変えず
に、まず言語間の移植に集中
変えないもの
•xUnit という共通語彙
•設計
•クラスやメソッドの名前
•クラス構造 (interface除く)
変えたもの
•言語間の違い
•静的型付けから動的型付けへ
•予約語
•xUnit の方言
Java コード
public void testNext() throws Exception {
String sql = "SELECT * FROM emp";
SqlTokenizer tokenizer = new SqlToken...
Ruby コード
def testNext
sql = "SELECT * FROM emp"
tokenizer = SqlTokenizer.new(sql)
assert_equal(SqlTokenizer::SQL, tokenize...
PTSCTCPW
Port The Simplest Case That Could Possibly Work
Context 逐語訳的テスト移植を終えた
Force
グリーンが見たいが、レッドに
なるテストが多すぎる
Solution
最も...
Context 移行元コードに不明点がある
Force
不明点をおいたまま先に進めた
くない
Solution
移行元コードの現在の振る舞い
を自動テストに落とし込む
Characterization Test
洗練
TDDのサイクル
1. テストを書き
2. そのテストを実行して失敗させ(Red)
3. 目的のコードを書き
4. 1で書いたテストを成功させ(Green)
5. テストが通るままでリファクタリング
を行う(Refactor)
6. 1∼5を繰...
TDDとコード
きれい
汚い
(すぐには)動かない 動作する
Red
Green
Refactoring
TDDと黄金の回転
きれい
汚い
(すぐには)動かない 動作する
Red
Green
Refactoring
実装のテストから
仕様のテストへ
Context
移植の最初のステップが終わっ
たので、内部を改善したい
Force 実装内部を思う存分変更したい
Solution
ホワイトボックステストを
ブラックボックステストに変換
例えば、
RSpec を
使ってみる
郷に入っては郷に従え
Context 逐語訳的移植を終えた
Force コードをきれいにしたい
Solution
移植対象言語のイディオム、ベ
ストプラクティスで書き換える
王道を知る
Context 逐語訳的移植を終えた
Force コードをきれいにしたい
Solution
設計の王道を調べ、移植対象言
語に実装が存在したら使用を検
討する
パーサジェネ
レータ
racc
ご存知、な (ry
ごめんなさいごめんなさい
racc
デカルチャー
ごめんなさいごめんなさい
割愛
ごめんなさいごめんなさい
そして
移植の
最後に
恩返し
第二部
完
Q & A
おわりに
大原則:
一度に複数を
相手にしない
TDDと黄金の回転
きれい
汚い
(すぐには)動かない 動作する
Red
Green
Refactoring
続け!
ご清聴
ありがとう
ございました
Tokyo Rubykaigi 01 t-wada
Upcoming SlideShare
Loading in …5
×

Tokyo Rubykaigi 01 t-wada

3,533 views

Published on

Published in: Technology
  • Be the first to comment

Tokyo Rubykaigi 01 t-wada

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

×