0
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でシステムを作り直すとき、品質はどう守るのか

0
Posted at

1人・4か月で商用Webサービスを全面刷新した事例から学ぶ、検証可能なAI駆動開発

生成AIやコーディングエージェントによって、既存システムの読み取り、移行案の作成、実装、テストコードの下書きは大幅に速くなった。以前なら複数人で数か月を要した作業を、少人数で進める事例も出ている。

しかし、商用システムの刷新で問われるのは、コードを早く書けたかではない。本番で利用者が使い続けられるか。既存の機能やデータを失わないか。障害時に切り戻せるか。移行後も運用・保守できるか。これらを示せて初めて、刷新は成功といえる。

ある商用Webサービスの刷新では、1人・4か月で本番移行まで完了し、コード量を約4割削減したという成果が紹介された。これらの数値は講演紹介値であり、規模や技術構成の異なる案件へそのまま当てはめることはできない。注目すべきなのは工期ではなく、確率的なAI実装と、決定論的で説明可能な品質保証を分離した設計にある。

AI時代のシステム刷新で作るべきものは、新しいコードだけではない。そのコードが正しいと継続的に示せる、検証可能性である。

商用リプレイスが難しい三つの理由

本番移行までが成果になる

PoCなら「技術的に可能だ」と確認できれば終えられる。商用サービスでは、そこからが本番だ。

  • データを正しく引き継げるか
  • 既存ユーザーの操作を再現できるか
  • 外部サービスとの連携を維持できるか
  • 本番相当の負荷と障害に耐えられるか
  • 失敗時に安全に切り戻せるか

AIがコードを生成できたことは、移行の入口に過ぎない。

破壊的変更では、変換ではなく再設計が必要になる

大きなフレームワーク更新やアーキテクチャ変更では、構文の置換だけでは済まない。旧システムの振る舞いを理解し、新しい構成の中で同じ契約を満たすように設計し直す必要がある。

旧コードの構造をそのまま移せば、重複、密結合、過去の互換処理、責務の混在まで引き継ぐ。外部から見える契約を守りつつ、内部を変えられることが、全面刷新の価値になる。

信頼できる仕様書がない

最も難しいのは、何を正解として移せばよいかが文書化されていない状態だ。残っているのは既存コードと、いま動いている本番システムだけかもしれない。

このとき、動いているシステムの観測可能な振る舞いを、暫定的な実行可能仕様として扱う。レガシーコードを安全に変更するために、既存の振る舞いをテストで捕捉する考え方は、characterization testing として知られている。Martin FowlerのLegacy Seamでも、既存コードを直接変えずに依存関係を扱い、観測・テスト可能にするための「継ぎ目」の重要性が説明されている。

ゴールデンマスターで、「同じ振る舞い」を比較する

ゴールデンマスター方式では、旧システムと新システムへ同じ入力を与え、外部から観測できる結果を比較する。

同じリクエスト
  ├─ 旧システム → 基準となる結果
  └─ 新システム → 移行後の結果
                    ↓
                  差分を判定

比較対象はHTTPステータスや本文だけではない。

  • レスポンスヘッダーと画面表示
  • データベースの更新結果
  • 外部API呼び出しとイベント
  • ファイル出力、メール送信、キューへの投入
  • 例外時の応答、エラーコード、監査ログ
  • 性能・タイムアウトなどの非機能要件

旧新の結果が一致すれば、その入力シナリオについて、外部契約が保たれたと判断できる。内部設計は同じである必要がない。新システムで責務を分け、依存を整理し、コード量を減らしてもよい。

ただし、ゴールデンマスターは「旧システムと同じ」ことを示す仕組みであって、「正しい」ことを証明する仕組みではない。旧システムのバグも、意図しなければ保存される。この性質を理解して、移行と仕様改善を混ぜないことが重要になる。

正規化と副作用の隔離が、比較テストを成立させる

商用システムの出力には、毎回変わる値が含まれる。

  • 時刻、UUID、セッションID、乱数
  • 並び順、環境固有のURLやファイルパス
  • トレースID、署名、有効期限
  • 在庫や外部APIの応答など、実行時に変化する状態

これらをそのまま比較すると、正しい移行でも常に失敗する。比較の前に、差し替え、固定、並び替え、マスキングなどの正規化ルールを設ける必要がある。

一方で、正規化しすぎると、本来検出すべき差分まで隠してしまう。たとえば金額、権限、業務日付、通知先は「変動値だから」と安易に除外してはいけない。正規化の対象は、理由と所有者を持つルールとして管理する。

もう一つの落とし穴は副作用だ。同じリクエストを旧新の両方へ送れば、二重決済、二重メール、重複更新が起こり得る。比較環境では、複製データベース、スタブ、テスト用の外部アカウント、書き込みを記録だけにするプロキシを用意し、現実の利用者へ影響させない。

ASTは「完全なテスト生成器」ではなく、見落としを減らす地図

AIに既存コードを渡して「テストケースを全て書いて」と頼むことはできる。しかし、AIの出力は確率的であり、同じ入力でも同じ網羅性を保証しない。ありそうなケースへ偏り、暗黙の仕様を補完し、例外経路を落とすこともある。

そこで、検証対象の発見には、できるだけ決定論的な方法を使う。代表的なのがAST(抽象構文木)の解析だ。

ASTを調べると、少なくとも次の構造を機械的に拾える。

  • ルート、入力パラメーター、関数呼び出し
  • 条件分岐、例外処理、戻り値
  • 外部API、データベース、ファイルへのアクセス
  • 状態遷移、権限判定、機能フラグ

たとえば、管理者と一般ユーザーで分岐するコードがあれば、二つの経路の存在を検出できる。ASTの役割は、仕様を完全に理解することではない。「コード上にこの分岐・外部副作用・入力経路が存在する」という、再現可能な証拠を集めることだ。

ASTだけでは、動的ディスパッチ、設定、データ内容、外部サービスの挙動、利用者の業務手順までは分からない。複数条件の組み合わせも爆発する。そのため、AST解析は次のものと組み合わせる。

  • 実トラフィックやアクセスログからの代表シナリオ
  • 業務担当者が知る例外ケース
  • 障害履歴と問い合わせ履歴
  • API仕様、データ制約、権限モデル
  • 探索的テストで見つかった未知の経路

AIは、抽出された構造を人が読めるシナリオへ整えたり、テストコードの雛形を作ったり、失敗原因を分析したりする場所で活用できる。テスト対象の根拠と、テストコードの生成を分けることが要点だ。

確率的な実装と、決定論的な合否判定を分ける

AI駆動開発で品質を守る基本は、AIに任せる領域と、AIの外側で強制する領域を分けることにある。

AIを活用しやすい領域 決定論的に管理する領域
新システムの実装案・コード生成 検証対象の抽出ルール
エラー修正、リファクタリング 旧新システムの出力比較
テスト失敗の原因仮説 合否判定と差分の分類
説明文、移行メモ、レビュー補助 カバレッジ、回帰テスト、リリース基準

AIがどのようなコードを書いても、比較テストとポリシー上のゲートを通るまで本番へ進めない。この構造なら、AIの速度を取り込みながら、品質の判定根拠を再現可能なものにできる。

AIへ「この実装は正しいですか」と自己評価させるだけでは足りない。実装と評価が同じ誤解を共有すれば、もっともらしい誤りを見逃す。必要なのは説明の説得力ではなく、同じ入力に対する観測結果である。

テストが通るまで直す内側のループ

定義済みの比較テストを基準に、新システムを修正するループをつくる。

AIまたは人間が実装
  ↓
旧新システムを実行し、結果を比較
  ↓
差分を分類
  ├─ 新システムの不具合 → 修正
  ├─ 旧システムの既知バグ → 意図的な差分として承認
  ├─ 仕様変更 → 契約・テストを更新
  └─ 比較環境・正規化の問題 → 比較ルールを修正
  ↓
再テスト

差分を「一致しないから直す」と一律に扱わないことが重要だ。旧システム側のバグを再現すべきか、移行時に直すべきかは、プロダクトと業務の判断になる。意図的な差分には、承認者、理由、関連チケット、テスト変更を残す。

テストの不完全性を改善する外側のループ

全テストが通過しても、「定義したテストの範囲で一致した」ことしか分からない。テストに存在しない経路は、比較できない。

そこで、内側のループの外に、人間による探索的・受け入れ検証を置く。

  • 本番相当環境での業務シナリオ確認
  • 業務担当者・サポート担当者による受け入れテスト
  • 例外データ、権限差、時間帯、障害時の操作
  • 実データに近い条件での負荷・性能確認
  • カナリアリリース後のメトリクス、エラー、問い合わせ監視

ここで「テストは通ったのにおかしい」が見つかったら、個別修正だけで終わらせない。なぜ既存テストで検出できなかったのかを調べる。

  1. 見落とした経路、データ条件、外部依存を特定する。
  2. ASTの抽出、シナリオ化、正規化、テストデータのどこに穴があったかを調べる。
  3. テスト生成・選定ロジックを修正する。
  4. シナリオを再生成し、全体を再テストする。

これは、バグだけでなく、品質保証プロセスそのものを改善するループである。高レベルのテストで失敗が見つかったとき、より下位のテストや検証方法の不足を補うという考え方は、Martin FowlerのTest Pyramidにも通じる。

テスト基盤は、次の移行を速くする資産になる

この方式は、単発のリプレイスだけを目的にすると費用が重く見える。だが、次の資産として残せば、投資の意味が変わる。

  • AST解析と検証対象の抽出ルール
  • 入力データの作成・匿名化・再生基盤
  • 旧新比較と正規化のルール
  • 外部依存を安全に扱うスタブ・プロキシ
  • 差分を分類し、承認するワークフロー
  • 探索的テストで見つけたシナリオの回帰テスト化

同じ技術スタックや類似の業務システムへ横展開できれば、次の刷新は「最初からテストを設計する」仕事ではなく、「既存の検証基盤を対象システムへ適用し、差分を学習する」仕事になる。

本番移行まで含めた実務チェックリスト

AI駆動のシステム刷新を始める前に、少なくとも次を確認したい。

  1. 比較境界を決める:API、画面、DB、副作用、非機能要件のどこを比較対象にするか。
  2. 仕様の出所を分ける:旧システムの現行挙動、正規の業務ルール、意図的な仕様変更を混同しない。
  3. 動的値を正規化する:対象外にする値と、その理由をコード・レビュー・監査で追えるようにする。
  4. 副作用を隔離する:決済、メール、外部更新を二重実行しない比較環境をつくる。
  5. テストの根拠を残す:AST、ログ、障害履歴、業務シナリオのどれから対象を導いたかを記録する。
  6. 差分を分類する:新側のバグ、旧側のバグ、仕様変更、比較の問題を区別して扱う。
  7. リリースを段階化する:切り戻し、カナリア、監視、データ整合性確認を移行計画へ含める。
  8. 生成ロジックを改善する:未検出の問題を、個別テストではなく抽出・選定ロジックへ還元する。

結論:AI時代の刷新で作るべきものは、コードではなく検証可能性である

AIは実装を速くする。しかし、商用システムの品質を保証するのは、AIの自信や人間の目視だけではない。

  • 何を外部契約として守るのかを定義する
  • 同じ入力で旧新システムを比較する
  • 検証対象を再現可能な根拠から集める
  • 動的値と副作用を制御する
  • 差分を説明可能な形で分類する
  • テスト漏れを、品質保証プロセスの改善へ返す

この構造があれば、確率的なAIによる実装と、商用サービスに求められる決定論的な品質保証を両立させられる。

これからの開発競争力は、「誰がコードを書いたか」では決まらない。そのコードが正しいと、どのように説明し、どのように繰り返し検証できるかで決まる。AIでシステムを作り直すなら、最初に設計すべきなのは実装プロンプトではない。検証可能性そのものである。


作成日:2026年7月25日

0
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
0
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?