今の職場でコードを刷新することになり、その準備として読んだのが『レガシーコード改善ガイド』です。
結論から言うと、テストのない古いコードを、壊さずに変えていかないといけない人に合う1冊です。ただし449ページと厚く、例も古めなので、頭から通して読むより、困ったときに引く本として使うほうが向いています。
いちばん役に立ったのは「時間がないのに変更しなければなりません」の章でした。読んでから、コードを変えるときの手順を2つ変えています。
PARTS LIST /目次
レガシーコード改善ガイドはどんな本か
書誌情報と目次は、紀伊國屋書店のページによるものです。内容説明では、構造が複雑で理解できないようなコードを、理解し、テストできるようにし、リファクタリングを可能にし、機能を追加できるようにするテクニックを紹介する本とされています。
特徴的なのは第2部です。章題が「時間がないのに変更しなければなりません」「このクラスをテストハーネスに入れることができません」のように、現場の困りごとそのものになっています。よくある質問の一覧のように、自分の困りごとから章を探せる作りです。
読んだきっかけ|コード刷新のため
今の職場でコードを刷新することになり、古いコードを壊さずに変える方法を知りたくて読みました。
役に立ったところ|時間がないのに変更しなければならないとき
いちばん役に立ったのは、第2部の最初の章「時間がないのに変更しなければなりません」です。テストのない大きなメソッドに機能を足さないといけない、でも全体をテストで覆う時間はない。そんなときの進め方の章です。
この章は、原書では第6章「I Don't Have Much Time and I Have to Change It」です(出版社Pearsonの書籍ページの目次による)。原書の目次では、この章に Sprout Method・Sprout Class・Wrap Method・Wrap Class という4つの手法の節が並んでいます。
4つに共通するのは、テストのない古いコードには最小限しか触らず、新しく書く部分をテストできる場所に置くことです。全体をきれいにする時間がなくても、足した部分だけは確かめられます。
読んでから変えたこと|テストで固めてから、切り出して足す
読んでから、コードを変えるときの手順を2つ変えました。職場のコードは載せられないので、説明用のJavaのコードで見せます。
1. 変更の前に、今の動きをテストで固める
直す前に、今のコードがどう動いているかをテストに書き留めるようにしました。期待値は「仕様として正しい値」ではなく「今のコードが返す値」です。これがあると、変更のあとで今までの動きが変わっていないかを確かめられます。
// 直す前に、今の動きをそのままテストに書き留める
@Test
void 今の送料計算の結果を固定する() {
ShippingCalculator calculator = new ShippingCalculator();
// 期待値は「正しい値」ではなく「今のコードが返す値」
// いったん実行して出た値を書き写す
assertEquals(500, calculator.fee(2999, "TOKYO"));
assertEquals(0, calculator.fee(3000, "TOKYO"));
assertEquals(800, calculator.fee(2999, "OKINAWA"));
}
第2部には「変更する必要がありますが、どんなテストを書けばよいのかわかりません」「どうすれば何も壊していないことを確認できるでしょうか?」という章もあります。テストの書き方の考え方は単体テストの考え方/使い方の書評でも書いています。
2. 既存のコードに直接足さず、切り出して足す
もう1つは、既存の長いメソッドに処理を書き足さず、新しいメソッドに切り出すようにしたことです。たとえば「同じ注文番号が2回来たら、2回目は捨てる」という処理を足すとします。
// 既存の長いメソッドに、新しい処理を直接足す
public void registerOrders(List<Order> orders) {
// ……テストのない処理が100行……
// 追加:同じ注文番号が2回来たら、2回目は捨てる
Set<String> seen = new HashSet<>();
List<Order> unique = new ArrayList<>();
for (Order order : orders) {
if (seen.add(order.number())) {
unique.add(order);
}
}
// ……テストのない処理が続く……
}
これを、新しいメソッドに切り出して、既存のメソッドからは呼ぶだけにします(Sprout Methodの考え方)。
// 新しい処理は、新しいメソッドに切り出す
public void registerOrders(List<Order> orders) {
// ……既存の処理……
List<Order> unique = removeDuplicates(orders); // 既存のメソッドへの変更は、この1行だけ
// ……既存の処理……
}
// 切り出したメソッドだけなら、テストが書ける
List<Order> removeDuplicates(List<Order> orders) {
Set<String> seen = new HashSet<>();
List<Order> unique = new ArrayList<>();
for (Order order : orders) {
if (seen.add(order.number())) {
unique.add(order);
}
}
return unique;
}
既存のメソッドへの変更は1行だけになり、足した処理は removeDuplicates だけをテストすれば確かめられます。
合わなかったところ|例が古く、厚い
合わなかったのは2つです。1つは、例が古く、C++のコードが多くて読みにくかったこと。もう1つは、449ページと厚く、通して読むのが大変だったことです。
日本語版は2009年、原書は2004年の本です。言語やツールの事情は、今とはかなり違います。
第2部の章題は、現場の困りごとそのものです。通して読もうとせず、今困っていることに近い章題を探して、そこから読むのが楽です。コードの例は、考え方だけを持ち帰り、今の言語に置き換えて読んでください。
困りごと別の読み方
第2部の章題から、よくある困りごとを選んでまとめました。
依存関係を切り離す具体的な手法は、第3部「依存関係を排除する手法」にまとまっています。Javaで依存を外から渡す基本はDI(依存性の注入)とはにまとめています。
向いている人・向いていない人
- 向いている人:コードの刷新や保守で、テストのない古いコードを変えないといけない人
- 向いていない人:最新の言語やツールの例で学びたい人。頭から通して読める薄い本がほしい人
あわせて読みたい
- 単体テストの考え方/使い方の書評:固めたテストを、壊れにくく保つ考え方
- ドメイン駆動設計入門の書評:刷新したあとの、コードの置き場所の考え方
- 良いコード/悪いコードで学ぶ設計入門の書評:新しく書く部分を、変更しやすく書く
読んだ本はほかにも、トムの本棚に並べています。
よくある質問
Q. 2009年の本ですが、今でも役に立ちますか?
テストのないコードを壊さずに変える、という考え方は今も使えます。ただ、例が古く、C++のコードも多いので、考え方だけを持ち帰って今の言語に置き換えて読むことになります。
Q. 全部読む必要はありますか?
ありません。第2部は困りごとが章題になっているので、今困っていることに近い章から読めます。私も、いちばん役に立ったのは「時間がないのに変更しなければなりません」の1章でした。
Q. 原書はありますか?
あります。Michael C. Feathers の「Working Effectively with Legacy Code」(Pearson)です。
| REV. | DATE | 内容 |
|---|---|---|
| 2 | 2026-10-16 | 図解を描き直し(図面のデザインにそろえた) |
| 1 | 2026-10-13 | 初版 |
既存のメソッドへの変更は呼び出しの1行だけ。切り出したメソッドには、テストを1つ書いておく。それだけで、足した部分は確かめられます。
続きを追う:X(@Tom_Java_Tech) / RSS

