第10章 総合実務課題

10_final_project

第10章 総合実務課題:商品・注文管理システム(改訂版)

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

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

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

対象:Java未経験から第01〜09章まで学んだ人/他言語経験者。Java 21、Eclipse、Maven、MySQL 8.4、Windows 11を使用。クラウドとGitHubは不要です。

独学時の注意: 商品・在庫・注文管理が本課題です。本文に登場する「会員表示名」などの別題材のお手本は、考え方を学ぶための独立した例であり、配布スターターにその機能が存在することを意味しません。

01. この章で達成すること

この章では、既存のWebアプリケーションに機能を追加します。完成後はテスト結果を用いて、要求仕様を満たしていることを示します。**完成コードを一から書き写す課題ではありません。

** あなたは途中まで開発された店舗用の商品管理システムを引き継ぐ担当者です。

受講者には examples/10_final_project/starter/product-web と本教材、SQL、受け入れテストの仕様を配布します。指導者向けの完成例は別の場所にあります。

到達目標は「仕様を読む」「変更箇所を見つける」「小さく実装する」「テストで根拠を示す」「他者が再現できる報告を書く」の5つです。実行できない項目がある場合は、その内容と原因を作業記録に残してください。

未確認の項目を確認済みとして報告してはいけません。

この節の独学チェック:01. この章で達成すること

確認問題: 総合課題で最終的に納品するものは何ですか。

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

ヒント1

総合課題の成果物一覧を読み直します。

ヒント2

コードが動くだけでは提出物が揃っていない可能性があります。

ヒント3

実装・テスト結果・報告書を分けてチェックします。

模範解答と理由

改修したSpring Bootアプリ、テスト結果と作業報告書など、課題で指定された成果物です。

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

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

  1. 1点: 課題を実装したSpring Bootアプリを納品する。
  2. 1点: テスト結果を提出する。
  3. 1点: 作業報告書を提出する。

満点の正答例: 改修したSpring Bootアプリ、テスト結果と作業報告書など、課題で指定された成果物です。

部分点の判定: 部分正答例:「課題を実装したSpring Bootアプリを納品する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「課題を実装したSpring Bootアプリを納品する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

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

02. 用語を確認する

API はプログラムが他のプログラムとやり取りするための入口です。HTTP はブラウザやテスト用ツールがWebサーバーと通信するときの決まりです。

Controller はHTTPを受け付け、Service は業務ルールを実行し、Repository はDBへの読み書きを担当します。

トランザクション は、複数のDB操作を一まとまりとして確定または取り消すための仕組みです。ただし「失敗したら必ず何でも取り消される」わけではありません。

対象の操作が同じトランザクションに参加していること、ロールバックされる例外や設定、DBの対応状況が条件になります。回帰テスト は修正後も既存の機能が壊れていないことを確認するテストです。

意味が曖昧なら第05〜09章を読み直します。

この節の独学チェック:02. 用語を確認する

確認問題: 商品管理システムで「在庫」と「注文」を一緒に扱う難しさは何ですか。

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

ヒント1

注文は在庫数を変化させる処理です。

ヒント2

注文履歴だけ保存できても正しいとは限りません。

ヒント3

注文と在庫の二つのデータを同時に整合させる必要を考えます。

模範解答と理由

注文の登録と在庫減算が食い違わないように整合性を守る必要があるためです。

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

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

  1. 1点: 注文の登録と在庫減算が食い違わないように整合性を守る必要があるためです。

満点の正答例: 注文の登録と在庫減算が食い違わないように整合性を守る必要があるためです。

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

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「注文の登録と在庫減算が食い違わないように整合性を守る必要があるためです」を示していないので0点です。

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

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

03. 配布フォルダーと重要な注意

starter/product-web は作業開始用の未完成アプリです。schema.sql は最終的なDBテーブル定義、api-spec.md は通信仕様です。

verification/api-check.ps1 はWindowsでAPIの代表的な動作を確認する補助ツールです。初期アプリには商品一覧と登録の一部だけがあり、注文やMySQL接続はまだありません。

初期状態では未実装の機能があるため、API検証スクリプトのすべての項目は成功しません。各マイルストーンに対応する機能を実装してから、その項目を確認します。

受講者配布用ZIPには指導者用完成コードを入れません。 instructor/complete-product-web は指導者が答え合わせに使うプロジェクトです。

この節の独学チェック:03. 配布フォルダーと重要な注意

確認問題: 受講者スターターと指導者完成版の違いは何ですか。

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

ヒント1

配布物に含まれる二つの版を確認します。

ヒント2

未完成の部分を受講者が実装するのはどちらでしょうか。

ヒント3

最初から完成コードを見ることが学習上適切か考えます。

模範解答と理由

スターターは改修対象の初期状態で、完成版は課題を実装した解答例です。受講者が最初に完成版を使うものではありません。

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

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

  1. 1点: スターターは改修対象の初期状態で、完成版は課題を実装した解答例です。
  2. 1点: 受講者が最初に完成版を使うものではありません。

満点の正答例: スターターは改修対象の初期状態で、完成版は課題を実装した解答例です。受講者が最初に完成版を使うものではありません。

部分点の判定: 部分正答例:「スターターは改修対象の初期状態で、完成版は課題を実装した解答例です」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「スターターは改修対象の初期状態で、完成版は課題を実装した解答例です」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

復習先: この節「03. 配布フォルダーと重要な注意」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

04. まずスターターを起動する

  1. 第01章で導入したJava 21が利用できることを java -version で確認します。メジャーバージョンが21でなければ第01章に戻ります。
  2. 作業用の場所に starter/product-web をフォルダーごとコピーします。元ファイルは比較用に残します。
  3. Eclipseの「File → Import → Maven → Existing Maven Projects」を開き、コピーした product-web を指定します。pom.xml が認識されていることを確認し、Finishをクリックします。
  4. Mavenの依存関係ダウンロードが終わることを確認します。初回はインターネットへの接続が必要です。アプリ本体とMySQLはローカルで動作します。
  5. ProductWebApplication.java を右クリックし、Run As → Java Applicationで実行します。起動ログにエラーがなければ http://localhost:8080/api/products にアクセスします。
  6. 取得したHTTPステータスとJSONを作業記録に書きます。ブラウザからのGETだけでなく、第06章の手順に従ってPOSTも実施してください。

起動に失敗したら: java -version、Maven dependencies、コンソール末尾のCaused by:、8080番ポートの競合を順に調べます。

Connection refused はアプリが起動していない可能性があります。404 はURLとHTTPメソッドを確認してください。ここで動かないまま次へ進みません。

この節の独学チェック:04. まずスターターを起動する

確認問題: スターター起動直後に、全ての注文機能が動くと考えてよいですか。

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

ヒント1

スターターは全機能の完成品ではありません。

ヒント2

既に動くAPIと未実装のAPIを区別します。

ヒント3

起動確認と要件達成の確認を分けて考えてください。

模範解答と理由

いいえ。スターターにない機能は実装対象です。まず初期状態と未実装機能を確認します。

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

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

  1. 1点: スターターにない機能は実装対象です。
  2. 1点: まず初期状態と未実装機能を確認します。

満点の正答例: いいえ。スターターにない機能は実装対象です。まず初期状態と未実装機能を確認します。

部分点の判定: 部分正答例:「スターターにない機能は実装対象です」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「スターターにない機能は実装対象です」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

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

05. 既存コードを読み、処理の道筋を描く

ProductController は入口、ProductService は商品を扱う処理、Product は商品データを表します。

GET /api/products の処理を起点に、どのメソッドが呼ばれ、どのJavaオブジェクトがJSONになるのか、クラス名とメソッド名を紙に書き出してください。

いきなりコードを書き換えず、まず現状を説明できる状態にします。

HTTP要求 → ProductController → ProductService → 現在はメモリー上の商品
                                              ↓
HTTP応答 ← JSONに変換された商品データ ← Product

理解を深める:例題:商品メモを登録できるようにする

依頼内容は「商品に補足メモを持たせたい。メモは空でもよいが、100文字以下とする」です。

曖昧な部分を残したまま実装しないため、まず「改行は文字数に含めるか」「既存データはどう扱うか」「APIの入出力にメモを含めるか」を確認事項に分けます。

今回はJavaの String.length() で100以下、未指定は空文字列、APIへ含めるという練習用仕様を置きます。実務なら担当者の合意を取ってから確定します。

**手順1:変更箇所を洗い出す。

** Product がデータを表し、ControllerがJSONを受け付け、Serviceが入力確認を行い、Repositoryが保存を担当する構成なら、4つすべてに影響する可能性があります。

ひとつのクラスを変える前に、どの境界でデータが受け渡されるかを紙に書きます。

手順2:受け入れ条件を書く。 「未指定→空文字列」「100文字→登録成功」「101文字→入力エラー」「登録後取得→同じメモを返す」「既存の商品一覧→以前と同様に取得できる」を確認条件とします。

この段階でHTTPのステータスや表示形式も仕様と照らし合わせます。

手順3:一番小さい単位から実装する。 まずService相当のメモ検証処理を考えます。

static String normalizeMemo(String memo) {
    String result = memo == null ? "" : memo;
    if (result.length() > 100) {
        throw new IllegalArgumentException("メモは100文字以内です");
    }
    return result;
}

このメソッドは説明用の独立した抜粋です。既存アプリのServiceにそのまま存在するわけではありません。null は入力が未指定の場合、三項演算子 条件 ? A : B は条件が真ならA、偽ならBを選びます。

101文字なら例外になるので、HTTPの入力エラーへ変換する必要があるかを第06章へ戻って確認します。

手順4:保存・取得をつなぐ。 メモがJavaの中だけに存在しても、DBへ書き込まなければ再起動後には失われます。

MySQLへ保存する課題なら列の追加、INSERT/UPDATE、SELECT、APIレスポンスへの反映まで変更点を洗い出します。

実際のSQLは既存のDB設計と移行方針に合わせて作成し、ここで一方的に本課題のスキーマを変更しません。

手順5:以前の機能を壊していないか確認する。 メモを追加しても、名前・価格・在庫・一覧表示が変わらないことを確認します。新機能のテストに通るだけでは不足です。

作った箇所と、影響を受ける既存箇所を両方検証するのが実務開発です。

別のお手本:会員の表示名変更(本課題とは別の例)

ここからは商品メモの例とは独立した、会員情報の変更を題材とするお手本です。**第10章の受講者用スターターに会員管理機能があるという意味ではありません。

** 設計の進め方を学ぶための架空の例として読み、商品・注文管理アプリにそのまま貼り付けないでください。

理解を深める:手順1:依頼内容を受け取ってあいまいさを消す

「会員の表示名を変更できるようにしてほしい」

この一文だけでは、空文字は許されるか、会員が存在しない場合はどうするか、変更結果をどう返すか分かりません。実務では依頼者に質問します。例題では次の仕様を仮定します。

  • 会員IDは正の整数とする。
  • 表示名は前後の空白を取り除いた後、1〜30文字とする。
  • 存在しない会員は「見つからない」エラーとする。
  • 更新が成功したら会員IDと更新後の表示名を返す。

理解を深める:手順2:処理の責任を分ける

HTTP PUT /members/{id}/display-name
  ↓ Controller: HTTPの値を受け取り応答へ変換
  ↓ Service: 形式・長さ・存在確認の業務判断
  ↓ Repository: 会員を検索・更新
  ↓ DB: 保存

すべてControllerに書くと業務ルールがWeb層に埋まり、テストが難しくなります。Serviceに判定をまとめると、画面側が変わっても同じ規則を利用しやすくなります。

この節の独学チェック:05. 既存コードを読み、処理の道筋を描く

確認問題: ControllerからDBまでの処理をどんな順番で追いますか。

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

ヒント1

HTTP要求の受付箇所を探します。

ヒント2

業務判断とDBアクセスを行うクラスを順に追います。

ヒント3

Controller→Service→Repositoryから実際のクラス名を調べます。

模範解答と理由

Controller→Service→Repository→DBです。実際のクラス名とメソッドを調べます。

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

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

  1. 1点: Controller→Service→Repository→DBです。
  2. 1点: 実際のクラス名とメソッドを調べます。

満点の正答例: Controller→Service→Repository→DBです。実際のクラス名とメソッドを調べます。

部分点の判定: 部分正答例:「Controller→Service→Repository→DBです」。この記述だけなら1点で、残る正答要素は未達です。

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

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

復習先: この節「05. 既存コードを読み、処理の道筋を描く」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:商品・在庫・注文の全体構成

商品・在庫・注文の全体構成

図の読み方:総合課題では商品・在庫・注文に関する処理をレイヤー間で連携させます。

06. マイルストーンA:在庫付き商品と詳細検索

商品データは id(正の整数)、name(1〜50文字)、price(0以上の整数円)、stock(0以上)です。

Product、入力値、Service、Controllerの修正箇所をリストアップしてから変更します。

GET /api/products/{id} を追加し、存在しなければ404、価格-1・在庫-1・空の商品名なら400にします。在庫が0の商品は登録できます。

変更のたびに、GET /api/products、POST /api/products、GET /api/products/{id} の3種類を確認し、変更前に動いていた一覧も再確認してください。

エラー時の応答が500なら、入力不備を適切に扱えていない可能性があります。

理解を深める:本課題での考え方

この例では「メモ」でしたが、本課題では在庫と注文を扱います。注文では処理を途中で確定すると不整合が起こり得るため、第05章のトランザクションの説明に戻ってください。

機能を実装するときは、必ず「仕様」「変更候補のクラス」「受け入れ条件」「確認した結果」を対応付けます。

会員表示名のお手本・手順3:判定ロジックを単独で書く

public class DisplayNameRules {
    public static String normalize(String name) {
        if (name == null) {
            throw new IllegalArgumentException("表示名が必要です");
        }
        String normalized = name.trim();
        if (normalized.isEmpty() || normalized.length() > 30) {
            throw new IllegalArgumentException("表示名は1〜30文字です");
        }
        return normalized;
    }
}

1行ずつ確認します。null のチェックが最初なのは、null.trim() を呼ぶと例外になるためです。trim() で前後の空白を除き、isEmpty() で空になっていないか確かめます。

length() はJavaの文字数の表現上、Unicodeの見た目の文字数と常に一致するとは限りません。この例題ではUTF-16コードユニット長で判定する簡易仕様とし、絵文字などへの厳密な対応は発展課題にします。

この節の独学チェック:06. マイルストーンA:在庫付き商品と詳細検索

確認問題: 在庫数-1の商品を登録してよいですか。

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

ヒント1

在庫数が負になる商品を考えます。

ヒント2

入力値のチェックに通してよいか確認します。

ヒント3

拒否した後、DBの値が変更されないことも考えてください。

模範解答と理由

仕様上、不正な在庫値として登録を拒否し、保存内容を変更しないようにします。

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

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

  1. 1点: 仕様上、不正な在庫値として登録を拒否し、保存内容を変更しないようにします。

満点の正答例: 仕様上、不正な在庫値として登録を拒否し、保存内容を変更しないようにします。

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

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「仕様上、不正な在庫値として登録を拒否し、保存内容を変更しないようにします」を示していないので0点です。

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

復習先: この節「06. マイルストーンA:在庫付き商品と詳細検索」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

07. マイルストーンB:MySQLへ保存する

第05章の training_db とは別に、training_final_db を作ります。第05章とはIDと価格の型が異なるため、同じテーブルを使い回しません。MySQLクライアントで次のSQLを実行します。

CREATE DATABASE IF NOT EXISTS training_final_db CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE USER IF NOT EXISTS 'training_final_user'@'localhost' IDENTIFIED BY '各自で決める長いパスワード';
GRANT SELECT, INSERT, UPDATE, DELETE ON training_final_db.* TO 'training_final_user'@'localhost';

続けて管理者権限で training_final_db を選択し、付属 schema.sql のCREATE TABLE文を実行します。次のコマンドで2テーブルを確認してください。

USE training_final_db;
SHOW TABLES;
DESCRIBE products;
DESCRIBE orders;

JavaアプリではMySQL Connector/JとSpring JDBCを利用し、ProductRepository を作ってDBアクセスを分離します。

Connection情報をJavaコードに書き込まず環境変数で与えます。Windows PowerShellの例:

$env:TRAINING_DB_URL='jdbc:mysql://localhost:3306/training_final_db?connectionTimeZone=UTC'
$env:TRAINING_DB_USER='training_final_user'
$env:TRAINING_DB_PASSWORD='(設定したパスワード)'

このPowerShellからEclipseを起動するか、EclipseのRun ConfigurationのEnvironmentタブで同じ名前を設定します。**パスワードをREADME・コミット・画面写真に含めないでください。

** 既存Serviceの保存先をメモリーからRepositoryに置き換えます。商品を登録してアプリを再起動し、登録した商品が残ることを確かめます。

この節の独学チェック:07. マイルストーンB:MySQLへ保存する

確認問題: メモリー保存をMySQLに変えた後、再起動して何を確認しますか。

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

ヒント1

アプリを停止して再起動する操作を思い浮かべます。

ヒント2

メモリーのListとDB保存の違いを考えます。

ヒント3

保存後に再起動して同じ商品を検索する確認方法を考えます。

模範解答と理由

登録した商品が再起動後もDBに残ることを確認します。

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

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

  1. 1点: 登録した商品が再起動後もDBに残ることを確認します。

満点の正答例: 登録した商品が再起動後もDBに残ることを確認します。

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

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「登録した商品が再起動後もDBに残ることを確認します」を示していないので0点です。

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

復習先: この節「07. マイルストーンB:MySQLへ保存する」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

08. マイルストーンC:在庫更新と注文登録

PATCH /api/products/{id}/stock では新しい在庫数を指定します。存在しないIDなら404、負数なら400です。

POST /api/orders は商品IDと数量を受け取ります。数量は1以上で、在庫より多ければ409を返します。商品が存在しなければ404です。

成功時は201を返し、注文ID、商品ID、数量、注文時の単価を保存します。現在の単価が後から変化しても注文時の価格は変えません。

注文処理は複数ステップです。まず商品を調べ、条件付きUPDATEで在庫を減らし、注文をINSERTします。この2つのDB操作は1つのトランザクション内で行います。

UPDATE products SET stock = stock - ? WHERE id = ? AND stock >= ?;

更新件数が1件であることを確認します。0件なら在庫不足などで更新されていません。

@Transactional をServiceの公開メソッドに付け、注文INSERTが失敗した場合には在庫減算もロールバックされる構造にします。二重注文で負の在庫が起きないようにするには、アプリ内のifだけでは不十分です。

DBの条件付きUPDATEが重要です。

この節の独学チェック:08. マイルストーンC:在庫更新と注文登録

確認問題: 在庫3の商品へ数量4の注文を受けたらどうすべきですか。

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

ヒント1

在庫数と注文数量を数値で比べてみましょう。

ヒント2

注文履歴だけ登録されたら何が困りますか。

ヒント3

エラー時に在庫も履歴も元の状態を保つか考えます。

模範解答と理由

在庫不足として注文を拒否し、注文履歴と在庫に不整合を残さないようにします。

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

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

  1. 1点: 在庫不足として注文を拒否し、注文履歴と在庫に不整合を残さないようにします。

満点の正答例: 在庫不足として注文を拒否し、注文履歴と在庫に不整合を残さないようにします。

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

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「在庫不足として注文を拒否し、注文履歴と在庫に不整合を残さないようにします」を示していないので0点です。

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

復習先: この節「08. マイルストーンC:在庫更新と注文登録」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

図解:注文登録時の処理

注文登録時の処理

図の読み方:注文では在庫確認と更新・登録を一体として扱い、不整合を防ぎます。

09. 受け入れテストの実施

番号 内容 期待結果
F01 一覧GET 200 + 商品配列
F02 正常な商品POST 201 + 発行されたID
F03 空の商品名 400
F04 価格-1、在庫-1 400
F05 存在しないIDをGET 404
F06 在庫2の商品を2個注文 201、残在庫0、注文履歴あり
F07 在庫0の商品を1個注文 409、DBの値は変わらない
F08 数量0の注文 400
F09 商品を登録→アプリ再起動 登録商品が残る
F10 注文履歴INSERTを意図的に失敗させる 在庫も元の値に戻る(指導者による検証)

第09章と同様に、入力・期待結果・実際の結果・実行日時・判断を記録します。補助スクリプト verification/api-check.ps1 は実行するたびにテスト商品を1件作成します。**運用DBでは使用しないでください。

** 商品・在庫・注文の正しい状態をMySQLでも確認します。

会員表示名のお手本・手順4:実装より前にテストケースを表にする

入力 期待結果 理由
" 佐藤 " "佐藤" 前後の空白を除去
"" 例外 空欄は禁止
null 例外 未指定は禁止
30文字 成功 上限ちょうど
31文字 例外 上限超過

この表ができれば、JUnitの assertEquals や assertThrows に落とし込みやすくなります。テストはコードに合わせて後から正解を変えるものではありません。

会員表示名のお手本・手順5:レイヤーをつないで結合確認する

Serviceでルールを使用し、Repositoryが実際に更新した件数を確認します。Controllerでは「入力不正」「存在しない」「成功」をHTTP応答へ対応付けます。

単体テストだけでDBへの保存は検証できないため、実DBを使った結合確認を別に行います。更新成功後に再検索して同じ表示名が戻ることも重要です。

この節の独学チェック:09. 受け入れテストの実施

確認問題: 注文履歴のINSERTが失敗したら、その前の在庫減算はどうするべきですか。

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

ヒント1

在庫減算の直後にINSERTが失敗するケースです。

ヒント2

2つのDB更新を別々に確定してよいでしょうか。

ヒント3

一方が失敗したら両方を取り消す仕組みを探してください。

模範解答と理由

同一トランザクションで処理し、失敗時はロールバックして在庫減算も取り消します。

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

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

  1. 1点: 同一トランザクションで処理し、失敗時はロールバックして在庫減算も取り消します。

満点の正答例: 同一トランザクションで処理し、失敗時はロールバックして在庫減算も取り消します。

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

誤答・採点ミスの例: 不十分な解答例:「よく分からないが、そのまま進めればよい」。正答条件「同一トランザクションで処理し、失敗時はロールバックして在庫減算も取り消します」を示していないので0点です。

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

復習先: この節「09. 受け入れテストの実施」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

10. 単体テスト・結合テストの違い

単体テストは対象クラスを依存先から切り離して、業務上の判断を確認します。第07章のMockitoを用いることで、MySQLなしでServiceの入力チェック、404・409分岐を検証できます。

一方、トランザクションの実際のロールバックはMockitoでは証明できません。MySQLを使った結合テストで確かめてください。指導者用の完成プロジェクトには単体テストの例を含めています。

この節の独学チェック:10. 単体テスト・結合テストの違い

確認問題: 単体テストと結合テストの結果が両方必要な理由は何ですか。

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

ヒント1

Serviceだけ動くテストとDBまで動くテストを比べます。

ヒント2

モックで置き換える範囲を確認してください。

ヒント3

業務ロジックと実際の接続の二つが確かめられるか考えます。

模範解答と理由

業務処理単体の正しさとDB等を含む全体の接続を、それぞれ確認するためです。

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

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

  1. 1点: 単体テストで業務処理そのものを確認する。
  2. 1点: 結合テストでDBを含む接続を確認する。

満点の正答例: 業務処理単体の正しさとDB等を含む全体の接続を、それぞれ確認するためです。

部分点の判定: 部分正答例:「単体テストで業務処理そのものを確認する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「単体テストで業務処理そのものを確認する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

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

11. 作業報告とコードレビュー

作業開始時にGitブランチを作り、機能ごとにコミットします。コミットする前に、パスワード・個人情報・DB接続情報が含まれていないことを確認してください。

作業報告には「変更内容」「変更したファイル」「動作確認」「未対応事項」「再現手順」を記載します。結果が期待どおりでない場合は、成功と書かず未完了として原因を記載します。

会員表示名のお手本・手順6:提出時に説明できるようにする

修正内容、仕様との対応、動作確認の入力と期待結果、未確認事項を報告書に残します。**本課題の在庫引当や注文処理も同じ考え方で、仕様→設計→実装→テスト→報告へ進めます。

** ただし、在庫・注文の一貫性にはトランザクションが追加で必要です。この例題のコードは第10章完成プロジェクトに組み込むものではありません。

この節の独学チェック:11. 作業報告とコードレビュー

確認問題: コードレビューに渡す情報として差分以外に何が必要ですか。

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

ヒント1

差分を見ただけで意図まで理解できるでしょうか。

ヒント2

どの仕様に対応する変更か書き出します。

ヒント3

実行条件・テスト結果・未確認事項もレビュー資料に加えます。

模範解答と理由

変更理由、仕様との対応、検証条件と結果、未確認事項です。

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

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

  1. 1点: 変更理由と仕様との対応を示す。
  2. 1点: 検証条件と結果を示す。
  3. 1点: 未確認事項を示す。

満点の正答例: 変更理由、仕様との対応、検証条件と結果、未確認事項です。

部分点の判定: 部分正答例:「変更理由と仕様との対応を示す」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「変更理由と仕様との対応を示す」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

復習先: この節「11. 作業報告とコードレビュー」の本文および直前の例題。誤った採点要素を説明できるまで確認してから再回答します。

12. エラー時にどこを見るか

  • Spring Bootが起動しない:Eclipse Consoleの末尾の例外、Javaバージョン、依存解決、ポート8080。
  • MySQLに接続できない:MySQLサービスの起動、接続先URL、ユーザー、パスワード、training_final_db の存在。
  • Table '...products' doesn't exist:選択DBが違うか、schema.sql を未実行。
  • POSTで400:JSONの括弧・引用符・Content-Typeと入力値。
  • 更新しても在庫が変わらない:UPDATEの更新件数、コミット、参照しているDB。
  • テストが失敗する:エラーメッセージと「期待値/実際値」を読み、最初の失敗から直す。

この節の独学チェック:12. エラー時にどこを見るか

確認問題: 起動は成功してHTTP 500が返る場合、どこを調べますか。

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

ヒント1

起動成功はHTTP処理が成功する保証ではありません。

ヒント2

HTTP 500時刻のサーバーログを探します。

ヒント3

Service、Repository、接続先DBの順に原因を絞ります。

模範解答と理由

アプリの例外ログ、ServiceやRepositoryの処理、DB接続・SQLなどを確認します。

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

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

  1. 1点: アプリの例外ログを調べる。
  2. 1点: Service・RepositoryおよびDB接続・SQLを調べる。

満点の正答例: アプリの例外ログ、ServiceやRepositoryの処理、DB接続・SQLなどを確認します。

部分点の判定: 部分正答例:「アプリの例外ログを調べる」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「アプリの例外ログを調べる」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

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

13. 経験者向け発展課題

同時注文の負荷試験、二重送信防止用の注文識別子、トランザクション境界、DBのデッドロック、ロック待ち時間、バリデーション共通化、ログの相関IDについて検討してください。これらは基本課題の合否とは別に評価します。

この節の独学チェック:13. 経験者向け発展課題

確認問題: 発展課題で同時注文を扱うなら、何を追加検討しますか。

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

ヒント1

二つの注文が同時に在庫を更新する場面です。

ヒント2

単に在庫数を読んでから更新する間に競合しませんか。

ヒント3

条件付き更新やロックと競合テストの必要性を考えます。

模範解答と理由

DBの排他制御、在庫の条件付き更新、競合時の結果とテストを検討します。

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

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

  1. 1点: 排他制御または条件付き在庫更新を検討する。
  2. 1点: 競合時の応答と同時実行テストを検討する。

満点の正答例: DBの排他制御、在庫の条件付き更新、競合時の結果とテストを検討します。

部分点の判定: 部分正答例:「排他制御または条件付き在庫更新を検討する」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「排他制御または条件付き在庫更新を検討する」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

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

14. 提出前チェック

重要: 指導者用完成例も、実際にMaven・MySQL・Windowsで検証するまでは「動作保証済み」ではありません。未検証を合格扱いしません。

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

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

実行する場所と順序

examples/10_final_project/starter/product-web を元とは別の作業用フォルダーにコピーしてからEclipseに取り込みます。

DBは第05章と別の training_final_db を作成します。

成功・失敗の判断

初期アプリは未完成です。最初はGETの商品一覧を確認し、各マイルストーン後に該当するAPIだけを受け入れテストします。

途中で止まったとき

初期段階で注文APIのテストが失敗するのは仕様どおりです。DBの接続エラーを調べる前にメモリーモードで起動できるか確認します。

作業記録の書き方

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

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

独学用ステップ演習

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

この節の独学チェック:14. 提出前チェック

確認問題: 提出前に必ず確かめるべき3点は何ですか。

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

ヒント1

納品する機能一覧を確認してください。

ヒント2

正常な注文と拒否すべき注文を両方試します。

ヒント3

コード差分・テスト結果・報告書の記載に食い違いがないか見ます。

模範解答と理由

仕様で求める機能、正常系と異常系のテスト結果、報告書と変更ファイルの整合性です。

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

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

  1. 1点: 仕様上必要な機能が実装されている。
  2. 1点: 正常系と異常系のテスト結果を確認する。
  3. 1点: 報告書と変更ファイルに整合性がある。

満点の正答例: 仕様で求める機能、正常系と異常系のテスト結果、報告書と変更ファイルの整合性です。

部分点の判定: 部分正答例:「仕様上必要な機能が実装されている」。この記述だけなら1点で、残る正答要素は未達です。

誤答・採点ミスの例: 不十分な解答例:「仕様上必要な機能が実装されている」。他の必須要素を欠いたまま満点と判定するのは誤りです。

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

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