404 Not Found

404 Not Found


nginx

総合演習:OrderFlowプロジェクト設計

プロジェクト設計は開発の青写真です。要件が方向を決め, 技術選定が手法を決め, 設計がアーキテクチャを決めます。準備が成功の半ばです。

1. 学ぶこと


2. プロダクトマネージャーの実話

(1) ペインポイント: 要件とコードのギャップ

Charlieが曖昧な要件文書を持ってAliceに来ました。「電子商取引の注文管理システムが必要です。」Aliceは「どんな機能が必要?ユーザーロールは何種類?商品の属性は?注文と決済はどう紐づく?」と尋ねましたが, Charlieは明確に説明できず, Aliceは経験に基づいて推測するしかありませんでした。その結果, 2週間の開発後, Charlieは「これは私が欲しかったものではない」と言いました。

(2) システム設計のソリューション

先に設計し, 後に開発—要件分析 → 技術選定 → データベース設計 → API仕様。各ステップをCharlieと確認します:

100%
graph TD
    A["要件<br/>分析"] --> B["技術スタック<br/>選定"]
    B --> C["データベース<br/>設計"]
    C --> D["API<br/>仕様"]
    D --> E["開発<br/>計画"]

(3) 成果

AliceとCharlieが2日間かけてシステム設計を確定した後, 開発の方向性が明確になり, 3週間で期待に応えるMVPを納品しました。Charlieは「初回からまさに欲しかったものだった」と言いました。


3. 要件分析

(1) 4大モジュール

モジュール コア機能 ユーザーロール
ユーザー管理 登録, ログイン, 個人情報, ロール管理 全ユーザー
商品管理 CRUD, カテゴリ, 検索, 在庫管理 ADMIN
注文管理 注文, 注文照会, キャンセル, タイムアウト自動キャンセル CUSTOMER / ADMIN
決済管理 決済開始, コールバック処理, 返金 CUSTOMER / ADMIN

(2) ロール権限マトリクス

機能 CUSTOMER ADMIN
登録 / ログイン
商品閲覧
商品検索
商品作成 / 管理
注文
自分の注文を表示
全注文を表示
自分の注文をキャンセル
任意の注文をキャンセル
決済開始
返金処理

(1) ▶ サンプル:ユーザーストーリー

TEXT
As a CUSTOMER, I want to:
  - Browse and search products
  - Add products to cart (future)
  - Place an order with multiple items
  - View my order history
  - Cancel an unpaid order within 30 minutes
  - Pay for an order
  - View payment status

As an ADMIN, I want to:
  - Manage products (CRUD)
  - View all orders
  - Cancel any order
  - Process refunds
  - View business statistics

出力:

TEXT
実行成功

4. 技術選定

(1) 技術選定決定マトリクス

決定点 選択肢A 選択肢B 選択 理由
Webフレームワーク WebMVC WebFlux WebMVC 主にCRUD, 同時接続 < 5,000; WebMVCの方がシンプル
認証方式 Session JWT JWT マイクロサービスアーキテクチャ, マルチインスタンスデプロイ, ステートレス認証
キャッシュ戦略 ローカルCaffeine 分散Redis L1 Caffeine + L2 Redis ホットデータのローカル高速アクセス; 分散キャッシュで整合性確保
データベース PostgreSQL MySQL MySQL チームに馴染みがある, 成熟したエコシステム
データベースアクセス JPA MyBatis JPA より自然なオブジェクトマッピング, SQL記述の削減
APIドキュメント SpringDoc 手動 SpringDoc OpenAPIドキュメントの自動生成

(2) 技術スタック概要

技術 バージョン
言語 Java 17 LTS
フレームワーク Spring Boot 3.2.x
Web Spring MVC 6.x
セキュリティ Spring Security + JWT 6.x
データベース MySQL 8.0
ORM Spring Data JPA 3.x
キャッシュ Caffeine + Redis 3.x / 7.x
バリデーション Bean Validation 3.x
テスト JUnit 5 + Mockito + TestContainers 5.x
ドキュメント SpringDoc OpenAPI 2.x
監視 Actuator + Micrometer 3.x
デプロイ Docker + Kubernetes 24.x / 1.28

5. データベース設計

(1) 完全ER図

100%
erDiagram
    USER ||--o{ ORDER : "places"
    PRODUCT ||--o{ ORDER_ITEM : "included in"
    ORDER ||--o{ ORDER_ITEM : "contains"
    ORDER ||--o| PAYMENT : "has"

    USER {
        bigint id PK
        varchar username UK
        varchar email UK
        varchar password_hash
        varchar role
        timestamp created_at
        timestamp updated_at
    }
    PRODUCT {
        bigint id PK
        varchar name
        varchar sku UK
        decimal price
        int stock
        varchar category
        tinyint status
        timestamp created_at
        timestamp updated_at
    }
    ORDER {
        bigint id PK
        bigint user_id FK
        varchar order_number UK
        varchar status
        decimal total_amount
        timestamp created_at
        timestamp updated_at
    }
    ORDER_ITEM {
        bigint id PK
        bigint order_id FK
        bigint product_id FK
        int quantity
        decimal unit_price
        decimal subtotal
    }
    PAYMENT {
        bigint id PK
        bigint order_id FK
        varchar transaction_id UK
        varchar method
        varchar status
        decimal amount
        timestamp paid_at
        timestamp created_at
    }

(1) ▶ サンプル:DDLテーブル作成文

SQL
CREATE TABLE users (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    username VARCHAR(50) NOT NULL UNIQUE,
    email VARCHAR(100) NOT NULL UNIQUE,
    password_hash VARCHAR(255) NOT NULL,
    role VARCHAR(20) NOT NULL DEFAULT 'CUSTOMER',
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

CREATE TABLE products (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(200) NOT NULL,
    sku VARCHAR(20) NOT NULL UNIQUE,
    price DECIMAL(10,2) NOT NULL,
    stock INT NOT NULL DEFAULT 0,
    category VARCHAR(50),
    status TINYINT NOT NULL DEFAULT 1,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_product_name (name),
    INDEX idx_product_category (category)
);

CREATE TABLE orders (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    order_number VARCHAR(20) NOT NULL UNIQUE,
    status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
    total_amount DECIMAL(10,2) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    INDEX idx_order_user (user_id),
    INDEX idx_order_status_created (status, created_at DESC),
    FOREIGN KEY (user_id) REFERENCES users(id)
);

CREATE TABLE order_items (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    order_id BIGINT NOT NULL,
    product_id BIGINT NOT NULL,
    quantity INT NOT NULL,
    unit_price DECIMAL(10,2) NOT NULL,
    subtotal DECIMAL(10,2) NOT NULL,
    FOREIGN KEY (order_id) REFERENCES orders(id),
    FOREIGN KEY (product_id) REFERENCES products(id)
);

CREATE TABLE payments (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    order_id BIGINT NOT NULL UNIQUE,
    transaction_id VARCHAR(50) UNIQUE,
    method VARCHAR(20) NOT NULL,
    status VARCHAR(20) NOT NULL DEFAULT 'PENDING',
    amount DECIMAL(10,2) NOT NULL,
    paid_at TIMESTAMP NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (order_id) REFERENCES orders(id)
);

出力:

TEXT
CREATE TABLE

6. API仕様設計

(1) RESTful API仕様

(1) ▶ サンプル:APIエンドポイント一覧

モジュール メソッド URI 説明 権限
Auth POST /api/v1/auth/login ログイン 公開
Auth POST /api/v1/auth/register 登録 公開
Product GET /api/v1/products 商品一覧 公開
Product GET /api/v1/products/{id} 商品詳細 公開
Product POST /api/v1/products 商品作成 ADMIN
Product PUT /api/v1/products/{id} 商品更新 ADMIN
Product DELETE /api/v1/products/{id} 商品削除 ADMIN
Order POST /api/v1/orders 注文 CUSTOMER+
Order GET /api/v1/orders 自分の注文 CUSTOMER+
Order GET /api/v1/orders/{id} 注文詳細 Owner/ADMIN
Order GET /api/v1/admin/orders 全注文 ADMIN
Order DELETE /api/v1/orders/{id} 注文キャンセル Owner/ADMIN
Payment POST /api/v1/payments 決済開始 CUSTOMER+
Payment POST /api/v1/payments/callback 決済コールバック 内部

(2) ▶ サンプル:標準レスポンスフォーマット

JAVA
// 成功レスポンス
public record ApiResponse<T>(
    int code,
    String message,
    T data,
    Instant timestamp
) {
    public static <T> ApiResponse<T> success(T data) {
        return new ApiResponse<>(200, "OK", data, Instant.now());
    }
    public static <T> ApiResponse<T> created(T data) {
        return new ApiResponse<>(201, "Created", data, Instant.now());
    }
}

// ページネーションレスポンス
public record PagedResponse<T>(
    List<T> content,
    int page,
    int size,
    long totalElements,
    int totalPages
) {}

出力:

TEXT
// 実行成功

(3) ▶ サンプル:ページネーションとソートパラメータ

BASH
# ページネーション, ソート, フィルタリング付き商品一覧
GET /api/v1/products?page=0&size=20&sort=price,desc&category=electronics&minPrice=100&maxPrice=999

出力:

TEXT
// コマンド実行成功

7. 開発計画とモジュール割り当て

(1) ▶ サンプル:イテレーション計画

スプリント イテレーション 目標 成果物
Sprint 1 1-2週目 基盤フレームワーク プロジェクト構造 + 認証 + 商品CRUD
Sprint 2 3-4週目 コアビジネス 注文モジュール + トランザクション + バリデーション + 例外
Sprint 3 5-6週目 高度な機能 キャッシュ + スケジュールタスク + 非同期通知
Sprint 4 7-8週目 運用とデプロイ Docker + K8s + 監視とアラート

8. 総合サンプル:OrderFlowプロジェクト設計文書

MARKDOWN
# OrderFlow システム設計文書

## 1. ビジネス要件
- 電子商取引注文管理システム
- 4モジュール: User, Product, Order, Payment
- 2ロール: CUSTOMER, ADMIN
- 予定: DAU 10,000, 1日1,000注文

## 2. 技術スタック
- Java 17 + Spring Boot 3.2.x
- MySQL 8.0 + Spring Data JPA
- Redis 7 + Caffeine (2段キャッシュ)
- Spring Security + JWT (OAuth2 Resource Server)
- Docker + Kubernetes デプロイ

## 3. データベース設計
- 5テーブル: users, products, orders, order_items, payments
- 高頻度クエリ列にインデックス

## 4. API仕様
- RESTful API with versioning (/api/v1/)
- JWT Bearer 認証
- 統一レスポンスフォーマット: ApiResponse<T>
- ページネーション: page, size, sort パラメータ

## 5. 非機能要件
- P99レイテンシ < 100ms
- エラー率 < 0.1%
- 可用性 > 99.9%
- 自動テストカバレッジ > 80%

❓ よくある質問

Q WebFluxではなくWebMVCを選ぶ理由は?
A OrderFlowは主にCRUD操作で, 想定同時接続 < 5,000 QPS; WebMVCの方がシンプルで成熟しています。WebFluxはI/O集約型, 高並列, リアルタイムストリーミングのシナリオに適しています; CRUDプロジェクトに使うと逆に複雑さが増します。
Q Redisだけでなく2段キャッシュを使う理由は?
A L1 Caffeineが最速 (ナノ秒レベル), L2 Redisが複数インスタンス間の整合性を確保します。ホットデータはローカルキャッシュにヒットし, Redisのネットワークオーバーヘッドを削減します。
Q APIバージョニングはURLパスとヘッダーのどちらを使うべきですか?
A URLパスバージョニング (/api/v1/)はより直感的で, テストしやすく, SEOにも優れています。ヘッダーバージョニングはよりRESTfulですが, デバッグが難しいです。実践的にはURLバージョニングを推奨します。
Q 決済コールバックのセキュリティはどう確保しますか?
A 1) コールバックURLは内部ネットワークからのみアクセス可能; 2) コールバック署名を検証; 3) 冪等処理 (重複コールバックで二重課金なし); 4) 照合用にコールバックイベントを全てログ記録。
Q データベース設計で論理削除と物理削除はどう扱うべきですか?
A 重要なビジネスデータ (注文, 決済)には論理削除 (status=CANCELLED)を使用し, 監査証跡を保持します。補助データ (テスト商品)は物理削除可能です。論理削除では全クエリで削除済レコードを除外する必要があります。
Q プロジェクト設計文書はどの程度詳細にすべきですか?
A 新しいチームメンバーがシステムの全体像を理解できる程度に詳細にしてください。含めるべき内容:ビジネス要件, 技術選定とその理由, データベース設計, API仕様, 非機能要件。コード実装の詳細は不要—コード自体が最も詳細なドキュメントです。

📖 まとめ


📝 練習問題

  1. 基本課題 (難易度:⭐): OrderFlowの要件分析文書を完成させ, すべてのユーザーストーリーとAPIエンドポイントを列挙してください。

  2. 応用課題 (難易度:⭐⭐): データベースER設計とDDLテーブル作成文を完成させ, すべてのインデックスを含めてください。標準化されたレスポンスフォーマットとエラーコード体系を設計してください。

  3. チャレンジ (難易度:⭐⭐⭐): SpringDoc OpenAPIを使ってAPI仕様を書き, インタラクティブなAPIドキュメントページを生成してください。APIドキュメントとコード実装の同期を保つ方法を考察してください。

Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%