目次
1. 詳細設計の目的と位置づけ
詳細設計は、基本設計(外部設計)で決めた「何を作るか」を、実装者が迷わず「どう作るか」に落とし込む工程です。
| 工程 | 主な問い | 主な読み手 |
|---|---|---|
| 要件定義 | 何を実現したいか | 発注者・業務担当 |
| 基本設計 | システムとして何を提供するか(画面・帳票・IF・データ) | 発注者・設計者 |
| 詳細設計 | 内部でどう実現するか(モジュール・処理・データ構造) | 実装者・テスト担当・保守担当 |
| 実装 | コードとして書く | 開発者 |
ゴール
- 実装者が設計者に質問しなくても実装できる
- テスト担当が単体テストの観点・ケースを導出できる
- 保守担当が後から「なぜこうなっているか」を追える
2. 基本原則
2.1 「書くべきこと」と「書かないこと」を区別する
- 書く: 判断が必要なこと、複数の選択肢から選んだ理由、チーム内で統一すべきルール、外部との約束(IF・データ形式)
- 書かない: コードを見れば自明なこと、言語・フレームワークの一般知識、実装者の裁量に任せてよい細部
- 詳細設計書は「コードの日本語訳」ではない。擬似コードを全行書くような設計書は、保守されずに陳腐化する
2.2 粒度を揃える
- 同じ設計書内で、ある機能はクラス図レベル、別の機能は1行ずつの擬似コード、という状態を避ける
- プロジェクト開始時に「どのレベルまで書くか」をサンプル1機能で合意してから横展開する
2.3 トレーサビリティを確保する
- 要件ID → 基本設計ID → 詳細設計ID → テストケースID を相互に追えるようにする
- 設計項目には一意のIDを振る(例:
DD-ORD-001)
2.4 Why(設計判断の理由)を残す
- 「何をしたか」はコードに残るが、「なぜそうしたか」はコードに残らない
- 採用しなかった案と不採用理由も記録する(ADR: Architecture Decision Record の形式が有効)
2.5 変更に強い構造にする
- 1つの仕様変更で複数の設計書を修正する必要がある状態を避ける
- 共通定義(コード値、メッセージ、エラーコード、定数)は1か所に集約し、各設計書からは参照する
3. 詳細設計で扱う主な項目
3.1 モジュール構成・責務分割
- レイヤー構成(例: Presentation / Application / Domain / Infrastructure)と依存方向
- パッケージ / モジュール / クラスの一覧と、それぞれの責務(1〜2文で言えること)
- 依存関係図(循環依存がないこと)
チェックポイント
- 1つのモジュールが複数の理由で変更されないか(単一責任の原則)
- 上位レイヤーが下位レイヤーの具象に直接依存していないか(依存性逆転)
- 外部サービス・DB・ファイルなどの I/O 境界が明確か
3.2 クラス / 関数設計
- 公開インターフェース(シグネチャ、引数・戻り値の型、例外)
- 事前条件・事後条件・不変条件
- 状態を持つクラスは状態遷移図を書く
関数名: calculateOrderTotal
入力 : order: Order(明細1件以上)
出力 : Money(税込合計、円単位・端数切り捨て)
例外 : InvalidOrderException(明細0件、数量0以下)
前提 : 単価・税率はマスタから取得済み
備考 : 消費税は明細ごとではなく合計に対して計算する(端数差異回避のため)
3.3 処理フロー
- 正常系だけでなく、異常系・境界条件を必ず書く
- 表現手段は目的で使い分ける
| 表現手段 | 向いている対象 |
|---|---|
| シーケンス図 | 複数コンポーネント間のやりとり、外部API連携 |
| アクティビティ図 / フローチャート | 分岐の多い業務ロジック |
| 状態遷移図・状態遷移表 | ステータスを持つエンティティ(注文、申請など) |
| デシジョンテーブル | 条件の組み合わせで結果が決まるロジック |
| 擬似コード | アルゴリズムが本質的に重要な箇所のみ |
デシジョンテーブルの例
| 条件 / ルール | R1 | R2 | R3 | R4 |
|---|---|---|---|---|
| 会員である | Y | Y | N | N |
| 購入金額 ≥ 5,000円 | Y | N | Y | N |
| 送料 | 無料 | 無料 | 無料 | 500円 |
条件の組み合わせ漏れが一目で分かり、そのままテストケースになる。
3.4 データ設計
- テーブル定義(カラム、型、NULL可否、デフォルト値、制約)
- インデックス設計と、その根拠となるクエリ
- 正規化の方針と、意図的に非正規化した箇所の理由
- 論理削除 / 物理削除の方針
- 主キーの採番方式(連番、UUID、ULID など)
- 文字コード、照合順序、タイムゾーンの扱い
- データ量の見積もりと増加ペース
3.5 インターフェース設計
- API: エンドポイント、メソッド、リクエスト / レスポンスのスキーマ、ステータスコード、エラー形式
- 可能な限り OpenAPI / JSON Schema / Protocol Buffers など機械可読な形式 で定義し、コード生成・テストに活用する
- バージョニング方針、後方互換性のルール
- ファイル連携: フォーマット、文字コード、改行コード、ヘッダ有無、ファイル名規則、配置タイミング
3.6 エラーハンドリング
- エラーの分類(業務エラー / システムエラー / 外部要因エラー)と、それぞれの扱い
- エラーコード体系と一覧
- どの層で捕捉し、どの層で変換し、どこでログ出力するか
- ユーザーに見せるメッセージと内部ログの内容を分ける
- リトライの対象・回数・間隔(指数バックオフ)・冪等性の担保方法
3.7 トランザクション・整合性
- トランザクション境界(どこからどこまでを1単位にするか)
- 分離レベル、排他制御方式(楽観ロック / 悲観ロック)
- 分散処理時の整合性確保(Saga、Outbox パターン、補償処理)
- 二重送信・二重実行の防止策
3.8 非機能要件の具体化
| 観点 | 詳細設計で決めること |
|---|---|
| 性能 | 処理ごとの目標応答時間、N+1問題の回避、キャッシュ方針、ページング |
| セキュリティ | 認証・認可のチェック箇所、入力検証、出力エスケープ、機密情報のマスキング・暗号化 |
| ログ | 出力項目、ログレベルの基準、相関ID、個人情報を出さないルール |
| 監視 | メトリクス、アラート条件、ヘルスチェック |
| 運用 | バッチのスケジュール・再実行手順、設定値の外部化 |
3.9 テスト観点
- 単体テストで確認すべき観点を設計書に併記する
- 境界値(最小・最大・その前後)、同値クラス、異常系、状態遷移の網羅
- テスト容易性を設計段階で考慮する(依存の注入、時刻・乱数の差し替え)
4. 設計書の書き方
4.1 構成の型を決める
各設計書は共通テンプレートで書く。例:
- 概要(目的、対象範囲、関連する要件・基本設計ID)
- 前提・制約
- 構成(図)
- 詳細(インターフェース、処理、データ)
- 異常系・エラー処理
- 非機能に関する考慮
- 設計判断の記録(採用案・不採用案と理由)
- 未決事項・課題
- 変更履歴
4.2 文章のルール
- 1文1義。主語と述語を明確にする
- 曖昧語を使わない: 「適切に」「必要に応じて」「など」「基本的に」「速やかに」
- 数値は単位を付けて具体的に書く(「大量のデータ」→「最大100万件」)
- 用語集を作り、同じ概念に複数の呼び名を使わない(「顧客」と「ユーザー」と「会員」の混在など)
- 「〜する」(確定)と「〜を検討する」(未確定)を明確に区別する
4.3 図を活用する
- 文章で3段落以上かかる関係性は、図にする
- 図はテキストベース(Mermaid、PlantUML)で書くと、差分管理・レビューがしやすい
sequenceDiagram participant C as Client participant A as OrderAPI participant S as StockService participant D as DB C->>A: POST /orders A->>S: 在庫引当 alt 在庫あり S-->>A: OK A->>D: 注文登録 A-->>C: 201 Created else 在庫不足 S-->>A: NG A-->>C: 409 Conflict end
4.4 Docs as Code
- 設計書を Markdown / AsciiDoc などでリポジトリに置き、コードと同じブランチ・PRで管理する
- 設計変更とコード変更を同じPRに含め、レビューで乖離を防ぐ
- Excel / Word 方眼紙形式は差分が追えず、検索・再利用もしにくいため、新規には避けるのが望ましい
5. レビューの進め方
5.1 レビューのタイミング
- 全部書き終えてからではなく、構成・方針が固まった段階で一度レビューする(手戻りの最小化)
- 共通部品・アーキテクチャに関わる部分は先行してレビューする
5.2 レビュー観点チェックリスト
- 基本設計の内容がすべて反映されているか(漏れ)
- 基本設計にない仕様が勝手に追加されていないか(逸脱)
- 異常系・境界条件が定義されているか
- 曖昧な表現がなく、実装者が一意に解釈できるか
- 他の設計書と矛盾していないか(コード値、IF、用語)
- 性能・セキュリティ・運用の考慮があるか
- テスト可能な粒度で書かれているか
- 設計判断の理由が残っているか
- 未決事項が明示され、担当者・期限があるか
5.3 レビューの運営
- 指摘は「事実(どこが)」「影響(何が困るか)」「提案(どうしたら良いか)」で伝える
- 指摘の重要度を分類する(必須修正 / 推奨 / 質問・軽微)
- 指摘傾向を蓄積し、チェックリストやテンプレートに反映して再発を防ぐ
6. よくある失敗と対策
| 失敗 | 結果 | 対策 |
|---|---|---|
| 正常系しか書いていない | 実装者ごとに異常系の挙動がバラバラ | テンプレートに異常系の欄を必須で設ける |
| コードを1行ずつ日本語で書く | 工数過大、実装後に誰も更新しない | 判断・約束事に絞って書く |
| 逆に粗すぎる | 実装者が都度質問、解釈の差でバグ | サンプル1機能で粒度を合意する |
| 設計理由が残っていない | 改修時に意図が分からず壊す | 設計判断の記録欄を設ける |
| 実装後に設計書を更新しない | 設計書が信用されなくなる | Docs as Code、PRで設計書の更新を必須化 |
| 共通定義が各所にコピーされている | 変更漏れ・不整合 | 共通定義書に集約して参照する |
| 未決事項が埋もれている | 実装直前に発覚して手戻り | 未決事項一覧を設け、定例で消化状況を確認 |
| 非機能要件を後回しにする | 結合・性能試験で大きな手戻り | 詳細設計時点で具体的な数値目標を決める |
7. アジャイル開発における詳細設計
- 「詳細設計書」という独立した成果物を重厚に作るのではなく、必要な部分を必要なタイミングで、軽量に書く
- 残すべきもの
- アーキテクチャの全体像と主要な設計判断(ADR)
- 外部との契約(APIスキーマ、データモデル)
- 複雑なビジネスルール(デシジョンテーブル、状態遷移)
- コードとテストが仕様の役割を担う部分は、文書を書かずにテストコードを「動く仕様」として扱う
- スプリントの中で「設計 → 実装 → 振り返りで設計を更新」のサイクルを回す
8. まとめ:詳細設計の10か条
- 読み手(実装者・テスト担当・保守担当)を意識して書く
- 判断が必要なことと約束事に絞り、自明なことは書かない
- 粒度をプロジェクト内で揃える
- 異常系・境界条件を必ず書く
- 「なぜそうしたか」を残す
- 曖昧語を排除し、数値と単位で書く
- 共通定義は1か所に集約する
- 図はテキストベースで、目的に合った種類を選ぶ
- 設計書はコードと一緒に管理し、常に最新に保つ
- 早い段階で小さくレビューし、指摘をチェックリストに還元する