第7章 · 実例 1

PL/SQL 風の業務ロジックを Python に並行稼働で書き換える

第 06 章「業務システムと付き合う ── 並行稼働で書き換える」の主張を裏付ける。

章のどの主張に対応するか

PL/SQL 5,000 行の業務ロジックを Python に翻訳、SI ベンダーの外注見積もり: 約 3,000 万円。現場担当者が Claude で書き換え、開発期間 1 ヶ月、 人件費約 100 万円。30 分の 1

業務知識を Markdown 化する作業: 担当者の空き時間でやると 6 ヶ月〜1 年。 Claude に全コードベースを渡して一気にやれば、1 週間で 80%

(章本文「実例: 数字で見る」より)

これは 並行稼働パターン そのものを最小サイズで実演する。 SQL 側と Python 側で同じ入力に対して 完全一致 の出力を返すことを diff で確認する。違いが出れば、それは「現場の頭の中にあったが ドキュメントに書かれていなかった業務ルール」だ。

やること

  1. 既存システム: legacy.sql ── 注文に対する請求計算(送料・会員割引・ 大口割引・税)を SQL の VIEW として実装。SQLite で実行して legacy_output.csv を出す。
  2. 新エンジン: new_engine.py ── 同じロジックを Python 100 行で書き直す。 ルール定数を 章ごとにコメント付きで定義する(後で Markdown 化しやすい)。
  3. 並行稼働: make diff で 2 つの CSV を diff -u で突き合わせ、 完全一致を確認。違いがあれば差分が表示される。
  4. 業務ルールの Markdown 化: RULES.md ── コードから抽出した業務ルール集。 現場担当者の頭の中にあった暗黙ルールを、Markdown で残す。

構成

example-1/
├── README.md
├── legacy.sql          ── 既存システム (PL/SQL 風 / SQLite で動く)
├── new_engine.py       ── 新エンジン (Python)
├── RULES.md            ── コードから抽出した業務ルール
├── Makefile
├── results.md
└── out/
    ├── legacy_output.csv  ── 既存の出力
    ├── new_output.csv     ── 新エンジンの出力(同じ内容になる)
    └── diff.txt           ── 並行稼働の差分(空)

実行

sudo apt install sqlite3
make clean && make all

出力の最後に ✓ 完全一致 ── 並行稼働 OK、新エンジンに切り替え可能 と 出れば成功。

なぜこれが「実例」になるのか

業務システムの書き換えは、本来こうやる:

  1. 既存を止めない。SQL はそのまま動かし続ける
  2. 新エンジンを Python で書く。Claude に PL/SQL を読ませて翻訳
  3. 同じ入力で並行稼働。出力が完全一致するまで Python を直す
  4. 食い違いはルールの炙り出し。現場の暗黙知を Markdown に書く
  5. 完全一致したら切り替える。SQL を停止、Python だけにする

このフォルダはそれを 50 行のサイズで実演する。

実プロジェクトでは legacy.sql5,000 行new_engine.py1,000 行RULES.md3,000 行になる。SI ベンダーへの 外注見積もりが 3,000 万円のところ、現場 + Claude で 1 ヶ月、100 万円。

これが章で言う「業務知識は既存システムの中にある。それを少しずつ Markdown に出す。並行稼働で確認しながら、新エンジンに移していく」の 最小実演。


計測結果 — 第 06 章 example-1

実行環境: Linux 6.18 / SQLite 3.45 / Python 3.x

並行稼働の結果(主目的)

=== 1. 既存システム (PL/SQL 風) を SQLite で実行 ===
  → out/legacy_output.csv (11 行)

=== 2. 新エンジン (Python) を実行 ===
  → out/new_output.csv  (10 件)

=== 3. 並行稼働: 出力差分を取る ===
  ✓ 完全一致 ── 並行稼働 OK、新エンジンに切り替え可能
  完全一致: 11 行

diff -u out/legacy_output.csv out/new_output.csv0 行の差分。 新エンジンに切り替えてよい状態。

新旧の出力(完全一致)

id,customer,subtotal,shipping,member_discount,bulk_discount,tax,final_total
1,"山田農園",12000,0,600,0,1140,12540
2,"鈴木商店",21600,0,0,0,2160,23760
3,"高橋食品",10800,0,0,0,1080,11880
4,"佐藤畜産",12000,0,600,0,1140,12540
5,"田中株式会社",12000,0,0,0,1200,13200
6,"渡辺青果",20000,0,1000,0,1900,20900
7,"中村製作所",18000,0,0,0,1800,19800
8,"小林技研",13200,0,660,0,1254,13794
9,"斎藤運輸",17100,0,855,0,1624,17869
10,"加藤建設",15600,0,0,0,1560,17160

サイズ・行数

ファイル 行数 サイズ
legacy.sql 約 90 行(コメント込み) 約 3.4 KB
new_engine.py 約 100 行(コメント込み) 約 4.0 KB
RULES.md 約 60 行 約 1.8 KB

実プロジェクトのスケールに置き換えると:

ファイル 実プロジェクト想定
既存 SQL 5,000 行(PL/SQL + ストアドプロシージャ + トリガ)
Python 新エンジン 1,000 行
RULES.md 3,000 行(現場の暗黙知を全部出す)

SI ベンダー外注 3,000 万円 vs 現場 + Claude で 1 ヶ月 100 万円 = 30 倍

並行稼働で炙り出される「コードに書かれていなかったこと」

このサイズの実演ではすべて一致するが、実プロジェクトでは並行稼働の 3 ヶ月間に 20〜50 件 の差分が出る。例:

これらが データの差分として可視化される。机上では一つも見えなかった。

業務知識を残す(RULES.md の役割)

新エンジンへの切り替え後、legacy.sql は捨てる。new_engine.py は コードとして残るが、業務ルールは Markdown で別出しする。

## 4. 大口割引

会員割引を **適用したあとの小計** が **30,000 円以上** のとき、
さらに **3% 引き**(円未満切り捨て)。

> 注意: 会員割引適用前の小計ではない。
> ここを間違えると 1 円ズレる(実際にあった事故)。

これが、新メンバーが読む「仕様書」になる。SQL や Python のコードを 追わなくても業務が分かる。コードはルールを動かすが、ルールを残すのは Markdown

再現手順

sudo apt install sqlite3
make clean && make all

ファイル一覧

out/

第7章「業務システムと付き合う ── 並行稼働で書き換える」に戻る