1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AI生成コードのレビューは全行読む必要ある?契約とテストで絞る設計

1
Posted at

この記事の要点

  • AI生成コードのレビューは、全行を同じ密度で読む必要はなく、「契約」と「テスト」で機械的に守れる部分と、人が読むべき部分に分けるのが現実的です。
  • 契約(入力と出力の約束事)をテストで固定すると、人は実装の中身ではなく「契約そのものが正しいか」に集中できます。
  • 認可・金銭・データ破壊など、契約で表しにくい領域は、AI生成であっても従来どおり人が精読する必要があります。

はじめに:AI生成コードのレビューで消耗していませんか

AI生成コードのレビューを、全行同じ密度で読み続けるのはつらい作業です。生成量が増えるほど、人の読む時間が先にあふれます。

この記事では、読む範囲を契約とテストで絞る設計を扱います。狙いは「手を抜く」ことではありません。「読む場所を選ぶ」ことです。

なお、この記事は次の記事の問題意識を参考にしています。内容の写しではなく、検索されやすい疑問に沿って再構成しました。

AI生成コードを全部同じ密度で読むべきか

結論から言うと、全部を同じ密度で読む必要はないと考えます。理由は2つです。

1つ目は、人の注意力に上限があることです。重要な1行と、定型の10行を同じ熱量で読めば、重要な1行を見落としやすくなります。

2つ目は、読まなくても守れる性質があることです。型、テスト、静的解析で検証できる部分は、機械に任せたほうが確実です。

ただし「読まない」と「検証済み」は別物です。検証の手段がない部分を読まないのは、ただの放置です。

契約(Design by Contract)とは何か

契約とは、関数やモジュールが守る約束事です。Design by Contract(契約による設計)では、主に3つを定義します。

  • 事前条件(precondition): 呼び出し側が満たすべき入力の条件
  • 事後条件(postcondition): 関数が返す結果が満たすべき条件
  • 不変条件(invariant): 処理の前後で常に成り立つ条件

出典: https://en.wikipedia.org/wiki/Design_by_contract

AI に実装を任せるとき、この3つは「仕様書」として働きます。実装は毎回変わってもよく、契約だけが変わらなければ良い、という考え方です。

契約を書く側が人間である意味

契約は、人が書いて人がレビューします。実装は AI が書き、契約に照らして機械が検証します。

つまり、レビュー対象が「実装の数百行」から「契約の数行」に縮みます。これが絞り込みの核心です。

具体例:契約とテストでレビュー範囲を絞る

割引計算の関数を例にします。契約を先に人が書き、実装は AI に任せます。

from hypothesis import given, strategies as st

def apply_discount(price: int, rate_percent: int) -> int:
    """
    事前条件: price >= 0, 0 <= rate_percent <= 100
    事後条件: 0 <= 結果 <= price
    事後条件: rate_percent == 0 なら結果 == price
    """
    ...  # ここを AI に実装させる

@given(
    price=st.integers(min_value=0, max_value=10**9),
    rate=st.integers(min_value=0, max_value=100),
)
def test_contract(price, rate):
    result = apply_discount(price, rate)
    assert 0 <= result <= price

@given(price=st.integers(min_value=0, max_value=10**9))
def test_zero_rate_is_identity(price):
    assert apply_discount(price, 0) == price

ここで使っている Hypothesis は、性質ベーステスト(property-based testing)のライブラリです。入力を自動生成して、契約が破れる例を探します。

こうしておくと、人が見る場所は3か所に減ります。

  1. 契約(docstring)は業務ルールと合っているか
  2. 性質テストは契約を漏れなく表しているか
  3. 契約の外側(丸め方、端数処理)は仕様で決まっているか

実装の中身は、テストが通る限り、読む優先度を下げられます。

書いてみて感じたこと

この例は、考え方を確かめるために書き下したものです。実プロジェクトでの計測はしていません。

書いてみて気づいたのは、契約を書く作業そのものが、仕様の曖昧さを洗い出す工程になることです。「端数は切り捨てか四捨五入か」は、実装を読んでも決まりません。契約を書く段階で初めて問いになります。

どこまで絞れるか:領域別の比較表

すべての領域で同じように絞れるわけではありません。目安を表にします。

領域 契約・テストで表せるか レビューの密度
純粋関数(計算・変換) 表しやすい 契約とテストを中心に読む
データ整形・マッピング 比較的表しやすい 境界値と欠損の扱いを読む
外部 API 連携 一部のみ 失敗時の挙動とリトライを読む
認可・認証 表しにくい 全行を精読する
金銭・決済 表しにくい 全行を精読する
データ削除・マイグレーション 表しにくい 全行を精読し、実行手順も確認する

認可の不備のような問題は、OWASP Top 10 でも主要なリスクとして挙げられています。

「テストが通った」ことは「認可が正しい」ことを意味しません。そもそも、そのテストが書かれていないことが多いからです。

テストの質を担保する:ミューテーションテスト

契約で絞る設計の弱点は、テストが弱いと全体が崩れることです。AI は「テストを通す実装」を作るのが得意です。弱いテストは、簡単にすり抜けられます。

そこで有効なのがミューテーションテストです。コードをわざと少し壊し(例:< を <= に変える)、テストが失敗するかを調べます。壊してもテストが通るなら、そのテストは弱いと判断できます。

実行時間はかかります。全体に回す必要はなく、契約で守ると決めた重要モジュールに限定するのが現実的です。

運用の手順:絞り込みレビューを始める5ステップ

  1. 変更を「契約で守れる層」と「守れない層」に分類する
  2. 守れる層は、先に人が契約とテストの雛形を書く
  3. AI に実装させ、テストと静的解析を CI で通す
  4. 人は契約・テスト・境界の扱いをレビューする
  5. 守れない層は、従来どおり全行を読む

分類の基準は、PR のテンプレートに書いておくと運用が安定します。たとえば「この PR は認可・金銭・削除に触れるか」というチェック欄です。

デメリット・向いていない人・うまくいかないケース

この設計には限界があります。導入前に確認してください。

うまくいかないケース

  • 仕様が固まっていない開発: 契約が毎日変わると、書くコストが実装コストを上回ります。
  • 副作用が中心のコード: 外部状態を変える処理は、契約で表すのが難しくなります。
  • テスト基盤が未整備のチーム: CI でテストが回らないなら、絞り込みの前提が成り立ちません。

向いていない人

「レビューを楽にしたいだけ」の場合は、おすすめしません。契約を書く作業は、実装を読む作業とは別の負担です。総量は減らず、移動するだけの場合もあります。

残るリスク

契約そのものが間違っていれば、正しく間違った実装が量産されます。契約のレビューだけは、省略できません。

まとめ:次に取る行動

最初の一歩は小さくて構いません。次の PR で、純粋関数を1つ選び、契約を3行で書いてから AI に実装させてみてください。

残る問いは、「どの領域を、誰が、どの基準で『守れない層』と判定するか」です。この判定基準をチームで言語化できるかが、導入の成否を分けると考えています。

よくある質問

Q. AI生成コードは人間が書いたコードより厳しくレビューすべきですか?

一律に厳しくする必要はありません。重要なのは書き手ではなく、変更が触れる領域です。認可・金銭・削除に触れるなら、書き手に関係なく精読します。

Q. 契約とテストだけで AI生成コードのレビューは省略できますか?

省略はできません。契約とテストで機械的に検証できる範囲が広がり、人が読む対象を絞れる、というのが正確です。契約自体の妥当性は人が確認します。

Q. 性質ベーステスト(property-based testing)とは何ですか?

入力例を人が1つずつ書く代わりに、「どんな入力でも成り立つ性質」を書いて、入力を自動生成して検証する手法です。Python では Hypothesis が代表的なライブラリです。

Q. ミューテーションテストは毎回の CI で回すべきですか?

毎回全体に回す必要はありません。実行に時間がかかるため、重要モジュールに限定するか、夜間ジョブで実行する運用が現実的です。

Q. 契約はどこに書くのがよいですか?

docstring、型、テストの3か所に分けて置くのが扱いやすいです。型で表せるものは型に、表せない条件は性質テストにします。

Q. 小規模チームでも導入できますか?

導入できます。全体に適用せず、純粋関数など契約を書きやすい部分から始めるのが現実的です。CI でテストが回る状態であることが最低条件です。

Q. AI にテストも書かせてよいですか?

実装と同じ AI にテストも任せると、同じ誤解を両方に持ち込むおそれがあります。契約と性質テストの骨子は人が書き、細かいケースの補完を AI に任せる分担が安全です。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?