Skip to content

필사 모드: リファクタリングの経済学、コストはいつ回収されるか — 変更頻度で計算する方法

日本語
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

はじめに — 83パーセント削減、そして39.7セント

2026年7月30日、martinfowler.comにThoughtworksのGiles Edwards-Alexanderが書いたThe Economic Benefit of Refactoringが掲載されました。実験設計が見事です。AIエージェントだけで作られた15万行のアプリケーションから、問題のある1万7,155行のRustデータアクセスモジュールをひとつ選び、「代表的な変更」を求めるプロンプトをひとつ固定したうえで、15段階にわたってリファクタリングしながら、各段階で同じプロンプトを再度実行し、トークン消費量を測定しました。段階と段階のあいだで変更内容は破棄し、エージェントが学習できないようにしました。

結果は実に引用しやすいものです。入力トークンは159,564個から27,360個へ、132,204個(83パーセント)減りました。そしてハッカーニュースの議論ですぐさま出てきた反論も同じくらい引用しやすいものです — その節約額は当時の価格で39.7セントです。時給100ドルのシニア開発者がこのリファクタリングを指示・監督した8時間と比べると、回収には数千回の変更が必要になります。

どちらの数字も正しいのです。そしてこの対比こそが、リファクタリング論争が20年経っても結論に至らない理由をまさに示しています。コストは目に見え、便益は将来に散らばっているため、便益の数え方しだいで答えが逆転するのです。 この記事はその数え方を扱います — 新しい実験が実際に測定したもの、既存のエビデンスがどれだけ薄いか、回収期間を計算する式、利子の比喩が崩れる地点、そしてマネージャーの前で美学の代わりに使える数字の取り出し方まで。

新しい実験が実際に測定したもの — そして著者自身が付けた注記

まず、この実験が測定した対象を正確にしておきましょう。人間の理解時間ではなく、エージェントの入力トークンです。 つまり「この変更を行うにはどれだけのコードを読む必要があるか」の代理指標です。この定義がこの実験を興味深いものにしています。人間は同じファイルを二度目に読むときは速くなりますが、エージェントは毎回ゼロから読むため、構造のコストが変更のたびに正直に課金されます。 人間を対象にした実験では学習効果のせいで切り分けにくい信号が、ここではくっきりと見えるのです。

数字から読み取れることが、あと何点かあります。

最大の削減を生んだのは、ファイルをドメインに沿って分割した段階でした。 15段階のうち最後のひとつの段階が、入力トークンを107,205個から27,360個まで落としました。著者はここで重要な注記を付けています — ファイルをやみくもに細かく分けても、エージェントが複数のファイルを探し回る羽目になるだけで、あまり役に立たないというのです。それより前の段階(重複の抽出のような局所的な整理)が、最後の分割を可能にする準備作業だったということです。つまり、効果は最後の段階に集中して現れますが、その段階だけを単独で行うことはできません。

出力トークンはほとんど変化しませんでした(およそ1,700~2,460個)。リファクタリングが「読むコスト」は減らしたものの「書くコスト」には影響しなかったということであり、著者もこの点については結論を出していません。

そしてコードの総量は減りませんでした。最大のファイルは17,155行から9,269行まで下がりましたが、データアクセス層全体では19ファイルにわたっておよそ16,500行とほぼ変わっていません。ハッカーニュースにはこの点を指摘するコメントがあり、リファクタリングは通常コード量を減らすという通念とは食い違うと述べていました。

著者自身が付けた注記はかなり長く、そのまま書き写す価値があります。

  • トークンの数え方は近似値です。文字数を4で割る方式を使ったとしており、著者はリアルタイムで正確にトークンを数える信頼できる方法がなかったと書いています。ハッカーニュースでは「ちゃんとしたトークナイザーライブラリがあるのになぜ」という反論が出ました。
  • グリーンフィールドのアプリひとつ、開発者ひとり、モジュールひとつ、変更の種類ひとつに関する単一の実験です。
  • リファクタリングの計画を立てて実行するのにかかったトークンは数えていません。上限を500万トークンと見積もっていますが、検証された値ではありません。
  • そしてもっとも興味深い注記 — エージェントはリファクタリングが得意ではありませんでした。 どのリファクタリングが適切かを自分で判断できず、段階ごとに人間が明示的に指示する必要があり、実際の変換作業はgrepとsedを使うPythonスクリプトで行われ、インデントでたびたび混乱を起こしました。もっとも価値のあったリファクタリングは最初は見落とされ、あとになって改めて適用する必要がありました。

要するにこの記事は、「リファクタリングは得になる」ことの証明ではなく、エージェントベースの開発において構造コストを測定するひとつの方法を提案した、最初の試みです。著者自身も「ひとつの実験にすぎないが、興味深い第一歩」と書いています。そう読むのが正しいでしょう。

既存のエビデンスは思ったより薄い

リファクタリングが得だという主張には、40年分の直感と、驚くほど乏しい定量的根拠が付いて回ります。実際に引用に値するものを並べると、リストは短いものになります。

もっとも頻繁に引用されるのは、Adam TornhillとMarkus BorgによるCode Red: The Business Impact of Code Quality(2022)です。39の商用プロダクションコードベース、30,737ファイルを対象に、ソース分析とバージョン管理履歴、Jiraのイシューを組み合わせて三つのことを報告しました — 品質の低いコードは欠陥が15倍多く、イシュー解決には平均で124パーセント長くかかり、最悪のサイクルタイムは9倍にまで広がるというものです。

この研究は真摯なものですが、限界もはっきりしています。コード品質の測定には著者たち自身が作った商用ツールの指標を使っており、関係は相関であって因果ではありません。そもそも難しい問題領域が、汚いコードと長い解決時間を同時に生み出した可能性も排除されていません。そして決定的なのは、この研究が測定したのは、「品質の低いコードのコスト」であって「リファクタリングの収益」ではないという点です。 両者は別物であり、リファクタリングにはそれ自体のコストと回帰リスクが別途伴います。

Martin Fowler本人の立場」も引用する価値があります。Is High Quality Software Worth the Cost?(2019年、2024年にTornhillとBorgの研究を引用して更新)で彼は設計スタミナ仮説を提示すると同時に、こう認めています — ソフトウェアチームが届けた機能を測定する方法がないため、その結果に確かな数字を付けることは不可能だということです。彼が示すグラフは例示であってデータではありません。この分野でもっとも影響力のある主張の著者自身が、根拠の性質をこれほど明確にしているのは、むしろ信頼に値する態度です。彼が付け加える実務的な観察がひとつ役立ちます — 熟練した開発者は、悪いコードが自分を目に見えて遅くしていることを「数週間のうちに」実感するのであり、したがって品質とコストを交換する区間そのものがそれほど長くないということです。

反対方向のエビデンスも実在します。 リファクタリングとバグの関係を扱った差分再現研究(ESEC/FSE 2020)は、特定のリファクタリングの種類、とりわけ継承階層に触れる作業が、新しい欠陥の導入と頻繁に関連していると報告しています。MSR 2022のIs refactoring always a good egg?は、リファクタリングがコードスメルを除去するか、まったく影響を与えないかのどちらかがほとんどであり、これは先行研究と食い違うと述べています。より最近の研究は方法論上の問題を指摘しています — リファクタリングとバグ修正、バグの混入が同じコミットのなかで絡み合っており、効果を切り分けること自体が難しいというのです。

正直な要約はこうです。質の低さが高くつくという証拠はあり、リファクタリングがそのコストを回収するという一般的な証拠は薄く、ある種のリファクタリングはリスクを増やします。 だから「リファクタリングは良いものだ」という前提から議論を始めてはならず、ケースごとの計算が必要です。

回収期間の計算 — 変更頻度が乗算項です

エビデンスが薄いときに使える方法は、一般命題の代わりに特定のモジュールについて計算することです。必要な項はたった五つです。

年間節約額は二つの筋から生まれます。ひとつは変更コストの節約、もうひとつは欠陥コストの節約です。

年間節約額 = (C × T × S × H)  +  (D × F × K)
  C : このモジュールに触れる年間の変更回数        (gitの履歴から取得)
  T : 変更1件あたりの平均所要時間                  (イシュートラッカーから取得)
  S : そのうち構造のせいで無駄になっている割合      (推定。0.2~0.5が保守的)
  H : 時間あたりの人件費
  D : このモジュールに由来する年間の欠陥数
  F : 欠陥1件あたりの総コスト(対応 + 手戻り + 顧客影響)
  K : リファクタリングで減ると見込まれる欠陥の割合  (推定。0.3なら楽観的)

リファクタコスト = (R × H)  +  (P × F_reg)
  R : リファクタリング作業時間(テスト強化を含む)
  P : 回帰を起こす確率 × 想定件数
  F_reg : 回帰1件あたりのコスト

回収期間(月) = リファクタコスト / (年間節約額 / 12)

ここで構造的に重要なのは、Cが乗算項だという事実です。 Cがゼロなら、T、S、Hがどれだけ大きくても節約はゼロになります。これが「変わらないコードは整理する価値がない」の数学的な表現です。5年前に書かれて以来誰も触れておらず、問題なく動いている汚いモジュールは回収されません。美学的に気に障ることと経済的に損であることは別の問題であり、この式はその二つを分離してくれます。

三つのモジュールについて計算してみると、差はきわめて明確になります。時間あたりの人件費を₩100,000、欠陥1件を₩2,000,000、Sを0.3、Kを0.3とした例です。リファクタコストには人件費の項だけを入れ、回帰リスクの項は除いているため、実際には以下の回収期間より長くなります。

モジュール年間変更 C1件あたりの時間 T年間欠陥 D年間節約額リファクタコスト回収期間
注文処理(ホットスポット)84回6時間11件約₩21,720,000160時間 = ₩16,000,000約9か月
レポートジェネレーター12回8時間2件約₩4,080,000120時間 = ₩12,000,000約35か月
レガシー精算バッチ1回20時間0件約₩600,000200時間 = ₩20,000,000約33年

三行目がこの表の要点です。レガシー精算バッチはおそらくコードベースのなかでもっとも読むのがつらいファイルであり、チームでもっとも頻繁に話題に上る負債でしょう。そして、触れてはいけないコードです。回収期間がサービスの寿命より長いのです。

数字を作るときに注意すべき点が三つあります。Sは正直に低く見積もってください。 Code Redの124パーセントをそのままSに換算すると0.55になりますが、それは相関データから出た上限であって、あなたのモジュールの値ではありません。Pをゼロにしないでください。 先に見た反対方向の研究が語っているのはまさにこの項です。とりわけ継承階層に触れるリファクタリングにはリスクプレミアムを乗せてください。そして計算結果が「やらない」と出たら、その結論を受け入れてください。 この計算の価値は承認を得ることにあるのではなく、どこに使わないかを決めることにあります。

利子の比喩が機能するところと崩れるところ

技術的負債という言葉は1992年にWard Cunninghamが作り、今ではこの議論の基本語彙になっています。この比喩は実際に二つのことをうまくやってのけます — 今すぐ速く進む代償として後でより多く払うという構造を財務の言葉に翻訳し、そのおかげでエンジニアリングの外にいる人にも議論が通じるようになります。それだけでも十分に有用です。

ただし、三つの点で崩れます。

第一に、利子は時間ではなく接触に付きます。 金融の負債はじっとしていても利子が積み上がりますが、技術的負債はそのコードに触れたときにだけ請求されます。Cunningham自身の言い回しも「きちんとしていないコードに費やすすべての時間が、その負債の利子である」というものです — 時間が経過することではなく、時間を使うことが条件なのです。前節でCが乗算項である理由がこれであり、この違いひとつのために「負債は早く返すほうがいい」という金融的直感はコードにおいては当てはまりません。

第二に、元金を計算できません。 利率も、返済スケジュールも、満期もありません。負債の総額を金額に換算してダッシュボードに表示するツールはありますが、その数字の分母が何なのかを説明できる人はまれです。比喩をモデルと取り違えた瞬間、この指標は管理の対象になり、管理の対象になった指標は最適化され始めます。

第三に、線形ではありません。 結合度の高い箇所にある負債は、局所的な負債よりはるかに高くつきます。同じ100行の汚いコードでも、20個のモジュールが依存する場所にあれば、コストが違ってきます。金融の比喩にはこの「位置」という概念がありません。

そして、Cunningham本人が何度も訂正してきた誤解がひとつあります — 彼の言う負債とは、あとでちゃんとやり直すつもりでわざと雑に書くことではありません。 早くリリースしてドメインについての理解を得て、その理解をコードに反映するためにリファクタリングする、という循環を意味していました。つまり元々の比喩において、負債は「悪いコード」ではなく、まだ反映されていない学びだったのです。 この定義が実務的により有用なのは、何を整理すべきかを教えてくれるからです — 今わたしたちがドメインについて知っていることと、コードが前提としていることとがずれている場所です。

マネージャーを説得する方法 — 美学ではなく履歴で

「このコードは汚い」には説得力がありません。聞く側に検証する手段がなく、好みの問題として片づけられてしまうからです。代わりに、前節の計算式に入れる値を実際のデータから取り出してきましょう。すべて監査可能な数字です。

# 1) 変更頻度 C: 過去12か月のファイル別コミット数トップ20
git log --since="12 months ago" --name-only --pretty=format: \
  | sed '/^$/d' | sort | uniq -c | sort -rn | head -20

# 2) 欠陥関連の変更 D: バグ修正コミットだけを絞り込んで同じ集計
#    (コミット規約があれば --grep、なければイシューキーのパターンで)
git log --since="12 months ago" --name-only --pretty=format: \
  --grep='^fix' --grep='hotfix' --grep='BUG-' \
  | sed '/^$/d' | sort | uniq -c | sort -rn | head -20

# 3) ホットスポット: 変更頻度が高いファイルのうち大きいものだけを残す
git log --since="12 months ago" --name-only --pretty=format: \
  | sed '/^$/d' | sort | uniq -c | sort -rn \
  | awk '{ n=$1; f=$2; cmd="wc -l < " f; cmd | getline loc; close(cmd);
           if (loc > 500 && n > 20) printf "%5d changes  %6d loc  %s\n", n, loc, f }'

この出力をそのまま持っていけば、会話が変わります。「注文処理モジュールは過去12か月で84回修正され、そのうち23回がバグ修正であり、P2インシデントの31パーセントがこのファイルを経由しています」は検証可能な言明です。ここに回収期間をひとつ添えれば、それは承認のお願いではなく投資提案になります。

次に添えるべきなのが、範囲を区切った実験です。 全面的な整理を求めるのではなく、ホットスポットひとつに決まった時間を割り当て、リードタイムの前後を測ると提案しましょう。失敗すればその範囲で終わり、成功すれば次のラウンドの根拠になります。先に見た新しい実験が実務に示唆することもここにあります — 「同じ変更要求をリファクタリングの前後で一度ずつ実行してみること」が、もっとも安上がりな測定方法です。エージェントを使っているならトークン数が、人間だけで進めているなら最初のコミットまでの時間が代理指標になります。

最後に、議論に勝とうとしないでください。三つのモジュールを計算し、二つは「やらない」と結論づけてひとつだけを提案する人のほうが、全部整理すべきだと主張する人よりもずっと速く承認を得られます。

終わりに — コードは読まれるときにだけ利子を生む

まとめるとこうなります。

  • 新しく出た実験はリファクタリング15段階で同じ変更の入力トークンを83パーセント減らしましたが、金額にすれば変更1件あたり39.7セントであり、著者自身が単一のグリーンフィールド実験だと釘を刺しています。結論ではなく「測定方法の提案」として読むのが正しいでしょう。
  • 既存のエビデンスは薄いものです。質の低さが高くつくという相関的な根拠はありますが(欠陥15倍、解決時間124パーセント)、リファクタリングがそのコストを回収するという一般的な根拠はなく、一部のリファクタリングの種類は欠陥混入と関連します。
  • だから一般命題の代わりにモジュールごとに計算してください。変更頻度が乗算項であるため、変わらないコードはどれだけ汚くても回収されません。
  • 利子の比喩はマネージャーには通じますが、モデルではありません。利子は時間ではなく接触に付き、元金は計算されず、結合度に応じて非線形です。
  • 説得は美学ではなくgitの履歴で行ってください。三つの候補のうち二つを自ら落とす提案が、もっとも速く通ります。

一行に縮めるなら、リファクタリングの価値はコードの状態ではなく、そのコードを今後何回読むことになるかで決まります。

参考資料

현재 단락 (1/78)

2026年7月30日、martinfowler.comにThoughtworksのGiles Edwards-Alexanderが書いた[The Economic Benefit of Refacto...

작성 글자: 0원문 글자: 9,148작성 단락: 0/78