Upgrade to Pro — share decks privately, control downloads, hide ads and more …

レガシー刷新と現行踏襲 - 現行業務を維持しながらシステムを刷新する要望にどう向き合うか

レガシー刷新と現行踏襲 - 現行業務を維持しながらシステムを刷新する要望にどう向き合うか

Avatar for geibee

geibee

July 14, 2026

More Decks by geibee

Other Decks in Technology

Transcript

  1. 01 / WHY RECONSTRUCTION MATTERS 機械的な現行踏襲は極めて炎上を招きやすい 現行踏襲でも現行画面・機能を完全に再現する必要はない。 01 02 03

    運用コストの低減 クラウドネイティブな構成へ移行し、運用負荷を下げる。 ベンダーロックインからの脱却 特定ベンダーへの依存を減らし、構成の選択肢を取り戻す。 改修容易性の向上 変更理由と影響範囲を追える構造へ変える。 重要な前提 運用・調達・変更容易性等を改善するには、業務構造の正確な理解が必要。 P03 / 15
  2. 02 / OBSERVE THE BUSINESS 画面一覧=顧客業務ではない 画面は真の業務ルールを知るための手掛かり。整合条件と状態遷移はその背後にある。 業務上の真理 概念 +

    状態 + 守るべき条件 画面・帳票 表示条件・操作可否 API・サービス 状態判定・更新条件 共有テーブル 制約・status値・nullable列 長年の個別改修 条件分岐が増殖 具体例 業務概念:ロット・販売案件・契約 不変条件:製造完了ロットだけ出荷指示できる 必要データ:契約済みなら契約情報を必ず持つ P04 / 15
  3. PROBLEM / TRANSACTION SCRIPT 現行踏襲の課題 - トランザクションスクリプトによる業務の分散 TRANSACTION SCRIPT =

    01–05 全体 01 / INPUT 入力を検証 lotNumber・期限 02 / LOAD ロットを取得 Repository.find 03 / RULE CHECK 状態を判定 status == manufactured ルールを直接保持 04 / UPDATE 状態を更新 期限も設定 05 / SAVE リポジトリへ保存 ユースケース完了 InstructShippingService if (status != "manufactured") error status = "shipping_instructed" 出荷指示サービスが遷移条件を知る CancelShippingService if (status != "shipping_instructed") error status = "manufactured" 別サービスも同じ status を直接更新できる P05 / 15
  4. PROBLEM / DUPLICATED IMPLEMENTATION 現行踏襲の課題 – 共通機能の重複 販売形態の差分は必要でも、取得・検証・関連付け・保存は重複しやすい。 予約販売API lotRepo.findAvailable(id)

    require(status == "manufactured") lot.salesCaseId = caseId lotRepo.save(lot) 差分:予約系処理 委託販売API lotRepo.findAvailable(id) require(status == "manufactured") lot.salesCaseId = caseId lotRepo.save(lot) 差分: 委託系処理 直接販売API lotRepo.findAvailable(id) require(status == "manufactured") lot.salesCaseId = caseId lotRepo.save(lot) 差分: 契約処理 共通4行 × 3API 同じDAO呼び出し・状態検証・関連付け・保存が複製されている 差分は各1項目 予約期限・委託者・契約だけをサブタイプ固有の振る舞いとして残す 共通処理を販売案件/ロットの振る舞いへ寄せ、APIは差分だけを調整する。 P06 / 15
  5. DOMAIN MODELING / TECHNIQUE 01 ドメインモデング - ステータス別の振る舞いを型として表現 状態ごとの判断をif文で表現すると破綻しやすい。型として表現すべき。 ※関数型ドメインモデリングの考え方であるため、実装方法はこの限りではない。以降同じ。

    BEFORE ShippingService if (status == "manufactured") instruct() else throw IllegalStateException() CancelService if (status == "shipping_instructed") ... ConvertItemService if (status != "shipped") ... 遷移条件が分散 →ソースコード全体を把握する必要がある AFTER 状態ごとの型・振る舞いを定義 ※テーブルが単一でもサブタイプでも適用できる Contracted 契約済なら出荷指示が可能 ShippingInstructed 出荷指示済の完了・取消が可能 許可される操作を型と関数にまとめる →関数シグネチャで正しい振る舞いが分かる 正しい状態遷移は関数シグネチャで定義されるため、 不正な遷移はコンパイル自体が通らない。 P08 / 15
  6. DOMAIN MODELING / TECHNIQUE 02 ドメインモデリング: 型による状態遷移の制約 遷移関数は遷移元として許可された型だけを受け取る。 STATE 01

    未査定 共通情報 STATE 02 査定済 + 査定 STATE 03 契約済 + 査定 + 契約 STATE 04 出荷指示済 + 指示日 STATE 05 出荷完了 + 完了日 査定 契約 出荷指示 出荷 コンパイルできる instructShipping(contracted, date) Contracted は許可された遷移元 コンパイルできない instructShipping(appraised, date) Appraised は関数の引数型に合わない P09 / 15
  7. DOMAIN MODELING / TECHNIQUE 03 ドメインモデリング: 型で「あり得ない状態」を表現不能にする 実行時に検査する前に、型が操作とデータの組み合わせを保証する。 コンパイル時の例 val

    salesCase: Appraised instructShipping(salesCase, date) コンストラクタ改善の例 data class Contracted( val appraisal: PriceAppraisal, val contract: SalesContract ) P10 / 15 引数の型が違うためコンパイル時に拒否 instructShipping が受け取れるのは Contracted だけ =出荷指示できるのは契約済みの商品だけ 事前条件を型として定義してデータ生成時点で矛盾を回避 「契約済みなのに契約情報がない」を作れない コンストラクタでのnull検査なども不要になる
  8. DOMAIN MODELING / TECHNIQUE 04 ドメインモデリング: アプリケーションにおける位置づけ アプリケーションサービスは残る。業務判断をドメインへ委ねる。 LAYER 01

    Application Service トランザクション開始 · 読み込み · ドメイン呼び出し · 保存 ORCHESTRATES LAYER 02 Domain Model 状態遷移 · 値制約 · 不変条件 · 業務判断 DECIDES LAYER 03 Repository / Persistence 永続化と取得 STORES CALL LOAD / SAVE P11 / 15
  9. HOW TO PROCEED / DOMAIN DISCOVERY 動くものだけではなく中間成果物による設計合意 成果物を作ることが目的ではない。同じ業務ルールを別の角度から検証する。 ドメイン上の真理 概念:販売案件

    操作:契約済みだけ出荷指示 不変条件:契約情報を必ず保持 業務用語集 例:販売案件/ロット/契約 概念の意味と境界を揃える 状態遷移図 Contracted → ShippingInstructed 許可される操作を図で確かめる 受け入れ条件 Given 契約済みの販売案件 When 出荷を指示する Then 出荷指示済みになる ドメインテスト BeforeAppraisal → instructShipping は不可 不変条件を継続的に固定する 同じ真理が4つの成果物で一致すれば、 画面が少ない初期でも進捗を検証できる P13 / 15
  10. SCHEDULE DESIGN スケジュールは「画面」ではなく「成果物」で区切る 安易に画面設計書・UIモックに逃げると結合テストでの手戻りが避けられない。 動くものがない期間を許容しながら、業務上の真理を合意するスケジュールにすべき。 SCREEN-BASED PLAN 週1–2 画面1–3 週3–4

    画面4–6 週5–6 画面7–10 結果:画面ごとに似た判定・更新・DAOが完成する ARTIFACT-BASED PLAN 週1 用語集 週2 遷移図・具体例 週3–4 モデル・テスト 週5–6 画面・API 結果:共通ルールを固めてから各機能を実装する 先に合意する成果物 業務用語集 → 状態遷移図 → 受け入れ条件 → ドメインモデルとテスト 後から並行化する単位 画面・API・帳票は、共通モデルを利用する実装として分担する P14 / 15