
2026/07/31 0:10
リファクタリングの経済的効果
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
AI 支援によるソフトウェア開発における画期的な進歩が達成され、150,000 行に及ぶ Rust アプリケーションの再構築に必要な巨大なトークン消費量を 83% 削減しました。このコスト削減の主な要因は、より賢い生成ではなく、コードモジュール性の向上です。「クラス抽出」などの戦略を用いて、単一の大規模ファイル(17,000 行)を 19 つの小規模なファイルに分割したことで実現されました。この分割により、入力トークンコストが大幅に削減されました(約 15.9 万から約 2.7 万へ)。ただし、出力コードの生成にかかるコストは依然として比較的高く、変更ごとに約 1,700 から 2,500 トークン程度維持されています。現在の AI エージェントはまだ、自律的な計画立案や完全なコードインデントの処理において課題に直面していますが、この再構築の成功には直ちに実用的な価値があります。開発者は今後は、大規模プロジェクトにおいてより高速な実行時間と大幅に低い運用コストを期待できるようになりました。今後の研究では、これらの出力トークンコストの最適化に注力し、複雑な自律的なコーディングタスクに対する効率性と経済的実現性をさらに向上させる必要があります。
Text to translate:
(if needed; otherwise repeat the original):
Summary:
A significant breakthrough in AI-assisted software development has been achieved, reducing the massive token consumption required to refactor a 150,000-line Rust application by 83%. The primary driver for this cost saving was improved code modularity—splitting a monolithic 17,000-line file into 19 smaller files using strategies like "Extract Class"—rather than smarter generation. While this split drastically lowered input token costs (dropping from ~159k to ~27k per request), the expense of generating output code remains relatively constant at roughly 1,700 to 2,500 tokens per change. Although current AI agents still face hurdles in fully autonomous planning and handling perfect code indentation, this refactoring success offers immediate practical value. Developers can now expect faster execution times and significantly lower operational expenses for large-scale projects. Future research must focus on optimizing these output token costs to further enhance efficiency and economic viability for complex autonomous coding tasks.
本文
代理型工学における大規模リファクタリング実験:AI エージェントによる自動最適化とトークンコスト削減
はじめに
代理型工学(Agent Engineering)の新しい領域に適応するため、自身を支援する高度なアプリケーションを開発しました。このプロジェクトは以下の機能を備えています:
- 高品質な Web UI: ダイナミックリフレッシュ機能付き
- インタラクション機能: ルックアップウィンドウ、モーダルウィンドウ
- 堅牢性: 自動保存機能、外部システム連携
- 高度な処理: 機械学習、テキスト解析、バックグラウンドジョブ
- デプロイメント: 完全自動化された環境設定
技術スタックと規模
- 全コード行数:約 15 万行
- Rust: 約 12 万行(大半)
- TypeScript: 一部
- Terraform: インフラ構成
- 開発体制:AI エージェントのみによる自動生成(Claude Code, Cursor)
- 人間レビュー:コード確認なし(時折の興味本位の眺めを除く)
問題発見:肥大化する単一ファイル
開発途中、データアクセス層において深刻な問題が見受けられました。
現状の状況
- 肥大化の兆候: エディター内でスクロールが追いつかず、ファイル 4,000 行付近で表示に支障が出た。
- 規模: データアクセス層単一ファイルが 17,155 行 に達した。
- 原因:
- 機能追加に伴う単純なコードの積み重ね
- HTTP リクエスト設定、JSON エンコード/デコード処理の重複
この状態を放置すれば、エージェントのトークン消費とエラー率が悪化する懸念がありました。
リファクタリング実験:戦略と手法
目標
リファクタリングによる現在の入力トークンコスト削減および、将来のメンテナンスにおける継続的なコスト低減。
実験の独自性
- バイアスフリー: 人間が介入せず、前段階の学習で汚染されない環境。
- 再現性: 同じプロンプトで異なるエージェント(サブエージェント)に適用し、結果を検証。
プロセスフロー
- 計画策定
- 厳格なリファクタリング計画を立案する。
- 代表例変更の定義
- 単一のプロンプトで記述された具体的な変更方針を決定する。
- ベースライン計測
- サブエージェントにプロンプトを実行させ、トークン消費量を含めて報告させる。
- 破棄とループ処理
- 結果を破棄し、計画のステップごとに反復処理を行う:
- 単一ステップ適用 → 実行時のコスト計測 → 破棄
- 結果を破棄し、計画のステップごとに反復処理を行う:
- 計測と記録
- トークン消費量、実行時間、コード行数(LoC)を各段階で記録。
技術的制約と対策
- トークン計測の課題: クロード(Claude)には正確なリアルタイムトークンカウント機能がないため、以下の手法を採用。
- 送信・受信文字数を報告し、4 で除算して近似トークン数を算出(tiktoken 方式)。
実験結果:明確なコスト削減効果
リファクタリングステップごとに計測された指標の変遷です。
| ステップ | 対象 | Rust 全体 (LoC) | 最大ファイル (LoC) | 入力トークン/変更 | 出力トークン/変更 | 実行時間 (秒) |
|---|---|---|---|---|---|---|
| ベースライン | 全体 | 50,359 | 17,155 | 159,564 | 1,705 | 342 |
| ステップ 1 | FirestoreClient | 49,910 | 16,706 | 155,205 | 1,723 | 530 |
| ステップ 2 | extract_doc_id | 49,766 | 16,562 | 159,227 | 2,105 | 574 |
| ... | ... | ... | ... | ... | ... | ... |
| ステップ 8 | traits.rs | 49,712 | 13,845 | 132,558 | 1,723 | 446 |
| ステップ 15 | store/ split | 49,812 | 3,695 | 27,360 | 2,113 | 454 |
(注:最終ステップ以降の詳細な中間データは省略されています)
主要な成果
- 入力トークンの急降下:
- ベースライン:159,564 トークン
- 最終リファクタリング:27,360 トークン
- 削減率:約 83%(132,204 トークンの削減)
- コード構造の変化:
- 単一ファイル(17K 行)から、19 の Rust ファイルへと分散。
- 最大単一ファイルはテストライブラリとなり、実装部がさらに細分化された。
コスト試算
- Sonnet 5 の価格設定(約 $3/MTok、0.39 ドル/トークン)を仮定すると:
- 節約額: 約 39 セント(一時的なコストの低減)
- 重要な効果: 将来的な変更に対する「銀行預金」となる低コスト基盤の確立。
考察:なぜリファクタリングが有効なのか
「読み込み量」の削減
- エージェントは、変更に関連する最小限のコードセクションのみを読み込むようになりました。
- データアクセス層全体のコード量は一定ですが、関連ファイルセットの特定精度が上がったためです。
リファクタリングの質と計画性
- ランダムな分割では効果なし: 単にファイルを小さくしても、エージェントが関連コードを探索する時間は減りません。
- 自然な進化: この節約は意図せず、典型的なリファクタリング(重複排除 → コア機能の分離)の結果として発生しました。
- クロードの特性: エージェントは「何が最適か」を自ら導き出せず、人間のガイドが不可欠です。
出力トークンの課題
- 入力トークン(5 倍高価)の削減は達成されましたが、出力トークンの削減には限界がありました。
- より複雑なサンプル変更によるノイズ分析が必要です。
プロセス上の注意点と教訓
クロード・コードの弱点
- 自律的な判断欠如: 「関数抽出」や「クラス分割」といったリファクタリングを、人間が明示的に指示しないと発見できません。
はより高度な理解(クライアントクラスの全体抽出)を示しました。Claude.ai
- 機械的適用の限界: リファクタリングは
,grep
スクリプトによる手作業に近い処理が行われたため、インデントエラーや見落としが発生しました。sed- 最も価値のあるリファクタリングが初期パスで見逃され、後続ステップで再適用が必要でした。
実験の環境制約
- 所要時間: 約 8 時間(6 時間 40 分後の介入なし完了)
- ボトルネック:
- ホテルの低速 WiFi
の一時ビルドキャッシュが肥大化し、テスト実行に深刻な影響を与えた。cargo
まとめと展望
結論
- この実験は、**新規プロジェクト(グリーンフィールド)**において、AI エージェントによる自律的リファクタリングが可能であることを実証しました。
- 83% の入力トークン削減は、長期的な運用コスト低下と開発効率向上に寄与します。
今後の課題
- 正確な計測: 実験全体のトータルトークン消費量の正確なカウントが今後必要です(上限:500 万トークン)。
- 広範な検証: より複雑な変更や、異なるアプローチでの相対的価値の検討が必要です。
これは始まりに過ぎません。
付録:使用されたプロンプトと手法の詳細
代表例の変更(サブエージェントへの指示)
~/dev/your-project-name の Rust プロジェクトにおいて作業しています。 既存のパターンに従って、Firestore レヤーに ItemWatchStore という新しい公開 async トレイトを追加してください。そのトレイトには以下の 3 つのメソッドを持たなければなりません: async fn watch_item(&self, item_id: &str, user_id: &str) -> Result<()> async fn unwatch_item(&self, item_id: &str, user_id: &str) -> Result<()> async fn watched_items_for_user(&self, user_id: &str) -> Result<Vec<String>> ウォッチは "item_watches" Firestore コレクションに格納されます。各ドキュメントには以下のフィールドがあります:itemId(文字列)、userId(文字列)、CreatedAt(タイムスタンプ)。ウォッチレコード用の Rust ストラクチャはありません — メソッドは Vec<String>(アイテム ID)を返します。 FakeStore および FirestoreStore の両方にこのトレイトを実装してください。(FakeStore では in-memory Vec<(String, String)> フィールドを FakeStoreInner に追加し、FirestoreStore では同ファイル内の他のストア実装と同じ HTTP パターンを使用します。) レスポンスの最後に必ずこの JSON ブロックを出力してください(実際の値に埋め込んでください): { "files_read": [ {"path": "src/firestore.rs", "chars": 123456}, ... ], "response_chars": 7890 } 変更をコミットしないでください。コードを書いたら終了してください。
リファクタリング計画のプロンプト
リファクタリングとは「証明可能な正則性を保持する一連のコードエディット」という厳格な定義に従い、Martin Fowler の「Refactoring」(2 版)を源として、@src/firestore.rs を検討してください。これは 17K 行の Rust ファイルです。そのような長さはありえません。おそらく内部言語を使用してクエリを構築・管理していないはずです。ファイルを分割することなく、インターフェースを変更せずに当該ファイルの行数を大幅に削減するための一連のリファクタリングを提示し、記述してください(実行しないでください)。
具体的なリファクタリングステップの概要(Martin Fowler 基準に基づく)
- Extract Class (7.5):
を抽出して輸送層とドメインロジックを分離。FirestoreClient - Extract Function (6.1):
,extract_doc_id
, クエリヘルパー、ファクトリ関数を抽出。new_link - Replace Inline Code with Function Call (8.5): JSON マクロ呼び出しを関数呼び出しに置換。
- Move Function:
- コード定義と実装の分離(
,src/firestore/mod.rs
,queries.rs
,traits.rs
などへ分割)。codec.rs - テストコードのモジュール内移動による整合性向上。
- コード定義と実装の分離(