北欧の少し肌寒い月曜日の朝、オフィスに漂う挽きたてのコーヒーの香りと共に、僕のエンジニアとしての戦いは始まります。
海外で働いてみたいと考えている日本のエンジニアの多くは、「海外の現場=常に最新技術(モダン・スタック)を駆使し、スマートに古いものを捨て去っている」というイメージを抱いているかもしれません。しかし、現実はもっと泥臭く、そして残酷なまでに「過去」と隣り合わせです。
今回は、僕が海外の現場で実際に直面したレガシーシステムの真実と、そこで培った「亡霊」を飼い慣らすための生存戦略について、深く掘り下げてみたいと思います。
1. 「It Just Works」という甘美な罠
金融系の基幹システムを支えるデスクトップアプリケーション。表向きはWPFとMVVMパターンを駆使したプロフェッショナルな設計に見えますが、その深淵を覗けば、15年以上継ぎ足し続けられた巨大な迷宮が広がっています。
僕が今のプロジェクトに配属された際、最初に突きつけられた言葉は、エンジニアにとって最も恐ろしい免罪符でした。
「It just works(とにかく動いているから、余計なことはするな)」
表面上は平穏。バグも(表向きは)出ていない。ユーザーも慣れた手つきで操作している。だから「触らぬ神に祟りなし」という沈黙の了解がチームを支配する。しかし、その平穏の下では、技術的負債という名の腐敗がじわじわと進行しているのです。
海外のエンジニアリング文化では「効率」や「ROI(投資対効果)」が極めて厳しく問われます。一見すると、無駄なリファクタリングを避けるのは合理的です。しかし、この「合理性」がレガシーを温存する強力な言い訳になり、後に “Silent Killer” と呼ばれる致命的なコストをプロジェクトに強いることになります。
技術的負債 D の増大が生産性 P に与える影響を単純化して表現するなら、以下のような関係が成り立ちます。
P=D+αk
ここで k はチームの潜在能力、α は避けられないオーバーヘッドです。負債 D が増大すればするほど、生産性 P は反比例して低下し、最終的には「維持」だけで手一杯の状態へと陥ります。
2. 聖域の崩壊:フロントラインのホラーストーリー
「放置された亡霊」がいざ暴れ出したとき、現場ではどのような地獄が繰り広げられるのか。
ある金曜日の午後、WPFで作られた高頻度取引(HFT)の監視ダッシュボードで事件は起きました。10年以上前に退職した伝説のエンジニアが遺した CommunicationManager.cs。数万行に及ぶ「黒魔術」的なリフレクションの連鎖。そこに加えた、たった1行のデコード処理がトリガーとなりました。
制御不能なデッドロックとメモリの悲鳴
WPFの Dispatcher が複雑にネストされ、古いライブラリが Thread.Sleep を強引に呼び出す設計。修正した1行がスレッドの実行順序を狂わせ、回避不能なデッドロックを誘発しました。
さらには、イベントハンドラの解除忘れという「亡霊」が何百箇所も潜んでおり、アプリを再起動しても数分でメモリ使用量が数GBに跳ね上がります。
C#
// 典型的な亡霊の痕跡:イベントハンドラのリーク
public class LegacyViewModel : IDisposable
{
public LegacyViewModel(IMessenger messenger)
{
// 購読はするが、解除されないイベント
messenger.Register<DataChangedMessage>(this, OnDataChanged);
}
private void OnDataChanged(DataChangedMessage msg)
{
// ロジック
}
// Disposeが呼ばれない、あるいは解除処理が漏れている
public void Dispose() { /* 空っぽ */ }
}
海外のマネージャーは冷徹です。「1時間ごとに損失額が積み上がっている。誰がこのコードを承認したのか?」と問い詰めます。
最も悲惨だったのは、システムの故障以上に「エンジニアの心が折れる音」を間近で聞いたことでした。優秀なエンジニアほど、自分の技術が錆びついていくことに恐怖を感じ、LinkedIn のステータスを「Open to Work」に変えて去っていきます。残されるのは、亡霊に怯えながら現状維持しかできない組織。これがレガシーがもたらす最大の罪悪です。
3. 過去に固執することで失っている「本当の価値」
レガシーに縛られるということは、単に古い技術を使っているという以上に、「未来への切符」を一枚ずつシュレッダーにかけているのと同じです。
生産性格差という残酷な現実
最新のC# 12や .NET 8/9 を使いこなすチームは、Primary Constructors や Pattern Matching を活用して、ボイラープレートコードを劇的に削減します。一方、レガシーチームは、最新スタックのチームが1週間でリリースする新機能を、1ヶ月かけて、しかもバグを抱えながら実装することになります。
海外の市場競争は激しいものです。「昨日のアイデアが今日には形になっている」世界で、このスピードの差は、競合他社に市場を独占するチャンスを献上しているようなものです。
また、予算の割り振りを見れば、その歪みは明白です。多くのレガシープロジェクトでは、開発予算の80%が「維持(メンテナンス)」に消え、ワクワクするような「イノベーション」に回せる予算はわずか20%しか残されていません。
4. 亡霊を払い、未来のエンジニアリングを手に入れる
では、僕らエンジニアはこの亡霊にどう立ち向かうべきか。海外のシニアエンジニアたちは、ただ絶望するのではなく、極めて戦略的に動きます。
戦略1:絞め殺しのイチジク(Strangler Fig)パターン
全部を一気に作り直す「ビッグバン・リライト」は、海外でも成功率が極めて低い自殺行為です。僕たちが取るべきは、**「Strangler Fig Pattern」**です。
木に絡みつき、最終的に元の木を枯らして入れ替わるイチジクのように、新しい機能は最新の基盤(.NET 8以上)で作り、古いWPFアプリの一部を少しずつ「島」のように置き換えていきます。
戦略2:技術的負債を「お金」の話に翻訳する
エンジニアが「コードが汚いから直したい」と言っても、ビジネスサイドには響きません。亡霊を払うための予算を勝ち取るには、共通言語である「投資対効果(ROI)」で話す必要があります。
「このリファクタリングに2週間投資すれば、今後の機能追加スピードが30%向上し、保守コストを年間15%削減できます」
この交渉ができるかどうか。それが、亡霊に魂を売るエンジニアと、亡霊を統御して未来を創るエンジニアの分かれ道になります。
戦略3:レガシーを最高の「学習教材」に変える
レガシーな環境は、見方を変えれば「設計力のトレーニングセンター」です。「なぜこのコードはこれほどまでに変更しにくいのか?」という問いに向き合い、少しずつ解きほぐしていくプロセスこそが、君をどんな環境でも通用する一流のエンジニアへと成長させます。
最後に:亡霊のいない、自由な世界へ
海外の現場に幻想を抱く必要はありません。どこに行っても亡霊は潜んでいます。しかし、その亡霊を恐れず、戦略的に立ち向かう姿勢さえあれば、言葉や文化の壁なんて大した問題ではありません。
むしろ、レガシーなコードをモダンな設計へと導けるエンジニアは、世界中のどの企業も喉から手が出るほど欲しがっています。「It just works」の呪文を解いて、新しい一歩を踏み出しましょう。
その先には、自由でクリエイティブなエンジニアリングの世界が待っています。

コメント