レガシーコード改善ガイド (Object Oriented SELECTION)
- 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
- 出版社/メーカー: 翔泳社
- 発売日: 2009/07/14
- メディア: 大型本
- 購入: 45人 クリック: 673回
- この商品を含むブログ (152件) を見る
『レガシーコード改善ガイド』をおととしくらいには購入していて、その時一度さっくり読んだけど「まぁ当たり前のことが書かれてるな」という気持ちしかなかった。今レガシーコードを触ってて*1調査も時間がかかるので、自分でやってて「これでいいのか。もしかしてもっといいやり方があるんじゃないか。何か違うやり方をしてるせいで時間がかかり過ぎているんじゃないか」と不安になってきたので改めて読んでみた。
読み直した感想
読み直しても思ったが、やっぱり「当たり前のこと」が書かれてる本だと思う。でも自分のやってることが間違ってないかを確認するのには良かった。間違ってないというか、少なくともこの本に書かれてる内容のうちのいくつかは実践していたもので、今も実際に使ってるから自分の方法自体は大きく外れないな、と思った。
具体的には「第12章 1箇所にたくさんの変更が必要ですが、関係するすべてのクラスの依存関係を排除すべきでしょうか」に出てくる割り込み点と絞り込み点を出してみるというところだ。割り込み点というのは「特定の変更による影響を検出できるプログラム上の場所」で、絞り込み点は「複数ある割り込み点のうち、すべての変更の影響を検出できる場所」のことで、特に絞り込み点は影響スケッチという「メソッドやクラスが呼び出される様子を矢印を引いてわかるようにした絵」の中で、自然と矢印が集中してくるところに当たる。私自身は影響スケッチというものは特に書いてなくて、以下のような箇条書きをよく使っている。
ClassA::methodA
ClassB::methodB
ClassC::methodC
ClassD::methodD
この箇条書きは methodA
が methodB
の中と methodD
の中で呼ばれていて、さらに methodB
は methodC
で呼ばれている、ということを表す。ClassX::
というのはそれぞれのメソッドがどのクラスにあるメソッドなのかを表している。クラス化されてなかったらファイル名を直接書いたりもする。ここから methodA
の変更は最終的に methodC
と methodD
に影響を与えることがわかる。だが methodD
の中に条件文があって、特定の条件では methodA
が呼ばれないことがわかり、かつ今回加えようとしている変更がまさに呼ばれないパターンに該当する場合には methodD
は影響を与える場所としては除外できる、みたいなことを調査しながら箇条書きを編集していく。例えば「 ClassD::methodD
無視」とか自分にわかる書き方でいい。 methodA
に変更を加えると必ず methodC
に影響が伝わることがわかったなら、絞り込み点は methodC
となって、とりあえず methodC
のテストを書いたら、仮に methodA
のテストが書けなくても動作は一旦保証できるので、 methodA
の変更でおかしなことがあったらわかるね、というやり方になる。もしここで ClassB::methodB
が他のメソッド内でも呼ばれることがわかったら ClassC::methodC
のテストよりも ClassB::methodB
のテストを書けるなら書くようにする。そうすることで影響範囲をまさに『絞り込む』。
影響スケッチ自体は書いたことが全くなかったわけではなく何度かはノートに書いたりしていたが問題があって、wikiとかに画像をのせても大体見にくくて「どうやって調べたか」聞かれた時にパッと見でわからずに結局説明し直さなきゃいけなくなることがあることだ。そもそも見にくいということはその時点でもう影響範囲がでかすぎるので、変更を加える場所自体を再考したほうがいいわけだが、「ここを変更したら他を変えなくていいじゃん」といって粘られることとかもあるので、まだ人に見せられる範囲に落とし込めそうで説明に使えそうかなぁと考えていたら自然と箇条書きになった。自分しか見ない影響スケッチなら自分一人のノートに書きなぐってしまえばいいと思ってたし、実際影響スケッチとはそうやって書捨てるようなものではあるが、影響範囲が広がりすぎると自分で描いててよくわからなくなってきて、いらないところを削って書き直して…とやってるうちに、「あれ?結局どの絵を見るのが一番正しいんだっけ?」みたいにもなってくるので、割と箇条書きはシンプルで使い易い気がしている。
絞り込み点を探すのは大事なことだとは思うが、そこの部分のテストがいつでもすんなり書けるように設計されてないことによく遭遇するので、もし初めに見つけた絞り込み点のテストが書けなさそうなら「どこのテストなら書けそうか」で探るのも結構やる。そうすると ClassB::methodB
よりも ClassC::methodC
かなぁとか考えてくうちに絞られてきたりする。あとテストがあるメソッドは経験的にテストがないメソッドよりも使い易い。
といった感じで12章とかはまさにこういう試行錯誤の話(というか全章に渡ってつらい試行錯誤すること多いよねって話)が書かれてて、悲しいけど「みんなつらいんだな。やっぱ時間かかっちゃうよな。」としぶしぶ納得する。
レガシーコードに触れたことがない人だったら悩まないのかもしれないが、これから触るかもしれない人は一度読んでみた方がある程度時間短縮になるかもしれない。いきなりコードを読み進めてもスパゲッティで迷子とか本当にあるある*2なので、心構えというかどう立ち向かえば突破できそうかヒントを多少知っておくだけでも、いきなり心折られるよりマシだと思う。正直いつも心折れてなんかやってられないから自分のやり方が合ってるか迷った時に精神安定剤的な使い方としてこの本を読むのもアリな気がする。これを読んで逆に「なんでこの章を読んでなかったんだ!早く読んでおいたら良かった!」と逆に発狂する可能性も微レ存。諸刃の剣。私は安心した。よかった。
あと一応、この本は手段であって答えではない。この本に書かれてることをそのまま使えるかどうかはケースバイケースだ。「読んでみたけど答えが書いてなかった」という人にこの本は向いてないと思う。ていうか答えがそんな簡単に転がってるならレガシーとか言わないと思うの。
読む順番について
この本の見出しは「何に悩んでいるか」というトピック形式で書かれているので、自分が抱えている問題に合わせて読みたい章を選ぶといい。でもどれも気になって結局どこから読み始めたらいいのかわからないけど全部を初めから読み通すのは面倒くさいよというそこの私。そう私だ。一応その目安になるページは第2章の『レガシーコードの変更手順』にある。
- 変更点を洗い出す
- 16: 変更できるほど十分に私はコードを理解していません
- 17: 私のアプリケーションには構造がありません
- テストを書く場所を見つける
- 11: 変更する必要がありますが、どのメソッドをテストすればいいのでしょうか
- 12: 1箇所にたくさんの変更が必要ですが、関係するすべてのクラスの依存関係を排除すべきでしょうか
- 依存関係を排除する
- テストを書く
- 13: 変更する必要がありますが、どんなテストを書けばよいのかわかりません
- 変更とリファクタリングを行う
- 8: どうやって機能を追加すればよいのでしょうか
- 20: このクラスは大きすぎて、もうこれ以上大きくしたくありません
- 21: 同じコードをいたるところで変更しています
- 22: モンスターメソッドを変更する必要がありますが、テストを書くことができません
上の順番で読んでくと大体網羅できる。14/25章なので読む量を少しは減らせる。感想で述べた第12章は「テストを書く場所を見つける」という項目に含まれる。もういいかなと思ったら、今はもうこの本にお世話になる時じゃないんだと思う。