Deburrエッジケーススキル:コーディングエージェントにローカルコードを体系化させる
「Deburr」と呼ばれる構造化されたコードレビュー手法を紹介する。ブランチをマージする前に、特にAIや複数貢献者によるコードから、冗長なチェック、過剰な抽象化などの「飾り」を取り除く方法を定義する。保持すべきコード、5つの装飾カテゴリ、段階的なプロセス、具体例を含む。
「Deburr」は、コードブランチから飾り(cruft)を体系的に取り除くための構造化レビュー手法です。特に、AIや複数の開発者によって生成されたコードは、フェーズごとの足場が積み重なり、全体像が見えた時点で冗長に見えることがよくあります。この手法は、狭い局所レイヤーで問題を解決する代わりに、グローバルまたは構造的に解決すべき問題を扱うコード(例えば、型システムで禁止できるはずの防御的ランタイムチェック)を特定し除去します。
装飾の定義 Deburrは以下のカテゴリを装飾とみなします:
- 型システムが禁止すべき防御的コード:より厳密な型でコンパイル時に禁止できるランタイムチェック、分岐、アサート。
- 冗長/過剰な検証:上流で既に保証されている不変条件を再チェック。
- 投機的一般性/過剰抽象化:単一の呼び出し箇所しかないトレイト、ジェネリック、間接層、設定用つまみ、ヘルパー。何も動作を追加しないラッパーメソッド。
- 装飾的なエラーハンドリング:発生し得ない条件に対するエラー/診断バリアント、または1つで十分なのに多数のバリアントがある場合。
- 死んでいるが装飾された足場:意図的な前方シームではないもの。
保持すべきコード 装飾と誤って削除しないために、以下は意図的に保持します:
- 真のアーキテクチャシーム:将来の実装者向けの文書化された拡張ポイントであるトレイト(現在実装が1つでも)。
- 唯一の強制ポイント:例えばツール呼び出し引数のバリデーションがその境界でしか強制されない場合。
- 実際の所有権と一致する並行プリミティブ(&self経由のAtomicBoolは値によるOptionで置き換えられない)。
- テストシーム:テストに実際の2番目の呼び出しがある汎化。
- 仕様で必須の安全レール。
- 過剰に構築されているが近い将来に2番目の消費者が確認されているDI/コンテキスト構造。
不明な場合は、荷重支持とみなして保持します。
プロセス
- 差分のスコープ設定:マージベースからの累積ブランチ差分を計算し、変更されたソースファイルをリストアップ。
- クラスタごとのレビュー:変更ファイルを論理クラスタ(例:構文解析/型、レジストリ/ストレージ、設定/状態モデリング、配線/転送)に分割し、クラスタごとに定義されたレンズ(5つの装飾カテゴリ+保持リスト)を適用。発見は1行タイトル、信頼度、ファイル:位置、具体的な飾り、修正案を含む。この段階では編集せず、報告のみ。
- 統合とトリアージ:発見を統合し、動作変更や低価値のものを削除。型システムの改善と真のノーオペレーション削除を保持。
- 1つずつ実行:1つの発見(または密接に関連するペア)を一度に処理。編集前に正確な契約を固定し、ターゲット型設計と不変条件の真理値表を記述。テスト移行マップを作成し、アサーションを弱めずに移行。侵襲性の低いものから順に実行。各変更後にcargoとレビューを実行。
- 疑わしい飾りが実際に削除可能か確認:削除前にコンパイラやclippyの警告が発生しないことを確認。もし警告が出たら元に戻し、報告する。
- 最終検証:フォーマット、clippy、テストなど完全なチェックスイートを実行。アサーションが弱められたり削除されていないことを確認。
具体例
- 三状態Optionの折りたたみ:enabled: Option<...>をNone→Some(true)と組み立て、unwrap_or(false)で読み取る代わりに、パース用DTOと解決済み型を分割し、コンシューマーフィールドをOptionにすることで「無効」をNoneで表現可能に。
- センチネル→Option:空文字列で「不在」を意味する戻り値をOptionに変更。
- 名前空間構造体→自由関数:ゼロフィールドで単一の関連関数を持つ構造体をモジュールレベルの自由関数に変更。
- ノーオペレーションラッパー:デフォルト実装が単にself.list()を返すだけのトレイトメソッドを削除。
アンチパターン 警告が出るコードを削除すること、仕様で必須の安全境界を削除すること、テストアサーションを弱めること、大きな構造的リモデルを最初に行うこと、バグハンティングと混同することなどが挙げられます。
Deburrは品質向上のためのパスであり、バグ修正ではありません。バグを見つけた場合は別途報告します。