2台のモニターに古いコードと新しいコードを並べて表示し、少し不安そうな表情で見比べている開発者

AIにコードを別言語へ移植させる|挙動の差を見抜く確認手順

「サポートが切れる前に、この古いPythonのバッチをTypeScriptに書き直しておいて。AIを使えばすぐでしょ?」 実際、AIに渡すと数分でそれらしいコードが出てきます。ビルドも通る。ざっと動かしても、エラーは出ない。 なのに本番の数字と照らし合わせたら、合計が1円だけ合わない。原因を追うと、四捨五入の仕方が言語によって違っていた——。

こういうとき、「AIの移植は信用できない」と全部を手で書き直したくなりますよね。 でも、少し安心してください。移植でずれる場所には、ある程度決まったパターンがあります。 そして、それを見つける方法も、手順にしてしまえば難しくありません。

この記事では、AIにコードを別の言語へ移植させるときに、挙動の差を見抜くための確認手順を整理します。一度に全部やらなくて大丈夫です。今日は、移植したい関数をひとつ選ぶところから、一緒に進めていきましょう。

結論:AIによる移植で見るべきは「文法が正しいか」より「同じ入力に同じ出力を返すか」です。手順は4つ。①移植前に、今のコードの入出力を記録して固定する/②AIには小さな単位で移植させ、言語差で挙動が変わりうる箇所を書き出させる/③同じ入力を新旧両方に流して、出力を突き合わせる/④ずれが見つかったら、どちらを正とするかは人が決める。最初の一歩は①。比べる相手がいないと、ずれに気づけません。

何が起きているのか——文法は合っていても、言語の「当たり前」が違う

AIは、ある言語のコードを別の言語の文法に置き換えるのが得意です。ループはループに、関数は関数に、きれいに対応させてくれます。

ただ、言語には文法とは別に、それぞれの「当たり前」があります。

見た目がそっくりな書き方でも、この「当たり前」が違うと結果が変わります。そしてAIは、見た目を似せることには強い一方で、元のコードが暗黙に頼っていた挙動まで、毎回引き継いでくれるとは限りません。

これはAIの手抜きというより、移植という作業そのものの難しさです。人が手で移植しても、同じところでつまずきます。だから「AIだから危ない」ではなく、移植には確認の型が要る、と考えるのが現実的です。

具体例:移植で結果が変わりやすい定番の差

よく出会うものを挙げます。どれも、エラーにはならずに静かに結果だけ変わるのが厄介なところです。

差が出る所例何が起きるか
負の数の割り算・余りPythonの -7 // 2 は -4、Javaの -7 / 2 は -3。余りもPythonの -7 % 2 は 1、Javaは -1マイナスを含む計算(返品・調整額など)だけずれる
四捨五入Python 3の round(2.5) は 2(偶数への丸め)、JavaScriptの Math.round(2.5) は 3金額・ポイント計算で1ずれる
真偽の判定PHPでは文字列 "0" が偽、Pythonでは "0" は真条件分岐の向きが変わる
並べ替えJavaScriptの [10, 9, 1].sort() は、比較関数がないと文字列として並べて [1, 10, 9]数値の並び順が崩れる
文字列の長さ絵文字1文字が、Pythonの len では1、JavaScriptの length では2文字数チェックや切り詰めがずれる
文字列の分割"a,b,,".split(",") が、Pythonでは空文字を残して4要素、Javaでは末尾の空文字を捨てて2要素CSVの列数がずれる
整数の大きさPythonの整数は桁あふれしないが、Javaの int は約21億を超えるとあふれる大きな件数・金額だけおかしくなる
日付JavaScriptの Date は月を0から数える1か月ずれる(詳しくは日付・タイムゾーン処理の確認手順)
並び順の保証Goの map は、くり返すたびに順番が変わりうる出力の順番が実行ごとに変わる

全部を覚えておく必要はありません。「こういう種類の差がある」と知っておくだけで、確認するときの目の付け所が変わります。

放っておくと、何が起きるか

移植のずれは、テストデータがきれいなうちは表に出てきません。

逆に、移植前に「今の挙動」を記録しておけば、ずれは移植した直後、手元で見つけられます。ここが、この記事でいちばん伝えたいところです。

移植の確認手順4ステップ

左に同じ入力データの箱があり、そこから上下2本の矢印が古いコードの箱と新しいコードの箱へ分かれ、それぞれの出力が右側の天秤で比べられている流れの図
同じ入力を新旧の両方に流し、出力を並べて比べる。ずれた所が確認ポイント

ステップ1:移植する前に、今の入出力を記録して固定する

まず、移植する前のコードに、いくつもの入力を流して、出てきた出力をそのまま記録します。仕様書が正しいかどうかではなく、「今のコードが実際にこう動いている」という事実を残すのが目的です。

入力の候補出しはAIに手伝ってもらえます(境界値・異常系をAIに考えさせる手順も参考にどうぞ)。ただし、期待する出力はAIに書かせず、旧コードを実際に動かして取るのがポイントです。AIが想像した答えでは、比べる意味がなくなってしまいます。

元のコードの仕様がそもそもはっきりしないときは、先にレガシーコードの仕様をAIに読み解かせる流れで、ざっくり把握しておくと進めやすくなります。

ステップ2:小さな単位で移植させ、「差が出そうな所」を書き出させる

ファイルを丸ごと渡すより、関数ひとつ、処理ひとつの単位で移植させるほうが、ずれを見つけやすくなります。

そして、コードと一緒に「言語差で挙動が変わりうる箇所」を書き出してもらいます。たとえばこんな頼み方です。

次の Python の関数を TypeScript に移植してください。

## 守ってほしいこと
- 元のコードと「同じ入力に同じ出力を返す」ことを最優先にしてください
- 読みやすさのための書き換えや、ついでの改善はしないでください

## 移植のあとに出してほしいもの
- 言語の違いで挙動が変わりうる箇所の一覧
  (割り算・余り、四捨五入、真偽判定、文字列の長さや分割、
    数値の大きさ、日付、並び順、例外の扱い など)
- それぞれについて、元の挙動に合わせるために何をしたか
- 自信がない箇所は「自信がない」と書いてください

(ここに元のコード)

この一覧は、AIが「ここは気をつけました」と自己申告しているだけなので、正しいとは限りません。それでも、人が確認する場所の地図として役に立ちます。

ステップ3:同じ入力を新旧に流して、出力を突き合わせる

ステップ1で記録した入力を新しいコードにも流し、出力を機械的に比べます。目で見比べるより、差分を出すほうが確実です(比べ方の考え方は差分(diff)の用語解説も参考になります)。

比べるための入出力の記録は、そのまま新しいコードのテストとして残せます。AIが書いたテストを確認するコツはAIが書いた単体テストの確認ポイントにまとめています。

ステップ4:ずれが見つかったら、どちらを正とするかは人が決める

ずれの中には、実は元のコードのほうがおかしかった、というものも混じります。

たとえば「旧コードの四捨五入が、実は業務ルールと違っていた」という場合。新しいコードで正しく直すと、過去の帳票と数字が合わなくなります。

これは技術の問題ではなく、業務の判断です。AIに決めさせず、関係者と相談して、決めた理由を残しておくのがおすすめです。移植と仕様の変更を同時にやると、ずれの原因が追えなくなるので、直すとしても「移植」と「修正」は別の変更に分けると、後から自分が助かります。

明日やること(小さく始める3つ)

  1. 移植したい関数をひとつ選び、入力を10個ほど流して出力を記録する:表の「ずれやすい値」を2〜3個混ぜてください。これだけで、移植の確認の土台ができます。
  2. AIへの頼み方に「差が出そうな所の一覧も出して」を一行足す:コードだけでなく、確認すべき場所の地図が手に入ります。
  3. 新旧の出力を差分で比べる小さなスクリプトを用意する:一度作れば、次の関数からも使い回せます。スクリプトの下書きもAIに頼めます。

AIによる移植 チェックリスト

【必須】の3つだけでも、静かなずれのかなりの部分を手元で拾えます。 残りは余裕があるときに。

最後に

移植で数字が1円ずれたとき、それはあなたの確認が甘かったからではありません。言語が違えば「当たり前」が違う。それだけのことです。 そして、今のコードの答えを先に記録しておく——このひと手間があれば、ずれはもう怖いものではなく、「見つけて直せるもの」になります。

明るいオフィスで、2台のモニターの結果がそろったことを確かめ、ほっとした笑顔で隣の同僚と顔を見合わせる開発者
比べる相手がいれば、移植のずれは「見つけて直せるもの」になる

AIに書き直してもらうこと自体は、とても良い使い方です。人が確かめる場所さえ決めておけば、移植はずっと速く、ずっと落ち着いて進められます。 まずは明日、移植したい関数をひとつ選んで、10個の入力を流してみてください。そこから始めましょう。

よければ、こちらも

関連用語