- 技術 💻
- 設計
詳細設計書の書き方|基本設計との違いと記入例
詳細設計書とは、基本設計で決めた「利用者から見たシステムの動き」を、プログラムとしてどう作るか――クラスやモジュールの構成、処理の手順、データベースへのアクセス、エラーの扱い――を、開発者に向けて書いた設計書です。「内部設計書」とも呼ばれます。
基本設計書がお客様と合意するための文書なのに対し、詳細設計書は開発者が迷わずに実装・テストできるようにするための文書です。この記事では、基本設計との違い、作成する成果物と目次のテンプレート、各項目の記入例、どこまで細かく書くかの目安、レビューのチェックリスト、そしてAIに実装を任せる場面が増えた今の書き方までを解説します。
基本設計と詳細設計の違い
| 基本設計(外部設計) | 詳細設計(内部設計) | |
|---|---|---|
| 答える問い | 外から見てどう動くか | 内部でどう作るか |
| 主な読み手 | お客様・開発チーム | プログラマー・テスト担当 |
| 承認する人 | お客様 | 開発チーム(設計のリーダーなど) |
| 代表的な内容 | 画面・帳票・テーブル・外部連携・非機能要件 | クラス・モジュール構成、処理手順、SQL、例外処理、ログ |
| 使う言葉 | 業務の言葉 | システムの言葉(クラス名、メソッド名、テーブル名) |
| 次の工程 | 詳細設計 | 実装(プログラミング)・単体テスト |
基本設計は「何が起きるか」、詳細設計は「それをどう実現するか」です。たとえば、基本設計の「注文確定時に在庫を引き当てる。在庫が足りなければ注文できない」を、詳細設計では「どのクラスが、どの順番で、どのSQLを使い、在庫不足の例外をどう扱うか」まで具体化します。
詳細設計で作成する成果物
| 成果物 | 内容 | 必要性の目安 |
|---|---|---|
| ソフトウェア構成図(レイヤー構成) | 画面・業務処理・データアクセスなどの層と、その役割 | ほぼ必須 |
| クラス図・モジュール一覧 | クラス(モジュール)の一覧と責務、関係 | ほぼ必須 |
| 処理詳細(機能ごと) | 入力・処理・出力、処理の手順、分岐 | 必須 |
| シーケンス図 | 複数のクラスや外部システムの呼び出しの順番 | 処理が複雑な機能 |
| SQL定義・データアクセス | 使用するSQL、トランザクションの範囲、ロック | DBを使う機能 |
| 例外・エラー処理設計 | 例外の種類、処理の方針、メッセージとの対応 | ほぼ必須 |
| ログ設計 | 出力する場面、ログレベル、出力項目 | ほぼ必須 |
| 共通処理・ユーティリティ | 複数の機能で共通に使う処理 | 中〜大規模 |
| 単体テスト観点 | 各処理で確認すべき条件(境界値など) | プロジェクトの方針による |
基本設計書と同じく、すべてを作ることが目的ではありません。「実装者によって作り方がばらつくと困るところ」「後から変えにくいところ」を優先して書きます。
目次のテンプレート
1. はじめに
1.1 本書の目的・対象範囲
1.2 参照する基本設計書(版番号)
1.3 用語・命名規約
2. ソフトウェア構成
2.1 レイヤー構成と各層の責務
2.2 パッケージ(ディレクトリ)構成
2.3 共通処理の一覧
3. 機能ごとの詳細設計
3.x 機能名(基本設計の機能IDと対応)
- 処理概要
- クラス・メソッド構成
- 処理詳細(入力・処理・出力)
- シーケンス図
- SQL・トランザクション
- 例外処理
4. 例外・エラー処理の共通方針
5. ログ設計
6. 変更履歴
「参照する基本設計書の版番号」を書いておくと、基本設計が変わったときに、どの詳細設計を見直せばよいかがわかります。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「詳細設計書の書き方|基本設計との違いと記入例」
各項目の書き方と記入例
基本設計書の記事と同じ「会員が商品を注文するECサイト」の、注文確定(機能ID:F-05)を例にします。
ソフトウェア構成(レイヤー構成)
| 層 | 責務 | 例 |
|---|---|---|
| プレゼンテーション層 | リクエストの受け取り、入力チェック、レスポンスの作成 | OrderController |
| アプリケーション層(サービス) | 業務処理の手順、トランザクションの管理 | OrderService |
| ドメイン層 | 業務のルール(在庫が足りるか、金額の計算など) | Order、Stock |
| データアクセス層 | データベースの読み書き | OrderRepository、StockRepository |
| 外部連携 | 決済サービスなど外部システムの呼び出し | PaymentClient |
どの層に何を書くかを最初に決めておくと、実装者ごとに処理の置き場所がばらつくのを防げます。
クラス・メソッド構成
| クラス | メソッド | 責務 |
|---|---|---|
| OrderController | confirm(request) | 入力を受け取り、OrderServiceを呼び出し、結果を返す |
| OrderService | confirmOrder(memberId, cartId) | 注文確定の手順を実行し、トランザクションを管理する |
| StockService | reserve(items) | 在庫を引き当てる。不足時は OutOfStockException を投げる |
| PaymentClient | charge(orderId, amount) | 決済サービスに決済を依頼する |
| OrderRepository | save(order) | 注文と注文明細を登録する |
処理詳細(入力・処理・出力)
| 項目 | 内容 |
|---|---|
| 機能 | F-05 注文確定(OrderService.confirmOrder) |
| 入力 | 会員ID、カートID |
| 出力 | 注文番号(正常時)/例外(異常時) |
| 前提条件 | 会員がログインしている。カートに1件以上の商品がある |
処理の手順
- カートIDから、カートの商品と数量を取得する(CartRepository.findById)
- カートが存在しない、または商品が0件の場合は
EmptyCartExceptionを投げる
- カートが存在しない、または商品が0件の場合は
- 各商品の現在の販売価格を取得し、合計金額を計算する
- 販売終了の商品が含まれる場合は
ProductUnavailableExceptionを投げる
- 販売終了の商品が含まれる場合は
- トランザクションを開始する
- 在庫を引き当てる(StockService.reserve)
- 在庫が不足する商品がある場合は
OutOfStockExceptionを投げ、トランザクションをロールバックする
- 在庫が不足する商品がある場合は
- 注文を「決済待ち」状態で登録する(OrderRepository.save)
- 注文明細には、手順2で取得した販売価格を保存する
- トランザクションをコミットする
- 決済を依頼する(PaymentClient.charge)。注文番号を冪等キーとして送る
- 成功:注文を「注文確定」状態に更新し、確認メールの送信を登録する
- 失敗:注文を「決済エラー」状態に更新し、在庫の引き当てを戻す
- 注文番号を返す
なぜトランザクションの外で決済を呼ぶのか、のように、判断の理由も1行添えておくと、後から読む人が安心して変更できます(この例では、外部の呼び出しの間、データベースのロックを持ち続けないため)。
シーケンス図
sequenceDiagram
participant C as OrderController
participant S as OrderService
participant St as StockService
participant R as OrderRepository
participant P as PaymentClient
C->>S: confirmOrder(memberId, cartId)
S->>St: reserve(items)
St-->>S: OK
S->>R: save(order)
S->>P: charge(orderId, amount)
P-->>S: 決済結果
S-->>C: orderId
SQL・トランザクション
| 項目 | 内容 |
|---|---|
| トランザクション範囲 | 手順3〜6(在庫の引き当てと注文の登録) |
| 分離レベル | データベースの既定(READ COMMITTED) |
| ロック | 在庫の行を SELECT ... FOR UPDATE でロックしてから更新する |
| デッドロック対策 | 複数商品の在庫をロックするときは、商品IDの昇順でロックする |
-- 在庫の引き当て(商品ごと、商品IDの昇順で実行)
SELECT quantity FROM stocks WHERE product_id = ? FOR UPDATE;
UPDATE stocks SET quantity = quantity - ? WHERE product_id = ?;
「どの順番でロックするか」「どこまでを1つのトランザクションにするか」は、実装者に任せると、同時に注文が集中したときの不具合(在庫のマイナス、デッドロック)の原因になります。詳細設計で決めておくべき代表的な項目です。
例外処理
| 例外 | 発生条件 | 処理 | 利用者へのメッセージ | ログ |
|---|---|---|---|---|
| EmptyCartException | カートが空 | 処理を中断 | E-101「カートに商品がありません」 | INFO |
| OutOfStockException | 在庫不足 | ロールバックして中断 | E-102「在庫が不足している商品があります」 | INFO |
| PaymentException | 決済サービスのエラー | 注文を決済エラーにし、在庫を戻す | E-103「決済に失敗しました」 | WARN |
| DataAccessException | データベースの障害 | ロールバックして中断 | E-999「システムエラーが発生しました」 | ERROR |
「業務上ありうるエラー(在庫不足)」と「想定外のエラー(DB障害)」を分けて、ログのレベルと利用者へのメッセージを決めます。すべてをERRORにすると、本当の障害が埋もれてしまいます。
ログ設計
| ログレベル | 出力する場面 | 例 |
|---|---|---|
| ERROR | 処理を続けられない、想定外の障害 | DB接続エラー、予期しない例外 |
| WARN | 処理は続けられるが、注意が必要 | 外部APIの再試行、決済の失敗 |
| INFO | 業務上の重要なイベント | 注文確定(注文番号、会員ID、金額) |
| DEBUG | 開発時の調査用 | SQLのパラメータ、処理の分岐 |
ログに出してはいけない情報(パスワード、カード番号、個人情報の全文など)も、ここで明記しておきます。
どこまで細かく書くか:粒度の目安
詳細設計で最も迷うのが細かさです。次の基準で判断します。
- 実装者によって作り方が変わると困るか(ロックの順番、トランザクションの範囲、例外の扱い)→ 書く
- 実装者が自由に決めてよいか(ローカル変数の名前、ループの書き方)→ 書かない
- コードを読めばわかることか → 書かない(コードと設計書が二重管理になる)
| 詳細設計に書く | 詳細設計に書かない(コードに任せる) |
|---|---|
| クラスの責務と、主なメソッドの入力・出力 | すべてのメソッドの1行ずつの処理 |
| トランザクションの範囲、ロックの順番 | SQLの細かな書き方(方針が決まっていれば) |
| 例外の種類と、その扱いの方針 | try-catchの書き方 |
| 判断の理由(なぜその作りにしたか) | ソースコードそのもの |
「プログラムの日本語訳」になっている設計書は、実装したコードと食い違いやすく、保守の手間だけが増えます。コードに書けないこと――判断の理由、全体の構成、処理の順番の約束――を中心に書くのがポイントです。
よくある失敗と対策
| よくある失敗 | 起きること | 対策 |
|---|---|---|
| コードをそのまま日本語にしたような設計書 | コードと食い違い、誰も読まなくなる | 構成・方針・理由を中心に書く |
| 正常時の処理しか書いていない | 異常時の動きが実装者ごとに違う | 手順ごとに「〜の場合は」を書く |
| トランザクションとロックの記述がない | 同時アクセスで在庫がマイナスになる | 範囲・分離レベル・ロックの順番を明記 |
| 基本設計との対応がない | 基本設計の変更が反映されない | 機能IDと参照する版番号を書く |
| 実装後に更新されない | 設計書が実態と違い、信用されない | 変更時に更新するルールをチームで決める |
レビューのチェックリスト
▶ 基本設計との整合
- □ 基本設計の機能・画面・テーブルと、すべて対応しているか
- □ 基本設計に書かれたエラー時の動き・メッセージが、例外処理に反映されているか
▶ 構成と責務
- □ 各クラスの責務が1つに絞られ、層の役割に沿っているか
- □ 同じ処理が複数の場所に重複していないか。共通処理を使えないか
▶ データと同時実行
- □ トランザクションの範囲、ロックの順番が決まっているか
- □ 同時に同じデータを更新したときの動きを考慮しているか
- □ 外部システムの呼び出しで、タイムアウト・再試行・二重実行の防止が決まっているか
▶ 異常系・運用
- □ 各手順の異常時の処理が書かれているか
- □ ログのレベルと出力項目が決まっており、個人情報を出力しないか
- □ 性能(件数が増えたときの処理、N+1問題)を考慮しているか
▶ テストしやすさ
- □ 単体テストで確認すべき条件(境界値、例外の発生条件)が読み取れるか
- □ 現在日時や外部システムなど、テストで差し替えたいものが分離されているか
AIに実装を任せる時代の詳細設計
AIのコーディング支援が普及し、詳細設計書をもとにAIがコードを生成する場面が増えています。このとき、詳細設計書の価値はむしろ高まります。
- AIは、書かれていないことを「それらしく」補って実装します。トランザクションの範囲やロックの順番、例外の扱いが書かれていないと、動くが同時実行に弱いコードが生成されがちです
- 処理の手順、例外の表、判断の理由が明確に書かれているほど、AIが生成するコードの精度が上がり、レビューもしやすくなります
- 詳細設計書を、Markdownで書いてリポジトリに置くと、AIのツールが参照しやすくなり、コードと一緒に変更を管理できます
- 一方で、AIが生成したコードが設計どおりかを確認するのは人の役割です。レビューのチェックリストは、AIのコードの確認にもそのまま使えます
「詳細に書くほど手間がかかる」と考えられがちな詳細設計ですが、AIに正確に指示するための文書と捉えると、書くべきことの優先順位が見えやすくなります。
よくある質問
Q. 詳細設計と内部設計は同じですか? A. ほぼ同じ意味で使われます。システムの内部の作りを設計するため、内部設計とも呼ばれます。会社やプロジェクトによって、プログラム設計と呼ぶこともあります。
Q. アジャイル開発でも詳細設計書は必要ですか? A. 機能ごとに分厚い設計書を作ることは少なくなっていますが、レイヤー構成や例外処理の方針、トランザクションの考え方など、チーム全体で揃えるべき共通の設計は文書にしておく価値があります。
Q. 詳細設計書はExcelで書くべきですか? A. チームやお客様の慣習に合わせます。表が中心ならExcel、文章と図が中心ならWordやMarkdownがよく使われます。コードと一緒に管理したい場合は、Markdownでリポジトリに置く方法もあります。
Q. 詳細設計書は誰が書きますか? A. 実装を担当するプログラマーや、チームの設計担当が書くことが多いです。基本設計を書いたSEがレビューし、基本設計との整合を確認します。
まとめ
- 詳細設計書は、基本設計の内容をプログラムとしてどう作るかを、開発者向けに書いた文書
- 成果物は、構成・処理詳細・SQLとトランザクション・例外処理・ログが中心
- 処理詳細は入力・処理・出力と、手順ごとの異常時の動きを書く
- トランザクションの範囲とロックの順番は、実装者任せにせず設計で決める
- コードを日本語訳しない。構成・方針・判断の理由を中心に書く
- 詳細設計書は、AIに正確に実装させるための指示書にもなる
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「詳細設計書の書き方|基本設計との違いと記入例」
株式会社RJCでは、SI事業を通じて、設計から実装・テストまで一貫してシステムを形にしています。設計書を「伝わる」形で書く力を、仲間と一緒に高め合いながら、成長を楽しんでいます。
株式会社RJC ― SI事業・SES事業・AI駆動開発。未経験からエンジニアに育てるのが得意な会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。