TDD BootCamp 北陸2日目

昨日の続き。

ハヤオキクラスタ数名がご飯の前にお風呂でウダウダ。ここでもちょっと愚痴ってしまう。いかんいかん。

ブレックファストセッション

朝ご飯を食べながら今日の方針をうだうだと。悩みは多いがやはりレガシーの方向に向かうことに。

ウェイクアップセッション - レガシー vs TDD デモ

報告。なぜか急に腹が緩くなった。

Ioke という JavaVM 上の言語へのコマンドを Twitter から投げられる bot のレガシーコードにテストを付加し、機能追加を考えながら、手法の解説を行うという、かなり @t_wada 頼みのセッション。

検体の活きが良すぎて若干消化不良ながらも以下の解説が繰り広げられる。

  • まずバージョン管理、そしてブランチを切る
  • 現在の動作を Characterization Test で浮き彫りに
  • 密結合の class をぶった切る。コンパイラに怒られるかどうかでメドをつけていく。ここはコンパイラと IDE の力に任せる。
  • 「gitk だけが友達です」
  • (やはり eclipse のコードアシスト(?) は便利。Emacs にも似た機能があるっぽいんだけど、聞き逃してしまった。)
  • sensing variables
    • (あとで捨てる前提の確認用メンバ変数。あるいは Logger なども含めて、内部の動作を明らかにする工夫。)

gitk 知らなかった。便利。MacPorts で入れたもの(たぶん)はフツーに使える。 Fink で入れたものはなんかフォントがずれてる。

正攻法で攻め切れないので迂回路を仕込んで動く状態に持っていくような感じ。「追い込み漁」という言葉が浮かんだ。

頑張って追いこんでいったけど、最終的に利用しているライブラリのバージョンが古くて動かないという事態に。

このセッションで最も印象的だった言葉を書き忘れていた。それは

「分かりました。引き返しましょう。」

道を分け入って分け入って、ここから先は危険と判断して別なルートから道を切り開こうとする探検家のような、そんなイメージが鮮明に思い浮かんだ。これは普段から自分がそういうイメージでコードと戦っているからなんだと思うけど、「同じ言葉を使っているんだなぁ」と嬉しくなった次第。

レガシーのレガシーたる所以

仕様変更に気づけないことがあるという話。テストが揃って CI で回していれば落ちた時点で気づける。

※ 実は今の自分の悩みはここ。CI まで手が回らない。自分がコードを書く時間を減らさないと、もう他のことまでできないんだよなー。

アフタヌーンセッション - レガシー vs TDD Coding Dojo

Coding Dojo については [記事紹介] Coding Dojo: InfoQ 〜 TDDを根づかせる:導入の問題と解決策: TDD.NET 参照のこと。一言で言うと1台のPCでペアを次々に取っかえひっかえしていくペアプロの乱取りです。

ここでは

wtnabe's pukiassist at master - GitHub

を検体として提供して Ruby でレガシーと闘うチームに参加。6人のうち Rubyist 2人という状況を見かねて @t_wada が参戦! これで勝つる!

まずはコードの目的と動作を説明。いきなり動かなくていろいろ焦るが、どうにか動く状態に持っていったところで、さて何をどうしようか。

ここで鶴の一声!

@t_wada 「パーサがありますね! パーサいいですね! パーサにしましょう!」

そうです、このツールには PukiWiki の記法を setext 記法に変換する機能が含まれているのですが、こいつを料理しようという展開。確かに、自分でも TDD のサンプルコードとして文字列処理はとても良いと思う。後から考えてもこのパーサに絞った判断は絶妙だった。1

  1. まずは rspec の雛形を準備してもらう。インスタンス化できない心配はここではないので、順調に進む。
  2. しかしどのようなパラメータを与えればよいのか分からず。コード書いた経験からいちばん下に if ( __FILE__ == $0 ) で実行する処理があったはずということでそこを確認してもらう
  3. テストデータを食わせるといきなり例外で死ぬ

すわ。ここが改善のポイントでは!

  1. どこで例外投げてるの?
  2. おぉ、例外を投げ直している!
  3. 作者コメント。えーとたぶんこれは見出しを変換する convert_heading() で投げてます。
  4. まずは convert_heading() の characterization test 書きたいんすけど
  5. 素晴らしい。それで。
  6. あー h3 相当の行は変換できないんですわ
  7. じゃあテストデータからとりあえず外して動くようにしましょうか
  8. 動きがつかめてきた
  9. じゃあ h1, h2 以外は受け付けない仕様になっているので h3 のときのテストに入りましょう
  10. 動かないっすねぇ。何がいけないんだろう。
  11. この if 文の動きを分けてみたいですね
  12. なるほどここでこの値以外は無視してるので無視しないように case ( when ) を追加しましょう
  13. よし、期待通りの case ( when ) を通るようになった
  14. じゃあ、h3 のときどうして欲しいか設計しましょう
  15. あとは目的の動作をするまでプロダクトコードをいじる

だいぶ端折ったけどこんな感じの流れ。

コードの中の問題箇所の同定については書いた本人がいたのでたぶん「現場」のレガシーコードを相手にしたときよりずいぶん速かったと思う。

自分一人でやったとしても流れとしては似たような感じになったと思うけど、

いま何をしているのか、t_wada の解説付きで一つずつ作業が進む

という贅沢仕立て。これで頭と身体に入ってこなければ嘘。

※ しかし冷静に考えるとわずか1年前のコードなのになんでテストがないのかな。あー PukiWiki -> setext 変換はもっと前に書いてて、他の部分も外部のツール(PukiWiki, smtpd)に完全に依存しているので、テストは諦めたんだ。個人的にはこういうツールは今後もよく作りそうなので、mock 力は必要だなー。

まとめ

  • とにかくペアプロは疲れる。二人同時に気が抜ける瞬間はまず来ないので生産性が落ちない。
  • オフライン用の道具大事。chm ファイル、IDE、ri, refe, irb、「本」など。
  • でもたまのオフラインはいいかもしれない
  • LL使いは「標準」の環境がないので、若干ペアプロのハードルが高いかもしれない
  • TDDという言葉よりも、その中の手法や概念を説明する言葉、そして何より経験が自分の理解と実感を確かにする
  • 2日目は JavaScript 経験率100% ! もしかしたら JS + jsUnit が TDD 勉強会では最強か? 2
  • 丁寧に「デバッグ」

昨日の分も

  • Emacs 以外の人にも優しい環境を目指す
    • 一応もう MacVim は動いてるよ!
  • テストの意図がストレートに表れるテストコードを目指したい
    • rspec がこの部分ですごく便利。テストケース一つ一つはメソッドではないので、名前付けが自由に行えるし、記述も読み下しやすい。レポートが見やすいし、わざと RED にしたりコメントアウトしたりしなくても pending だけで「飛ばせる」。
  • 自分の三角測量がちょっと疎かだった
  • やはりペア設計、ペアプロ、ペアデバッグはハマりを減らしてくれる
  • バージョン管理の安心感重要

コードはまた今後。

最後にスタッフの皆さん、出席者の皆さん、そして @t_wada ありがとうございます! やっぱ hands-on はいいですね。またやりましょう!

  1. ※ 実は何をするか読めなかったので http と smtp の mock を直前で仕込んでいたんだけど、そっちに流れるよりずっとよかった。 

  2. できることが限られちゃうけど、最も TDD に向いているテーマの一つ、文字列処理は問題なくできる。 

More

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Develop Document Jekyll