定義
一般的には昔作られて今も使われ続けているコードを指しますが、本質はあまりに複雑だったり安全装置がなかったりして修正するのが恐ろしいソフトウェアコードのことです。著名な開発者マイケル・フェザーズ(Michael Feathers)は「テストコードのないコード」をレガシーコードと定義しました。一見正常に動いているように見えても、時間が経つにつれて新機能の追加やバグ修正がどんどん難しくなっていきます。
なぜ手を入れるのが怖いのでしょうか?
築数十年の古い家をリノベーションしようと壁を剥がしたところ、正体不明の配線がクモの巣のように入り組んでいて途方に暮れる場面を想像してみてください。レンガを一つ間違えて引き抜けば、家全体が傾いてしまうかもしれません。
レガシーコードとはまさにこのような状態です。最初にプログラムを作った人はすでに退職しており、仕様書やドキュメントもまともに残っていないケースが珍しくありません。今のところは動いていても、たった1行コードを修正しただけでまったく関係なさそうな別の機能が突然止まってしまうリスクを常に抱えています。
そのため、開発者は問題が起きても根本的な改修をためらい、その場しのぎのつぎはぎコードを付け足してしまいがちです。こうした応急処置が繰り返されるうちに、コードはますます手のつけられない怪物へと膨れ上がっていきます。
より正確に言うと
単に書かれてから年月が経っているからといって、無条件にレガシーコードと呼ばれるわけではありません。10年前に書かれたコードであっても、構造が美しくドキュメントが整っており、自動検証の仕組み(テストコード)がしっかり支えていれば、それは優れたコードです。
多くの開発者に支持されるマイケル・フェザーズの定義によると、レガシーコードを分ける決定的な基準はまさに自動化されたテストの有無です。もちろん、他者から引き継いだコードや、すでにサポートが切れた技術で作られたコードをレガシーと呼ぶなど、他の定義も広く使われています。テストコードは、自分が修正した内容が既存の機能を壊していないかをボタン一つで確かめてくれる命綱(セーフティネット)です。
この安全装置がなければ、コードに手を入れるたびに人間が一つひとつすべての機能をクリックして確認しなければなりません。結果として、失敗への恐れから誰もコードを改善できなくなり、技術的な借金(技術的負債)ばかりが雪だるま式に膨らんでいくことになります。
レガシーコードにはどう向き合うべきか?
最もよくある失敗は、「最初から全部作り直そう」とシステムを丸ごとリプレイスしようとすることです。しかし、既存のシステムが何年も耐え抜いてきた無数の例外処理やノウハウを一度にすべて再現するのは、想像以上に危険で失敗する確率も極めて高いのです。
代わりに、庭師が枝を剪定するように少しずつ安全に整えるリファクタリングの手法をとります。手を入れる必要のあるごく小さな箇所にまず安全ネット(テストコード)を張り、その部分のコード構造だけをわかりやすく整理する作業を地道に繰り返すのです。
こうして古い部品を新しい部品へと少しずつ交換していけば、走り続ける車のエンジンを乗せ換えるかのように、システム全体を安全で健全な状態に保ち続けることができます。
よくある誤解
レガシーコードは単に古いという理由だけで決まる。
古い技術で作られたコードや他者から引き継いだコードをレガシーと呼ぶこともありますが、開発現場でより重視される基準は「安全に変更できるかどうか」です。フェザーズの定義に従えば、昨日書いたコードであってもテストがなければ立派なレガシーコードになり得ます。
日常で出会う場面
銀行の基幹系システムのように、数十年前に作られた言語(COBOLなど)で書かれており、修正が極めて困難な金融システムのコードです。
作成者が退職した後、誰も動作原理を理解できず、バグが発生しても怖くて手をつけられない社内ツールのコードです。
つまり ひとことで
レガシーコードとは、安全装置や仕様書がなく修正が困難なコードのことであり、小さなテストの追加と段階的なリファクタリングによって克服していく必要があります。