読者です 読者をやめる 読者になる 読者になる

レガシーコード本 読了!

久しぶりの読了宣言のような気がします。本を読んでなくはないのですが、今の職場に移った事にともなって通勤時間が短くなって読書の時間も短くなったんですよね。睡眠不足で、電車の中で立ったまま寝てることもよくありますし。

で、今回の本は通称「レガシーコード本」。邦訳が出てないころから話は聞いてて、邦訳が出たらぜひ読んでみたいと思ってて今に至ります。時間がかかりましたが、何とか12月19日 "TDD" Boot Camp  ~ "TDD" をつかめ! ~(東京都)の前に読み終わってよかったです。来たる12/19のTDD Boot Campでは、この辺を意識しながら望みたいです。

あと、実はこれ会社の経費で買ってもらいました。経費で買ってもらった以上、ちゃんと恩返しをということで読書感想文を載せます。まぁ、自分で買っても、感想文は載せていますけどね。。。

レガシーコード改善ガイド (Object Oriented SELECTION)

レガシーコード改善ガイド (Object Oriented SELECTION)

  • 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
  • 出版社/メーカー: 翔泳社
  • 発売日: 2009/07/14
  • メディア: 大型本
  • 購入: 40人 クリック: 555回
  • この商品を含むブログ (125件) を見る


以下、いつも通りに気になったところを。

1.2 危険な変更

頻繁に変更しないと腕がなまってしまう

これはアジャイル開発の頻繁なリリースと同じ考えかな。リリース作業が1回もしくはほんんの数回だけだと、作業にとまどって迂闊なミスもよくありますからね*1

2.1 単体テストとは

実行に0.1秒もかかる単体テストは、遅い単体テストである

極論に聞こえるけど、実績がある人が言うんで重みがあります。そういや、レガシーコードの定義(テストがないコード)も極論ですし。

3.1 強調クラスの偽装

偽装オブジェクトとモックオブジェクトの違い。「モックオブジェクトとは、内部的に表明を実行する偽装オブジェクト」とのこと。たいていは、単純な偽装オブジェクトで大丈夫らしい。

モックオブジェクトといえば、easymockはちょっと触ったことある(⇒ 新しいものに取り組んでみた - @ikikko のはてなダイアリー)けど、イマイチ使い方が分からんかった記憶が。

6.1 スプラウトメソッド

追加するロジックをまったく新しいメソッド(スプラウトメソッド)として切り分け、そのメソッドに対してテストコードを記述するやり方。これは理解しやすいこともあって、よくやりますよね。

ただ短所もやっぱりあります。古いコードの中に新しいコードがあると、コードの美しさとかも含めた整合性がとれんのですよね。実体験しました。

9.1 いらだたしいパラメータ

とりあえず、テストコードを作る際に必要なパラメータをnullにするってのは、現実的な解だと思いました。テストコード中でそのパラメータが使われないなら特に問題ないし、使われててもその場でNullPointerExceptionが発生しますからね。

13.1 仕様化テスト

今動いている振る舞い(仕様)を維持するために、仕様化テストを書く。そのための手順は↓。

  1. テストハーネスの中で対象のコードを呼び出す
  2. 失敗すると分かっている表明を書く
  3. 失敗した結果から実際の振る舞いを確認する
  4. コードが実現する振る舞いを期待するように、テストを変更する
  5. 以上の手順を繰り返す

偶然にも、ちょうどこれやっていました。既存のプロダクトを修正するというのをプライベートな時間を使って友人とやっているのですが、そこでテストコードを書くときに、この手順に沿って行っていました。

18.1 クラスの命名規約

下記は、本書で例示されている金融パッケージのクラス一覧です。

- CheckingAccount
- CheckingAccountTest
- FakeAccountOwner
- FakeTransaction
- SavingsAccount
- SavingsAccountTest
- TestingCheckingAccount
- TestingSavingsAccount

それぞれのprefix / suffixは以下の意味を持ちます。

~Test
単体テスト用クラス
Fake~
協調クラスを偽装するクラス
Testing~
「サブクラス化とメソッドのオーバーライド」を行う際に作成するクラス

JUnit3の時代の名残で~Testはよく見ますし、Quick JUnit Plugin for Eclipseでもデフォルトは~Testですよね、多分。FakeやTestingは今まであまり見たことないけど、いちいち考えるのも時間の無駄なので基本これに統一させてもいいかも。

20.1 責務の把握

本書内で提示されている下記の疑問は、私もずっと疑問に思ってました。それに対する回答で、ある程度もやもやが晴れたような気がします。

Q. どうやってprivateメソッドをテストするのでしょうか?
A. どうしてもprivateメソッドをテストしたいのなら、そのメソッドはprivateにすべきではない。

「privateからpublicにするのがしっくりこないならば、別クラスに切り出す」ということですね。なるほど。

あと、この節で提唱されている、機能スケッチでクラス内部の関係を表す手法、一回実践しておきたいです。図示するとすんなり頭に入ってくることもありますしね。

22.3 手作業によるリファクタリングに挑戦

「テスト時の内部状態確認用に検出用変数を導入し、全てのリファクタリングが終わってから検出用変数を削除する」なるほどね。リファクタリングだからといってコードをまったく追加していけないわけでなく、後で消すことが濃厚なコードは適宜追加してよいということか。

24 もうウンザリです。何も改善できません

あるあるw。そして、それに対する本書の回答が実にいい!「ブラボー おお ブラボー」もしくは「ディ・モールト よい」ってやつですねw

http://www.rapturhythm.net/blog/archives/bravo.jpg:image:small:left
http://pds.exblog.jp/pds/1/200902/22/69/c0151969_2223268.jpg:image:right



詳しくはここでウダウダ書くより、立ち読みでもいいんで本書を見てみてください。勇気付けられますよ。

25 依存関係を排除する手法

テストがないコードに対して、安全にリファクタリング(してテストを整備できる環境にする)手法について。ここは、個人的に1番のポイントだと思っています。

  1. テストを用意してから
  2. リファクタリングする

というのが理想だろうけど、レガシーコードだと現実にはその最初のテストが用意できないことも多いはず。そういったときのことを前提とした書き口です。

ただ、本書でも述べられていますが

これらの手法を適用するだけで、すぐに設計を改善できるわけではありません。
紹介する手法の中にはカプセル化に反するようなものも含んでいるため、優れた設計センスを持っている人は、それらを見て二の足を踏むかもしれません

とあるように、一時的にでも設計が悪くなったように見えます。なので、大きい(かつ品質管理を厳格に求められる)組織だと導入が難しいのかもしれませんね。まぁ、そのような組織だと「動くものには触るな」が格言なので、リファクタリングの意義を問うことから始めるのでしょうけど。。。


次は、同じくテスト・リファクタリング関連で、ちょっと古いけどこの2冊のどっちか読もうかな。ちょうど事務所に置いてあったのが気になってたところなので。

パターン指向リファクタリング入門~ソフトウエア設計を改善する27の作法

パターン指向リファクタリング入門~ソフトウエア設計を改善する27の作法


JUnitイン・アクション

JUnitイン・アクション

  • 作者: ビンセントマソル,テッドハスティード,Vincent Massol,Ted Husted,クイープ
  • 出版社/メーカー: ソフトバンククリエイティブ
  • 発売日: 2004/05
  • メディア: 単行本
  • クリック: 53回
  • この商品を含むブログ (41件) を見る

*1:心なしか、久しぶりの書評エントリだと書き方を忘れているような気がします。。。