Skip to content

Instantly share code, notes, and snippets.

@wm3
Last active December 14, 2015 18:09
Show Gist options
  • Select an option

  • Save wm3/5127054 to your computer and use it in GitHub Desktop.

Select an option

Save wm3/5127054 to your computer and use it in GitHub Desktop.
実践テスト駆動開発第2回

14章 スナイパーがオークションで落札する

  • 落札する機能を追加する
  • この際に、以前のリファクタリングが成果を上げる

まずは失敗するテストから

エンドツーエンドテストの改善

  • テスト項目
    • スナイパーが高い値段を入札する事で落札する
  • スナイパー (application:ApplicationRunner) に処理を追加
    • スナイパーが勝っている事を表示している (hasShownSniperIsWinning)
    • スナイパーが落札した事を表示している (showsSniperHasWonAuction)
  • オークション (auction:FakeAuctionServer) に処理を追加
    • 価格をレポートしろ (reportPrice)
    • 落札された事を通知しろ (announceClosed)

入札者については誰が知っているのか?

現時点ではアプリケーションに入札者を判別する機能が無い

  • 追加したいが、誰に機能を追加するかが問題

自分の付けた価格かどうかが分かれば良い

  • 現在の落札者情報について不要な詳細は公開しない
  • PriceSource という enum クラスを追加して、自分か他人かを記述できるようにする

自分で付けた価格かどうかの判別をどのロールに

  • トランスレータ (AuctionMessageTranslator) の責務
  • 解析は入れ子クラスの AuctionMessageEvent で行う

実装を追加

  • (割と自明な)パラメータの追加等になっている

スナイパーのやるべき事は他にもある

現在勝っているかどうかを通知する機能を追加

AuctionSniper に割り当て

  • 新しいテストが失敗する
  • 勝っているかどうかに応じて SniperEvent を通知する処理を追加

スナイパーに状態をいくつか加える

  • AuctionSniper に状態を管理する必要が出てきている

スナイパーが落札する

コード参照

アローアンス

  • 呼び出しを行っても行わなくても良いという事を表現

状態

  • jMock では実行の条件を state オブジェクトを導入する事で表現

安定して進捗させる

15章 実際のユーザーインタフェースに向けて

より現実的な実装

UIを改善する事にする

  • 単純なテキスト (JLabel) ではなくテーブル (JTable) を使用する

JLabel を置き換える

  • エンドツーエンドテストのテストを追加
    • JTable の状態をチェック
  • テーブルによる実装を追加
    • Swing の AbstractTableModel を導入

価格の詳細を表示する

まずはテストを失敗させる

  • 商品IDを表示しているかのテストを追加する
  • テーブルに商品IDのカラムを追加する

スナイパーの外部から状態を送信する

  • SniperListener へのコールバックがたくさんありすぎるのでまずはそれを整理
  • SniperState の導入
  • SniperListener#sniperBiddingに SniperState 引数を追加
  • AuctionSniper が商品IDのアクセスをする
    • AuctionSniper が保持
    • AuctionSniper のコンストラクタに渡す
    • Auction からは取得しない、識別子の形式が変わるかもしれないので

コラム: Public な Final フィールド

  • ゲッターのメンテナンスコストが抑えられる
  • 特にクラスが安定していないとき
  • 最終的には意味のあるアクションメソッドで置き換えたいともくろんでいる

入札中のスナイパーを表示する

  • SniperTableModel を実装
  • TableModelListener をモック
    • 例外。TableModelListener の設計がこちらでやりたい事と非常にあっているため
  • 実装
    • switch を多用しているが、あまりオブジェクト指向的ではないので注意

詳細は表示されたが、まだテストは失敗している

  • カラムヘッダが修正されていないため

スナイパーイベントをシンプルにする

リラックスして振り返り

  • リファクタリング
  • メソッドを整理
  • SniperSnapshot にする

sniperBidding() を再利用する

  • sniperBidding() から sniperStateChanged() に名前を変える

Note: jMock の軽量な拡張

  • aSniperThatIs メソッドを導入して可読性を上げている

数字を埋めていく

  • 一位入札中である事を sniperStateChaned の呼び出しで置き換える
  • (機能ベースでテスト名を分けているメリットか)
  • AuctionSniper の実装
  • SniperSnapshot のヘルパーメソッドを追加

最後までやりきる

「落札成功」と「落札失敗」を変換する

  • sniperStateChanged() に変換する
  • AuctionSniper#isWinningが消える
  • AuctionSniperはSniperStateを使用していない事になる

テーブルモデルを整える

Column クラスをオブジェクト指向的にする

  • 価格の詳細を定義していない古いコードをテストから取り除く

  • switch文を取り除く

  • Event の経路を短縮する

最後の仕上げ

  • カラムタイトルのテスト

  • TableModel のテスト

  • さしあたりはこれで十分

所見

単一責任

  • AND や OR、 BUT は禁止

ソフトウェアのキーホール手術

  • 途中で辞められない大規模な修正ではなく、小さな修正をする

プログラマの過敏性

心変わり万歳

解決策は他にもある

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment