第 06 章「業務システムと付き合う ── 並行稼働で書き換える」の主張を裏付ける。
章のどの主張に対応するか
PL/SQL 5,000 行の業務ロジックを Python に翻訳、SI ベンダーの外注見積もり: 約 3,000 万円。現場担当者が Claude で書き換え、開発期間 1 ヶ月、 人件費約 100 万円。30 分の 1。
業務知識を Markdown 化する作業: 担当者の空き時間でやると 6 ヶ月〜1 年。 Claude に全コードベースを渡して一気にやれば、1 週間で 80%。
(章本文「実例: 数字で見る」より)
これは 並行稼働パターン そのものを最小サイズで実演する。
SQL 側と Python 側で同じ入力に対して 完全一致 の出力を返すことを
diff で確認する。違いが出れば、それは「現場の頭の中にあったが
ドキュメントに書かれていなかった業務ルール」だ。
やること
- 既存システム:
legacy.sql── 注文に対する請求計算(送料・会員割引・ 大口割引・税)を SQL の VIEW として実装。SQLite で実行してlegacy_output.csvを出す。 - 新エンジン:
new_engine.py── 同じロジックを Python 100 行で書き直す。 ルール定数を 章ごとにコメント付きで定義する(後で Markdown 化しやすい)。 - 並行稼働:
make diffで 2 つの CSV をdiff -uで突き合わせ、 完全一致を確認。違いがあれば差分が表示される。 - 業務ルールの 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、新エンジンに切り替え可能 と
出れば成功。
なぜこれが「実例」になるのか
業務システムの書き換えは、本来こうやる:
- 既存を止めない。SQL はそのまま動かし続ける
- 新エンジンを Python で書く。Claude に PL/SQL を読ませて翻訳
- 同じ入力で並行稼働。出力が完全一致するまで Python を直す
- 食い違いはルールの炙り出し。現場の暗黙知を Markdown に書く
- 完全一致したら切り替える。SQL を停止、Python だけにする
このフォルダはそれを 50 行のサイズで実演する。
実プロジェクトでは legacy.sql が 5,000 行、new_engine.py が
1,000 行、RULES.md が 3,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.csv で 0 行の差分。
新エンジンに切り替えてよい状態。
新旧の出力(完全一致)
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 件 の差分が出る。例:
- 「会員でも初回注文は会員割引を適用しない」 ── コードには無く、 運用画面の「初回フラグ」で対応していた
- 「30,000 円ちょうどは大口割引を適用しない」 ── 担当者の言う「以上」と、 コードの「>」の食い違い
- 「沖縄離島は送料 +500 円」 ── 担当者の暗黙知、SQL には無し
- 「税抜表示画面では税は別表示、税込画面では合算」 ── 画面ごとに分岐
これらが データの差分として可視化される。机上では一つも見えなかった。
業務知識を残す(RULES.md の役割)
新エンジンへの切り替え後、legacy.sql は捨てる。new_engine.py は
コードとして残るが、業務ルールは Markdown で別出しする。
## 4. 大口割引
会員割引を **適用したあとの小計** が **30,000 円以上** のとき、
さらに **3% 引き**(円未満切り捨て)。
> 注意: 会員割引適用前の小計ではない。
> ここを間違えると 1 円ズレる(実際にあった事故)。
これが、新メンバーが読む「仕様書」になる。SQL や Python のコードを 追わなくても業務が分かる。コードはルールを動かすが、ルールを残すのは Markdown。
再現手順
sudo apt install sqlite3
make clean && make all