第09章 既存システム改修

09_maintenance

第09章 既存システム改修演習(改訂版)

この章の読み方: 本文の基本説明、直後の発展解説、例題、演習の順に読んでください。専門用語は初めて出てきた箇所で意味を確認し、コードの予想結果を考えてから実行します。

章末の演習は、それまでの本文の内容を使って解けるように設計しています。

用語の表記: 全10章共通の用語集 と表記を揃えています。

対象はプログラミング未経験者と、他言語の開発経験者です。Java 21とEclipse、Gitを使います。この章では、完成済みのコードを読むだけでなく、原因調査から修正結果の説明までを自分で行います。

引き継いだシステムに不具合がある状況を再現し、仕様確認・再現・原因調査・影響範囲の確認・改修・回帰テスト・報告を一通り行います。

01. この章でできるようになること

  • 他の人が書いたコードの入口を探し、処理を複数のクラスにまたがって追える。
  • 実行結果と仕様書を比較し、何が不具合なのか言葉と数値で説明できる。
  • 修正前の失敗を記録し、修正後の成功を同じ条件で証明できる。
  • 共通の処理を修正する際、別の機能が壊れていないか確認できる。
  • Gitの差分とテスト結果を添えてレビュー依頼を作れる。

学習時間の目安: 初心者は8〜12時間、他言語経験者は4〜6時間です。学習速度には個人差があり、時間の経過ではなく提出物で達成を判断します。

この節の独学チェック:01. この章でできるようになること

確認問題: 改修演習で新規開発と最も異なる点は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

完成済みの処理を改修する点に注目します。

ヒント2

新機能だけ見て既存処理を壊したらどうなるでしょうか。

ヒント3

変更要求と守るべき既存動作を分けます。

模範解答と理由

既存の期待動作を守りながら、要求された変更だけを追加・修正する必要がある点です。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 既存の期待動作を守りながら、要求された変更だけを追加・修正する必要がある点です。

満点の正答例: 既存の期待動作を守りながら、要求された変更だけを追加・修正する必要がある点です。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「既存の期待動作を守りながら、要求された変更だけを追加・修正する必要がある点です」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「01. この章でできるようになること」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

02. 実務改修とは何か

新規開発では、自分で画面やクラスを設計してプログラムを書き始めることがあります。これに対して保守・改修では、すでに他の人が作ったクラスや動いている仕様を理解し、その振る舞いをできるだけ維持しながら必要な点だけ変更します。

例えば「商品検索で大文字と小文字の違いを無視してほしい」という依頼が来ても、検索処理だけを変更すれば必ず安全だとは限りません。共通メソッドが別の画面でも使われていれば、別の画面の検索結果も変わるかもしれないからです。

作業の順序は 仕様を読む → 変更前の現象を記録 → 呼び出しを追跡 → 原因を絞る → 最小限の変更 → すべて再テスト → 報告 です。修正コードを最初から見てしまうと、問題を自力で調べる能力を練習できません。

この節の独学チェック:02. 実務改修とは何か

確認問題: 改修前に仕様と既存コードのどちらを確認しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

仕様書だけ読んでも現在の不具合は特定できません。

ヒント2

実装だけ読んでも正しい動作を判断できません。

ヒント3

要求された状態と現実の振る舞いを比較する方法を考えます。

模範解答と理由

双方を照らし合わせます。仕様上の期待と現行コードの実際の挙動の差を把握します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 双方を照らし合わせます。
  2. 1点: 仕様上の期待と現行コードの実際の挙動の差を把握します。

満点の正答例: 双方を照らし合わせます。仕様上の期待と現行コードの実際の挙動の差を把握します。

部分点の判定: 部分正答例:「双方を照らし合わせます」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「双方を照らし合わせます」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「02. 実務改修とは何か」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

03. 演習用アプリの概要と制約

examples/09_maintenance/order-maintenance/starter は、引き継いだ既存システムを表す不具合入りのソースコードです。solution は指導者だけが使用する修正版です。

Java標準ライブラリだけを使用するため、MySQLやMavenがなくても実行できます。ただしこれはWebサーバーではありません。HTTPの実通信やDBのトランザクションをこの章で検証するものではありません。

演習では商品が三つ登録されています。Coffeeは400円・在庫5、Teaは250円・在庫3、COCOAは350円・在庫0です。アプリを終了すると登録情報が消えるため、毎回同じ初期条件から試験できます。

この節の独学チェック:03. 演習用アプリの概要と制約

確認問題: この課題のデータ保存はDBですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

第09章のRepositoryの実装を確認します。

ヒント2

MySQLに接続するコードがあるか見てください。

ヒント3

メモリー上の保存で検証できることとできないことを分けます。

模範解答と理由

いいえ。第09章の主課題はメモリー内のRepositoryを利用し、DBの同時更新は対象外です。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 第09章の主課題はメモリー内のRepositoryを利用し、DBの同時更新は対象外です。

満点の正答例: いいえ。第09章の主課題はメモリー内のRepositoryを利用し、DBの同時更新は対象外です。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「第09章の主課題はメモリー内のRepositoryを利用し、DBの同時更新は対象外です」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「03. 演習用アプリの概要と制約」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

04. 仕様書:改修後も守る必要がある動作の約束

ID 機能 要求仕様
S-01 商品検索 商品名の部分一致で検索し、大文字・小文字を区別しない
S-02 商品検索 キーワードがnull・空白のみなら全商品を返す
S-03 商品検索 該当なしなら空リストを返す
S-04 注文 注文金額は単価×数量、成功時に在庫を数量分減らす
S-05 注文 数量0・負数・在庫不足・商品未登録なら IllegalArgumentException
S-06 注文 同一注文IDを再登録しようとしたら拒否し、在庫を変更しない
S-07 取消 ACTIVE注文を取り消すとCANCELLEDとなり、在庫が元へ戻る
S-08 取消 二重取消は拒否し、在庫が二重に戻らない
S-09 取消 存在しない注文IDは例外

この演習では注文と在庫を同一プロセスのメモリー内で管理します。実際のDBを使う場合、複数処理をまとめるトランザクションや並行更新の制御が別途必要です。ここでは「注文が成功したときと失敗したときの状態」を確認する基礎を学びます。

この節の独学チェック:04. 仕様書:改修後も守る必要がある動作の約束

確認問題: 在庫5個の商品に数量0の注文が来たとき、仕様上どう扱いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

入力数量が0のとき業務ルールはどう定められていますか。

ヒント2

在庫数が変化してしまうと何が困るでしょうか。

ヒント3

拒否後の注文と在庫の状態を両方確かめます。

模範解答と理由

数量0は不正入力として拒否し、注文も在庫数も変更しません。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 数量0は不正入力として拒否し、注文も在庫数も変更しません。

満点の正答例: 数量0は不正入力として拒否し、注文も在庫数も変更しません。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「数量0は不正入力として拒否し、注文も在庫数も変更しません」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「04. 仕様書:改修後も守る必要がある動作の約束」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

05. ソースのどこから読めばよいか

ファイルを無作為に開かず、まず Application.java を探してください。main メソッドはアプリの開始地点です。

そこから ProductController.search()、OrderController.place()・cancel() をたどり、それぞれ呼び出すServiceを調べます。

Repositoryは保存や検索を担当します。

Application (起動)
  ├─ ProductController.search
  │    └─ ProductService.search
  │         └─ ProductRepository.findAll
  └─ OrderController.place / cancel
       └─ OrderService.place / cancel
            ├─ ProductRepository.findById / save
            └─ OrderRepository.findById / save

Controller は処理の入口をまとめるクラスです。今回のControllerはHTTPを扱わない、学習用の普通のJavaクラスです。Service は検索条件や在庫判定などの業務ルールを担当します。

Repository はデータの保存・取得を担当する窓口であり、今回の実装は Map を使用します。interface とは「この名前のメソッドを利用できる」という約束を表すJavaの仕組みです。

理解を深める:例題:送料無料判定が1円ずれている

依頼書には「合計金額が3,000円以上なら送料は0円、2,999円以下なら送料は500円」と書かれています。ところが3,000円の注文に500円の送料が付いてしまいました。

手順1:仕様を具体的なテストに置き換える。 2,999円→500円、3,000円→0円、3,001円→0円の3条件を書きます。

特に境界の直前・境界・直後を調べるのは、< と <= などの間違いを見つけやすくするためです。

手順2:現象を再現する。 以下の小さなコードを読みます。

class ShippingFee {
    static int calculate(int total) {
        if (total > 3000) { // 仕様では3000円も送料無料
            return 0;
        }
        return 500;
    }
}

calculate(3000) は条件 3000 > 3000 が偽なので、500が返ります。仕様と異なることを、値と比較演算子まで説明できます。

手順3:原因を一文にする。 「送料無料の条件が 3000円超 になっており、仕様の 3000円以上 と一致しない」と説明します。「おそらくif文に問題がある」という曖昧な報告は避けます。

手順4:最小限の修正を選ぶ。 条件を total >= 3000 に変更します。この例では負の金額に対する扱いは仕様がないため、勝手に新しい例外仕様を追加せず、確認事項にします。

手順5:回帰確認する。 2,999円、3,000円、3,001円を再実行し、どれも期待結果になることを確かめます。送料計算を使っている別の画面も同じメソッドを呼んでいないか検索して確認します。

手順6:報告する。 「原因:境界比較の誤り。修正:> を >= に変更。確認:2,999/3,000/3,001円で期待結果一致。残確認:負数入力の仕様。」のように、判断の根拠を残します。

この節の独学チェック:05. ソースのどこから読めばよいか

確認問題: 注文取消が誤動作したとき、どの処理の呼び出しを追いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

注文取消のHTTP入口から順に追います。

ヒント2

在庫更新はどの層で呼ばれるか考えます。

ヒント3

注文状態の変更とRepository操作を一続きで見ます。

模範解答と理由

OrderController→OrderService→Repositoryと、注文状態と在庫変更を追います。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: OrderControllerからOrderServiceへ追跡する。
  2. 1点: Repositoryを追跡し、在庫と注文状態の更新を調べる。

満点の正答例: OrderController→OrderService→Repositoryと、注文状態と在庫変更を追います。

部分点の判定: 部分正答例:「OrderControllerからOrderServiceへ追跡する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「OrderControllerからOrderServiceへ追跡する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「05. ソースのどこから読めばよいか」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:既存コードの調査順

既存コードの調査順

図の読み方:呼出し元から関連クラスへ処理を追うと、改修対象を特定しやすくなります。

06. 初回実行:修正前の失敗を確認する

実行手順を開いてください。WindowsならPowerShellを起動し、対象フォルダーへ移動してから以下を実行します。

New-Item -ItemType Directory -Force build | Out-Null
$sources = Get-ChildItem "starter/src/training/maintenance/order" -Filter '*.java' | ForEach-Object { $_.FullName }
javac -encoding UTF-8 -d build @sources
java -cp build training.maintenance.order.AcceptanceCheck
$LASTEXITCODE

javac はJavaのソースを .class 形式に変換するコンパイラです。-encoding UTF-8 は文字コードの指定です。-d build は生成した .class の出力先を指定します。

-cp build はJava実行時にクラスを探す場所の指定です。初回は FAIL が表示されるのが正しい初期状態です。これは失敗を直す練習なので、失敗の原因を調べる前に solution を見ないでください。

この節の独学チェック:06. 初回実行:修正前の失敗を確認する

確認問題: 修正前の検証で19件中10件が失敗したら、環境構築に失敗したと断定しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

テストが失敗すること自体が演習の狙いです。

ヒント2

コンパイルエラーとassert不一致を区別します。

ヒント3

教材が指定した失敗件数・テスト名をログと比較してください。

模範解答と理由

断定しません。不具合再現用スターターで意図的な失敗があるため、期待したテスト名と失敗原因を確認します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: テスト失敗だけで環境構築失敗と断定できない。
  2. 1点: スターターの意図的な不具合とテスト失敗の内容を照合する。

満点の正答例: 断定しません。不具合再現用スターターで意図的な失敗があるため、期待したテスト名と失敗原因を確認します。

部分点の判定: 部分正答例:「テスト失敗だけで環境構築失敗と断定できない」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「テスト失敗だけで環境構築失敗と断定できない」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「06. 初回実行:修正前の失敗を確認する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

07. テストケースとは何か

テストケースは「事前条件・操作または入力・期待結果」の組です。例えば在庫が5個という開始条件を決めないと、注文後の在庫が3個になるかどうかを正しく判定できません。

例えば商品Coffeeに数量2を指定して注文すると、金額は800円になり、在庫は5から3へ変化するはずです。AcceptanceCheck.java は期待結果と実行結果を照合します。

テストの各行には日本語の項目名が付いています。まず失敗した行だけを控え、共通する原因を考えてください。

正常系 は正しい入力が想定どおりに処理されるかを見るテストです。異常系 は存在しない商品や負の数量などの不正な入力に対する動作を確認します。境界値 は数量0と1のように判断が切り替わる値を意味します。

これらはすべて改修の前後に必要です。

この節の独学チェック:07. テストケースとは何か

確認問題: 「事前条件」の例として二重取消のテストで何を準備しますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

1回目の取消後の注文状態を考えます。

ヒント2

2回目の取消時に初期状態と同じではありません。

ヒント3

事前に1回取り消した注文を用意する手順を書きます。

模範解答と理由

注文が成立し、1回目の取消が終わっている状態を準備して2回目の取消を試します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 注文が成立し、1回目の取消が終わっている状態を準備して2回目の取消を試します。

満点の正答例: 注文が成立し、1回目の取消が終わっている状態を準備して2回目の取消を試します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「注文が成立し、1回目の取消が終わっている状態を準備して2回目の取消を試します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「07. テストケースとは何か」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

08. Eclipseで値を追う

Eclipseで OrderService.java を開き、place() にある在庫更新行の左端をダブルクリックします。青い丸(環境によって表示色は異なります)が付けばブレークポイントが設定されています。

AcceptanceCheck.java を右クリックして Debug As → Java Application で起動します。

停止したらVariablesビューで quantity、p.stock()、p.price() を確認します。

Step Over は現在の行を実行して次へ進み、Step Into は呼び出したメソッドの内部に入ります。何が変わったかをメモしたら Resume で続行できます。

どのクラスを変更すればよいか分からない場合、ProductController から ProductService へ進み、search の戻り値を比較します。すべてのクラスを書き直す必要はありません。

理解を深める:例題:購入金額に送料が追加されない

問い合わせ:「1,000円未満の注文には送料500円が必要なはずなのに、合計に含まれないことがある」。この時点では、原因がController・Service・計算用クラスのどこにあるかは分かりません。まず仕様を文章で確認します。

「1,000円未満なら500円を追加」「1,000円以上なら送料0円」です。

手順1:現象を小さな入力で再現する

商品代金 期待する送料 確認したいこと
999円 500円 境界の直前
1,000円 0円 境界ちょうど
1,001円 0円 境界の直後

テスト前に、この表を仕様から作ります。表が作れなければ、まず仕様の意味を確認してください。

手順2:入口から処理を追う

CheckoutController
  → CheckoutService.calculateTotal()
      → ShippingPolicy.shippingFee()

呼び出し元から順に追うと、どのメソッドで金額が変化するか分かります。メソッド名だけで判断せず、引数と戻り値を記録してください。

手順3:原因となる条件式を確認する

class ShippingPolicy {
    int shippingFee(int subtotal) {
        return subtotal <= 1000 ? 500 : 0; // 不具合のある例
    }
}

<= は「以下」なので、1,000円でも500円が付いてしまいます。要求は「未満」なので、条件式は < 1000 であるべきです。

この1文字を変える前に、999・1000・1001円の3ケースを用意することで、修正後に期待どおりか確認できます。

手順4:最小の変更を加えて再確認する

return subtotal < 1000 ? 500 : 0;

修正したら3件を再実行し、既存の正常例も確認します。関連しない命名変更や整形を同時に入れない方が、何を直したか説明しやすくなります。

手順5:調査報告に残す

現象:1,000円の注文に送料500円が加算された。原因:送料判定に「以下」を使っていた。変更:<= を < へ修正。確認:999円、1,000円、1,001円の境界値テストを実施し期待結果と一致。影響範囲:同じ送料計算を利用する呼び出し元を確認する必要がある。

この節の独学チェック:08. Eclipseで値を追う

確認問題: Eclipseのデバッガーで停止したときに調べるものは何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

ブレークポイント位置で現在の変数を確認します。

ヒント2

呼び出し元と呼び出し先を追ってください。

ヒント3

次の1行で在庫や注文状態がどう変わるか予想します。

模範解答と理由

現在の呼び出し箇所、変数の値、次に呼ばれるメソッドを確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 現在の呼び出し箇所、変数の値、次に呼ばれるメソッドを確認します。

満点の正答例: 現在の呼び出し箇所、変数の値、次に呼ばれるメソッドを確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「現在の呼び出し箇所、変数の値、次に呼ばれるメソッドを確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「08. Eclipseで値を追う」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

09. 影響範囲を調べる

例として、OrderService.place を修正した場合、OrderController.place の呼び出し方法、在庫更新、注文保存に影響します。

Eclipseではメソッド名を選択して References → Workspace(環境により Ctrl+Shift+G)で参照元を探せます。

findById を変更した場合は、検索・注文・取消のどの処理から呼ばれるかを記録します。

変更候補 影響を確認する操作
商品検索の条件 大文字小文字・空文字・null・該当なし
注文の金額 数量2、在庫減算、0・負数量
重複注文の拒否 注文レコード・注文先商品の在庫
取消の条件 取消後の状態・在庫・二度目の取消

この節の独学チェック:09. 影響範囲を調べる

確認問題: 注文取消を修正したら、注文登録のテストは不要ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

注文登録と取消で共通する処理を探します。

ヒント2

取消だけ直しても共通在庫処理が変わる可能性があります。

ヒント3

以前成功していた注文登録のケースも実行します。

模範解答と理由

不要ではありません。在庫処理を共有しているなら注文登録も影響を受けるため回帰確認します。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 不要ではありません。
  2. 1点: 在庫処理を共有しているなら注文登録も影響を受けるため回帰確認します。

満点の正答例: 不要ではありません。在庫処理を共有しているなら注文登録も影響を受けるため回帰確認します。

部分点の判定: 部分正答例:「不要ではありません」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「不要ではありません」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「09. 影響範囲を調べる」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

10. 修正する前に作業ブランチを作る

第08章のGitを利用し、変更前に git status を実行して未保存の変更がないか確認します。

初めてこのフォルダーでGitを使う場合は練習用のコピーを作り、そのコピーを git init してから最初のコミットを行ってください。

git switch -c fix/order-maintenance で専用ブランチを作り、小さな単位で修正します。実際の会社のリポジトリの場合は作業ルールを優先してください。

この節の独学チェック:10. 修正する前に作業ブランチを作る

確認問題: 修正前に作業ブランチを作る理由は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

mainを直接変更した場合の復旧を考えます。

ヒント2

修正差分を分離して記録する方法を思い出します。

ヒント3

作業ブランチで履歴を保つ利点を説明します。

模範解答と理由

元のコードを保持したまま変更差分を追い、安全にレビュー・復旧できるためです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 元のコードを保持したまま変更差分を追い、安全にレビュー・復旧できるためです。

満点の正答例: 元のコードを保持したまま変更差分を追い、安全にレビュー・復旧できるためです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「元のコードを保持したまま変更差分を追い、安全にレビュー・復旧できるためです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「10. 修正する前に作業ブランチを作る」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

11. 改修と回帰テスト

まず商品検索を修正し、再度すべてのテストを実行します。次に注文数量・注文金額・重複IDの問題を修正し、最後に二重取消の動作を修正します。修正するたびに 全件 を実行してください。

ある不具合が直っても、それ以外の機能が壊れていないか確認する試験を回帰テストといいます。

エラーを無視して先へ進むのではなく、期待結果・実測結果・変更したメソッドを記録します。テストに失敗した場合は、直前に変更した行を調べ、想定外の副作用がないか確認します。

理解を深める:演習本体に応用するヒント

今度は送料ではなく、商品検索・注文・取消を扱います。たとえば「取消を2回実行すると在庫はどうなるべきか」を、仕様→変更前の結果→関連クラス→原因仮説→最小修正→確認の順番で調べます。

最初から解答のソースを見るのではなく、発見した現象を短い文章で残してください。

理解を深める:本課題に取り組む際の考え方

実際の第09章の演習では、どの条件式を直すべきかを先に決めつけないでください。仕様書のルールを1件ずつ表にし、初期テストで再現し、処理の入口から呼び出しを追います。原因の仮説と、確認した証拠を分けて記録してください。

指導者用の完成コードは、受講者への配布物に含めないでください。

この節の独学チェック:11. 改修と回帰テスト

確認問題: 修正後にテストが19件中19件成功すれば、本番の同時注文に対応できたと言えますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

19件のテストが検査する範囲を確かめましょう。

ヒント2

複数端末から同時実行するケースがあるか調べます。

ヒント3

メモリー上の単純な処理と本番のDB競合を区別します。

模範解答と理由

言えません。この演習はメモリー上の単純な実行で、DBのロックや並行実行を検証していません。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: この演習はメモリー上の単純な実行で、DBのロックや並行実行を検証していません。

満点の正答例: 言えません。この演習はメモリー上の単純な実行で、DBのロックや並行実行を検証していません。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「この演習はメモリー上の単純な実行で、DBのロックや並行実行を検証していません」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「11. 改修と回帰テスト」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:改修と回帰テスト

改修と回帰テスト

図の読み方:改修後は不具合だけでなく、以前から動いていた機能も確認します。

12. 本番システムとの違い

この教材のRepositoryはメモリー保存で、複数端末からの同時注文、DB接続断、途中で処理に失敗したときのロールバックは扱いません。本番ではこれらを考慮する必要があります。

受講者は「今回は何が確認できて、何がまだ確認できないか」を報告書に書いてください。実務では、確認していないことを確認済みと報告しないことも重要な技術です。

この節の独学チェック:12. 本番システムとの違い

確認問題: 本番の注文システムで新たに必要な考慮点を一つ挙げてください。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

同じ在庫を複数の人が同時注文する場面を考えます。

ヒント2

一方の更新中に他方が割り込む場合があります。

ヒント3

排他・トランザクション・監視から一例を選びます。

模範解答と理由

例えば複数端末からの同時注文に対する排他制御、トランザクション、運用監視などです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 例えば複数端末からの同時注文に対する排他制御、トランザクション、運用監視などです。

満点の正答例: 例えば複数端末からの同時注文に対する排他制御、トランザクション、運用監視などです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「例えば複数端末からの同時注文に対する排他制御、トランザクション、運用監視などです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「12. 本番システムとの違い」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

13. 改修報告を提出する

提出用テンプレートをコピーし、修正前の結果、原因、修正したクラス・メソッド、修正後の結果、残った懸念点を記載します。指導者は提出内容と実際のソース差分・テスト結果を照合します。

この節の独学チェック:13. 改修報告を提出する

確認問題: 改修報告に最低限記載したい項目は何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

レビュアーが変更理由を再現できるか考えます。

ヒント2

変更ファイルとテスト結果だけで仕様に対応できますか。

ヒント3

要求・差分・検証・未確認事項を整理します。

模範解答と理由

要求、変更ファイル、修正内容、テスト結果、未確認事項、影響範囲です。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 要求・修正内容・変更ファイルを記録する。
  2. 1点: テスト結果・影響範囲・未確認事項を記録する。

満点の正答例: 要求、変更ファイル、修正内容、テスト結果、未確認事項、影響範囲です。

部分点の判定: 部分正答例:「要求・修正内容・変更ファイルを記録する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「要求・修正内容・変更ファイルを記録する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「13. 改修報告を提出する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

14. 第03〜08章の知識との関連

クラスとinterfaceは第03章、ListやMapは第04章、DBを使う場合の注意は第05章、ControllerとServiceの分離は第06章、テストは第07章、Gitのコミット・ブランチは第08章で学習しました。

ここではそれらを組み合わせて、知らない既存コードを調査します。特に「どこが処理の入口なのか」「どの値が変化したか」「修正の影響はどこまで及ぶか」を意識してください。

この節の独学チェック:14. 第03〜08章の知識との関連

確認問題: 第03章と第07章の知識は第09章のどこで使いますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

第03章はクラス同士の責務を扱いました。

ヒント2

第07章はテストによる確認を扱いました。

ヒント3

呼び出しの追跡と回帰テストへそれぞれ当てはめます。

模範解答と理由

クラス間の責務・参照を追跡し、修正後に単体・回帰テストで仕様を確認する場面です。

この節の自己採点基準(2点満点)

独立して判定する正答要素

  1. 1点: 第03章の知識でクラス間の責務と参照を追う。
  2. 1点: 第07章の知識で単体・回帰テストを行う。

満点の正答例: クラス間の責務・参照を追跡し、修正後に単体・回帰テストで仕様を確認する場面です。

部分点の判定: 部分正答例:「第03章の知識でクラス間の責務と参照を追う」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「第03章の知識でクラス間の責務と参照を追う」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:2/2点。 正答の言い換えは認めます。

復習先: この節「14. 第03〜08章の知識との関連」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

15. よくあるエラーと対処

  • javac は認識されません:JDK 21のPATH設定を第01章に戻って確認します。
  • file not found:order-maintenance フォルダーにいるか pwd で確認します。
  • Could not find or load main class:コンパイル先 build と -cp build が一致しているか確認します。
  • IllegalArgumentException:異常系で期待した例外か、不具合による例外かを仕様表と照合します。
  • Eclipseでパッケージエラー:Javaファイルの先頭に書かれた package training.maintenance.order; とフォルダーの対応を確認します。
  • 修正後も古い結果になる:コンパイルし直し、同名クラスの複数コピーが混ざっていないか確認します。

この節の独学チェック:15. よくあるエラーと対処

確認問題: 修正前のテストに失敗したとき、環境とロジックをどう見分けますか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

javacや起動そのものが失敗しているか確認します。

ヒント2

起動は成功しassertだけ失敗する場合を考えます。

ヒント3

環境由来と業務ロジック由来の失敗を分けて記録します。

模範解答と理由

コンパイル・起動自体の失敗か、テストの期待値と実際値が一致しないかを切り分けます。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: コンパイル・起動自体の失敗か、テストの期待値と実際値が一致しないかを切り分けます。

満点の正答例: コンパイル・起動自体の失敗か、テストの期待値と実際値が一致しないかを切り分けます。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「コンパイル・起動自体の失敗か、テストの期待値と実際値が一致しないかを切り分けます」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「15. よくあるエラーと対処」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

16. 理解度確認

  1. Controller、Service、Repositoryを分ける理由を説明してください。
  2. 商品検索が失敗したとき、どのクラスから確認しますか。
  3. 数量0の注文を拒否するチェックはなぜ必要ですか。
  4. 同じ注文を二度登録したとき、在庫が変わってはいけない理由は何ですか。
  5. 取消を二度行うと在庫にどのような問題が起きますか。
  6. 一つの機能を修正した後に全テストを再実行する理由は何ですか。
  7. 今回のアプリでMySQLのトランザクションを検証したと言えますか。

この節の独学チェック:16. 理解度確認

確認問題: 改修演習の自己評価でテスト成功だけを見れば十分ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

テストが緑でも変更箇所を説明できるでしょうか。

ヒント2

要件とコード差分を突き合わせます。

ヒント3

仕様解釈と報告の根拠まで確認してください。

模範解答と理由

不十分です。仕様の解釈、変更範囲、報告書の根拠も確認します。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 仕様の解釈、変更範囲、報告書の根拠も確認します。

満点の正答例: 不十分です。仕様の解釈、変更範囲、報告書の根拠も確認します。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「仕様の解釈、変更範囲、報告書の根拠も確認します」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「16. 理解度確認」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

17. 他言語経験者向け発展

Javaのrecordはデータをまとめた不変に近い値オブジェクトの定義に使えます。Optional は値が存在しない可能性を戻り値で表す型です。Map による保存は単純ですが、並行スレッドでの整合性は保証しません。

実務でDB保存に変える場合、Service層でのトランザクション境界、ユニーク制約、同時在庫引当の方法を設計してください。これは追加課題であり、基本演習の合格条件には含めません。

この節の独学チェック:17. 他言語経験者向け発展

確認問題: 他言語経験者向けの拡張で注意することは何ですか。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

既存コードの設計変更には副作用があります。

ヒント2

例外の種類や公開メソッドの契約が変わるか考えます。

ヒント3

新しい設計でも従来テストを維持する条件を探します。

模範解答と理由

例外処理やメソッド設計を見直しても既存動作・テスト条件を破壊しないことです。

この節の自己採点基準(1点満点)

独立して判定する正答要素

  1. 1点: 例外処理やメソッド設計を見直しても既存動作・テスト条件を破壊しないことです。

満点の正答例: 例外処理やメソッド設計を見直しても既存動作・テスト条件を破壊しないことです。

部分点の判定: 正答要素は1つなので部分点はありません。意味が一致すれば1点、異なれば0点です。

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「例外処理やメソッド設計を見直しても既存動作・テスト条件を破壊しないことです」を示していないので0点です。

合格条件:1/1点。 正答の言い換えは認めます。

復習先: この節「17. 他言語経験者向け発展」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

18. 完了条件

テスト全19件PASS、終了コード0、修正理由の説明、影響範囲表、Git差分、報告書の提出がそろったら基本課題を合格とします。指導者による受講者実機操作の確認は別途必要です。

学習内容を振り返るための操作確認

この節は、本文の例題や演習が実行できないときに戻るための案内です。最初にファイルの場所と作業中のツールを確認し、コマンドを貼り付ける前に現在のフォルダーを確認してください。

実行する場所と順序

PowerShellで examples/09_maintenance/order-maintenance へ移動し、Get-Location と Test-Path "starter/src/training/maintenance/order" を確認してからREADMEのコンパイル手順を実行します。

成功・失敗の判断

修正前のテストがFAILとなることが正しい開始状態です。修正後は19件全件PASSと終了コード0を確認します。

途中で止まったとき

修正前のFAILを環境構築の失敗と混同しないでください。一方 javac のエラーや ClassNotFoundException は演習開始前に解決が必要です。

作業記録の書き方

  1. 利用環境(OS、Java、必要なツールのバージョン)を記録します。
  2. 実際に操作したフォルダー、実行コマンド、入力内容を記録します。
  3. 期待した結果と実際の結果を別々に書きます。失敗時にはエラーメッセージの全文を保管します。
  4. 修正を加えた場合は変更箇所を記録し、同じ手順で再確認します。
  5. 成功を確認できていなければ「未確認」と記載し、成功と推測して次へ進まないでください。

実際の入力、実行結果、原因の説明、演習の提出物がそろって初めて章の学習を完了とします。

独学用ステップ演習

完全未経験者は、本文を読んだ後、段階別ヒント・自己採点付きの独学演習へ進んでください。最初から最終課題のすべてを実装する必要はありません。

この節の独学チェック:18. 完了条件

確認問題: 第09章の完了基準を説明してください。

取り組み方: 解答を見る前に自分の答えを記録してください。

ヒント1

何を直す課題だったか仕様書に戻りましょう。

ヒント2

修正前に失敗した19件の結果を思い出します。

ヒント3

全件成功だけでなく変更理由と影響範囲の報告まで確認します。

模範解答と理由

指定された不具合を修正し、全19件のテストを成功させ、影響範囲と結果を報告することです。

この節の自己採点基準(3点満点)

独立して判定する正答要素

  1. 1点: 指定された不具合を修正する。
  2. 1点: 19件すべてのテストを成功させる。
  3. 1点: 影響範囲と結果を報告する。

満点の正答例: 指定された不具合を修正し、全19件のテストを成功させ、影響範囲と結果を報告することです。

部分点の判定: 部分正答例:「指定された不具合を修正する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「指定された不具合を修正する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

合格条件:3/3点。 正答の言い換えは認めます。

復習先: この節「18. 完了条件」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。