🎯 この記事の範囲
モダナイゼーションの失敗は、だいたい同じ形をしています。新しい画面のモックから書き始め、旧システムの「つもり」で仕様を復元し、切替の直前に現場の例外が噴き出す。
本シリーズは逆です。原典は旧実装です。PHP、2010 年前後の C# デスクトップ、iPhone / Android の MAUI。動いているコード、紙に出ている帳票、現場が毎日押しているボタンが、仕様書より先にあります。
革新は AI が読めることではありません。旧実装が今日通している入力と拒否を、先にテストへ落とすことです。この種の業務システムでは単体テストはほとんど無く、書けない開発環境が普通です。継ぎ目を切ってユニットと接続テスト(Moq / フェイク)を揃えると、実プリンタ無しで誤送を落とせます。
| 本記事 | 隣接領域 | |
|---|---|---|
| 本記事(第 1 回) | なぜ置換するか / 原典は旧実装 / 置換の鍵は TDD / 寄せる境界 / 機械で閉じる受入と人が残る切替 / 再現にハーネスが要る理由 | AS/400 を残して外側に足す 戦略、TDD 編、ハーネスの作り方 |
営業の数字・見積・請負条件は本シリーズの対象外です。数字は www の開発実績(置換ケース) に置きます。ここは なぜ着手し、どうやれば次も同じように移せるか を書きます。
端末選定は、業務要件と運用コストに関わる設計判断として扱います。関連事例「JAN出荷検品の端末選定 — BT-W85から.NET MAUIへ」では、中古iPhone・Androidと専用ハンディを比較する条件、機器接続の分離、実機での受入を整理しています。
🎯 なぜ、置換するのか
「古い実装の技術的負債を取り除く」では、焦点がぼやけます。負債返済は結果です。現場が動き出す理由は、だいたい次の 3 つです。
| 動機 | 起点 | 本シリーズが書くこと |
|---|---|---|
| 今は動かしていない過去実装を、別系統で再利用したい | ソースはある。現行業務は通っていない | 休眠と死んでいるを分ける。欲しい機能だけをテストに落として移す |
| 他人が作ったシステムを、自分のプロジェクトへ入れたい | リポジトリ(SVN / Git)は分かる。パスが分からない。作者はいない | ステアリングを組む前の調査。地図を先に出す |
| 他社が作ったシステムに手が出せない | 手直しのたびに高額見積でも、代替が無い | 旧実装を原典に、自社側で直せる形へ移す(内製化) |
3 が発注理由です。1 と 2 は、3 を安全にやるための起点です。
AS/400 モダナイゼーション が「基幹を残して外側に足す」なら、本シリーズは 手が出せない実装を、読める原典にして自社側へ移す 話です。新規の SaaS を頭の中の仕様から書く話でもありません。
どうやるかの革新は、次節からの TDD です。動機を手法に置き換えません。
🚫 新規のつもりで書くと、置換は壊れる
レガシー置換で最初に捨てるべき幻想は、「今の頭で正しい業務を再設計すれば、旧システムは消せる」です。
現場が 15 年動かしてきた例外は、仕様書にありません。納品書の見出し幅が 13mm では Windows の太字で折り返す、バーコード下の数字は均等配置、ラベルは PDF にしない、取得した印刷ジョブを排出完了としない。これらは 動いているコードと紙 にしか残っていません。
AI に「新しい出荷 SaaS を作って」と頼むと、きれいな CRUD が出ます。AI に旧 WPF と旧 RDLX を読ませ、「この紙面とこの状態機械を壊さず移せ」と頼むと、別の仕事になります。後者が本シリーズの対象です。
💡 置換の TDD とは、新しい仕様からテストを書くことではありません。 旧実装が今日通している入力と拒否を、先にテストにすることです。原典だけだと AI は欠陥まで移植します。テストだけだと、きれいな CRUD のテストに逃げます。二つ揃って、死んでいるコードを捨て、休眠は欲しい機能だけ移し、欠陥を再現せず、堅牢に置換できます。
実践編で書いた「AI は放置すると負債を増やす」は、ここでも成り立ちます。原典もテストも無い新規は増幅です。原典をテストに落とした置換は返済です。
旧実装(原典)→ テストに落とす(TDD)→ 新実装 → 実機・実紙(人)
📖 原典は仕様書ではなく、動いている実装
CTS がいま置換している対象は、だいたい次の層です。
| 層 | 旧側の実体 | 新側でやっていること |
|---|---|---|
| 業務端末 | 古い C# デスクトップ、MAUI(iPhone / Android) | 共通 MAUI。ログイン後の権限で利用可能な業務を出し分ける |
| Windows の無人印刷 | ActiveReports 依存の WPF | 同じ役割の WPF。PDF をスプーラーへ渡す。ActiveReports は使わない |
| A4 帳票 | RDLX + VB 式 | Scriban の HTML/CSS + Playwright Chromium |
| 感熱ラベル | 機種の印字コマンド | SBPL を .NET で組み立てる。PDF に寄せない |
| サーバー | 旧 API・採番・印刷ジョブ | テナント付きの契約へ移す。接続と切替は後段 |
PHP や 2009〜2012 年の C# は、消す対象ではなく 読み解く対象 です。先にやるのは書き直しではなく、台帳です。
台帳で分けるのは、機能名ではありません。
- 動いている — 現場が今日も使っている。紙が出る、スキャンが通る、例外処理が残っている
- 死んでいる — ソースにはあるが、現行業務が通らない。互換のための移植はしない
- 休眠 — 今のラインでは止まっているが、別のフロント/バックで同じ機能が欲しい。死んだ原紙の復活ではなく、後期仕様を正として載せ替える
- 欠陥として残っている — 動いているが、バグである。共有の可変値で帳票種別が食い違う、印刷日欄が 2mm、未対応文字の黙った
?置換
死んでいるコードを「互換のため」に移植すると、新システムが旧システムの墓地になります。休眠は墓地ではありません。今は通っていないことと、捨てることとは別軸です。欠陥は再現しません。移植時に直し、直したことを台帳に残します。
旧コードの読み方そのものは第 2 回で掘ります。総論で固定するのは原則だけです。AI に読ませるのは「全部移植しろ」ではなく、この四分類です。地図が無い状態からの調査も、第 2 回の起点です。
🧱 全部を 1 つのエンジンに寄せない
置換で二番目に捨てる幻想は、「新しい描画エンジンに全部載せれば単純になる」です。
A4 納品書は HTML/CSS の mm 指定とヘッドレス Chromium で出せます。203 dpi の感熱ラベルは出せません。既存資産は SBPL です。PDF をラベル機へ送る「統一」は、単純化ではなく誤送です。
実例は ActiveReports → Playwright + Scriban 移行 に書きました。本シリーズから見ると、あれは帳票という 一つの境界の引き方 です。
| 寄せる | 寄せない |
|---|---|
| 帳票データはテナント・拠点付きの DTO | テンプレートが店名から拠点を推測する |
| 同じ MAUI で複数業務を出す | ログイン前から全業務メニューを出す |
| 印刷ジョブ ID で追跡する | スプーラー受理を紙の排出にする |
| レビュー済みテンプレートだけ実行する | 利用者が任意のテンプレートを投稿する |
| A4 は Chromium PDF | ラベルも PDF にする |
AS/400 モダナイゼーション が「基幹を残して外側に足す」なら、本シリーズは 端末と帳票と印刷を、旧コードを原典に載せ替える 話です。Rehost / Replatform / Refactor の分類より先に、「何を一つの契約にし、何を機種の言語のままにするか」が決まります。
境界の引き方は第 3 回です。総論の結論は、統一は目的ではない。誤配線を禁止できる境界が目的です。
✅ 受入は文章ではなく、落ちるテストにする
「現行と同じに動く」は受入条件になりません。同じ、の単位が無いからです。この種の出荷・帳票などの業務システムでは、旧環境に単体テストがほぼありません。設計器と実プリンタが正本で、Moq で切る継ぎ目が無かったためです。書けなかったテストを、置換の受入そのものにします。詳細は 第 4 回 です。
機械で閉じられるものから先に閉じます。
| 機械で閉じる | 人に残す |
|---|---|
| テナント/拠点が一致しない文書は描画しない | 実紙のミシン目・プリンター倍率 |
| HTML 混入はエンコードする | 実機スキャナでの読取 |
| 12 明細 / 7 商品で改ページする | 運送会社の送り状発行 |
| Code128 / QR を生成し、画像から復号して元値と一致する | ドライバーからの本番自動印刷 |
| 用紙に収まらない文字は PDF を書かずに失敗する | 複数端末をまたぐ実運用の排他 |
| 再起動後に同じジョブを二重送信しない | 税・送料・値引き・適格請求書 |
| PDF 用経路へ SBPL を流さない | 切替日と切戻し |
帳票では、Linux 上でブラウザーを含むテストが通り、Windows の Chromium / Chrome でも同じページ数の PDF が出るところまで来ています。それは エンジン置換の受入 であって、現行紙への切替条件ではありません。
Linux では閉じないテストの出先は第 5 回、人が残る切替は第 6 回です。総論で固定するのは、手元のサンプル PDF が綺麗なことを、切替としない ことです。
🧩 なぜ、途中でハーネスが要るのか
ここまでの手順は、優秀な一人と優秀なモデルがあれば、一回はできます。一回できることと、次の置換でも同じ品質でできることは違います。
CTS-EC で直した負債が CTS-POS で再発した、という記録は ハーネスのサービス化 にあります。置換でも同じ穴が開きます。
- 旧コードの四分類が会話の中だけにあると、次のセッションが死んだ分岐を復活させ、休眠を捨てる
- 「PDF に寄せない」がルールファイルに無いと、ラベルを HTML にしたくなる
- 受入テストがゲートに無いと、AI はサンプル PDF の成功を完成と宣言する
- 期限切れの印刷ジョブを再送してよい、が文書に無いと、親切な再試行が誤出荷になる
ハーネス はモデルではありません。原典の置き場、禁止事項、テスト、証跡、周回の停止条件です。置換が AI 向きなのは原典があるからで、原典を次の実行でも同じ優先度で読ませる装置がハーネスです。
本シリーズはハーネスの作り方を再解説しません。作り方は ステアリング駆動開発 と 応用編 にあります。ここでは、置換の現場で ハーネスが無いと壊れる箇所だけを示します。それが第 7 回です。
📌 簡単に移行できる、の中身は新しいモデルではなく、台帳とゲートです。 旧実装を ZIP で渡して「新しくして」では、新規のつもりで書くのと同じ失敗を高速化します。
📍 いま閉じていること、閉じていないこと
2026 年 9 月時点の到達点です。完成宣言ではありません。
閉じつつあるもの
- 旧 RDLX の受注票兼納品書を Scriban へ移植し、社内出荷番号の Code128 と日本語 QR をサーバー側 SVG で埋め込む
- A4 は Playwright、ラベルは SBPL、という出力の分離
- 印刷ジョブの claim / submitted / 要確認。スプーラー受理を排出完了にしない
- 同じ MAUI を権限で出し分ける方針
- WPF から ActiveReports を外す
まだ人の切替側にあるもの
- 現行紙との重ね合わせ、ミシン目
- 送り状 API、実機スキャナ、PW208 への実送信
- CTS-EC 本体の API / DB への接続、複数端末排他の通し
- iPhone / Android 実機での検品オペレーション
ソースの調査と移植とテストは AI に出せます。切替は出せません。この切り分けが、次の案件でも使い回せる定義です。
✅ 第 1 回まとめ
- 動機は負債返済ではない。手が出せない他社製、パスが分からないリポジトリ、今は止まった過去実装の再利用である
- レガシー置換の原典は、新しい仕様ではなく 動いている実装 である
- 革新は AI が読めることではなく、その振る舞いを先にユニットと接続テストへ落とす TDD である
- 旧環境はテストを書かないのではなく、書けない。新側で Moq / フェイクの継ぎ目を切る
- 死んでいるコードは移植しない。休眠は欲しい機能だけ移す。欠陥は再現せず、直した事実を台帳に残す
- 全部を一つのエンジンに寄せない。A4 とラベル、複数正本、送信と排出は境界にする
- サンプル PDF の成功を切替にしない
- 同じ置換を次でも再現するには、ハーネス が要る
次回「旧コードの読み方」では、リポジトリは分かるがパスが分からない状態から、何を先に台帳化し、何を読ませないかを書きます。
📚 シリーズ記事
| 回 | タイトル | 主題 |
|---|---|---|
| 1 | レガシー置換とは(本記事) | 旧実装を原典にし、先にテストへ落とす |
| 2 | 旧コードの読み方 | 地図が無い状態から四分類 |
| 3 | 寄せる境界・寄せない境界 | DTO、PDF と SBPL、店舗と別拠点 |
| 4 | 受入の機械化 | ユニットと Moq・フェイクで先に落とす |
| 5 | Linux から Mac / Windows へ出して TDD する | SSH 先で閉じる不足分、キャプチャまで AI |
| 6 | 人が残る切替 | 実機・実紙・契約・並行稼働 |
| 7 | 再現装置としてのハーネス | 台帳・禁止・ゲート・停止条件 |
🔗 関連リソース
営業側の置き場(本シリーズの外)
- www の開発実績(置換ケース) — 内製化の動機と人月目安。数字はこちら
すでに公開した置換の実例
- ActiveReports → Playwright + Scriban 移行 — A4 帳票のエンジン置換。ラベルは SBPL のまま
- 脱Microsoft・OSS移行 総論 — OS・ライセンス層の置換。本シリーズは業務アプリ層
基幹を残す話(本シリーズとは別)
- AS/400 モダナイゼーション戦略 — Rehost / Replatform / Refactor
- AS/400 を使い続けながら B2C に参入する — 基幹を捨てず外側に足す
再現装置
- ハーネスエンジニアリング — モデルではなく周囲の制御層
- 二度の「1か月」を繰り返さない — 負債の再発とハーネス
- TDD 編 — テストを先に置く理由。本シリーズはそれを旧実装のキャラクタリゼーションに使う
- ステアリング駆動開発とは — 要件と設計を先に固定する手法
- AI 駆動開発が積み上げる技術的負債 — 原典の無い増幅