システム開発をしていると、「詳細設計書を作成してください」と言われることがあります。
しかし、いざ詳細設計書を書こうとすると、
- そもそも詳細設計書って何?
- 要件定義書や機能仕様書・基本設計書とは何が違うの?
- 詳細設計書には何を書けばいいの?
- どこまで細かく書く必要があるの?
- プログラムのコードまで書く必要があるの?
と疑問に思うこともあるでしょう。
この記事では、詳細設計書とは何なのか、基本的な役割や主な記載項目、具体的な書き方についてわかりやすく解説します。
詳細設計書とは?
詳細設計書とは、簡単にいうと、基本設計で決めたシステムの構成や機能を、プログラムとして実装できるように、内部の処理や構造まで具体化した文書です。
基本設計では、画面・データ・外部インターフェース・システム構成など、システムとしてどのような形で実現するのかを具体化します。
例えば、基本設計書で次のように書かれていたとします。
ユーザー登録画面から表示名・メールアドレス・パスワードを入力し、登録ボタンを押すとユーザー情報をデータベースに保存する。
このように書かれているだけでは、プログラムをどのように作るのか判断できないことがあります。
この内容を実現するために、詳細設計では、次のような内容を具体化します。
UserControllerでリクエストを受け付けるUserServiceで登録処理を制御する- 入力値の検証後、メールアドレスの重複を確認する
- パスワードを適切な方式でハッシュ化する
UserRepositoryでユーザー情報を保存する- 保存時のエラーや重複が発生した場合の処理を定義する
このように、詳細設計では、基本設計で決めた内容を実現するための内部処理や構造を具体化し、実装する人によって認識が大きく異ならないようにします。
つまり、詳細設計では「システムとしてどのような形にするか」よりも、「その機能をプログラム内部でどのように実現するか」を明確にすることが重要です。
ただし、基本設計と詳細設計の境界には、すべてのプロジェクトに共通する厳密な決まりがあるわけではありません。基本設計の段階で内部処理まで決める場合や、詳細設計と実装を並行して進める場合もあります。
詳細設計書は何のために作る?
詳細設計書を作る大きな目的は、プログラムの内部構造や処理方法について開発者間の認識を合わせ、実装に必要な設計内容を明確にすることです。
例えば、「ユーザー登録機能を実装する」という指示だけでは、人によって実装方法が異なる可能性があります。
ある人は、すべての処理を1つの関数に記述するかもしれません。別の人は、入力チェック・業務処理・データベースアクセスを別々のクラスに分けるかもしれません。また、エラー処理やトランザクションの扱いについても、判断が異なることがあります。
このような認識の違いを残したまま開発を進めると、モジュール間の不整合や、保守しにくいプログラムにつながる可能性があります。
そのため、詳細設計書では主に以下の内容を整理して、開発者間で共有します。
- モジュールやクラスの役割
- 関数・メソッドの入出力
- 処理の順序や条件分岐
- データベースへのアクセス方法
- エラー・例外処理
また、詳細設計書は、実装だけでなく、単体テストの対象や処理条件を考える際の参考資料にもなります。
要件定義書・機能仕様書・基本設計書・詳細設計書の違い
詳細設計書について理解するときは、要件定義書・機能仕様書・基本設計書との違いを知っておくと分かりやすくなります。
それぞれの役割を大まかに分けると、次のようになります。
| 文書 | 主に決めること |
| 要件定義書 | なぜ作るのか、何を実現する必要があるのか |
| 機能仕様書 | システムがどのように振る舞うのか |
| 基本設計書 | 画面・データ・外部インターフェースなどをどのような形にするのか |
| 詳細設計書 | プログラム内部をどのように構成・実装するのか |
あわせて読みたい
要件定義書・機能仕様書・基本設計書・詳細設計書の違いについては下記の記事で詳しく説明しています。興味のある方は下記のリンクからぜひチェックをしてみてください。 続きを見る
要件定義書・機能仕様書・基本設計書・詳細設計書の違いを解説!
詳細設計書に書く主な項目
詳細設計書には「必ずこの項目を書かなければならない」という一律の決まりがあるわけではありません。
システムの規模や種類、使用するプログラミング言語、プロジェクトの進め方によって必要な項目は異なります。
一般的な業務システムやWebシステムであれば、例えば次のような内容を整理します。
| 項目 | 主な内容 |
|---|---|
| 基本情報・改訂履歴 | 文書名、対象機能、作成者、バージョン、変更履歴 |
| 対象範囲・前提条件 | 設計対象となる機能やモジュール、関連文書 |
| モジュール・クラス構成 | クラスやモジュールの役割、依存関係 |
| 関数・メソッド仕様 | 処理内容、引数、戻り値、例外 |
| 処理フロー | 処理の順序、条件分岐、繰り返し |
| データ構造・内部インターフェース | 内部で扱うデータや受け渡し方法 |
| データベース処理 | 参照・更新処理、トランザクションなど |
| エラー・例外処理 | 異常時の処理、ログ出力、後続処理 |
| その他の設計事項 | 権限、性能、排他制御など必要な内部設計 |
ここからは、ユーザー登録機能を例に、詳細設計書の主な記載項目と具体的な書き方を見ていきましょう。
以下は説明用のサンプルです。実際のプロジェクトでは、使用する言語やフレームワーク、基本設計、セキュリティ要件などに合わせて設計します。
1. 基本情報・改訂履歴
まず、詳細設計書そのものを管理するための基本情報を記載します。
例えば、次のような内容です。
- 文書名
- システム名
- 対象機能・対象モジュール
- バージョン
- 作成日
- 作成者
- 承認者
- 改訂履歴
詳細設計書は、実装やレビューの結果によって内容が追加・変更されることがあります。
そのため、「どの版が最新なのか」「いつ、どの内容が変更されたのか」を確認できるようにしておくことが重要です。
例えば、改訂履歴は次のように整理します。
| バージョン | 日付 | 変更内容 | 作成者 |
|---|---|---|---|
| 1.0 | 2026/09/07 | 初版作成 | 山田 |
| 1.1 | 2026/09/10 | エラー処理を修正 | 山田 |
2. 対象範囲・前提条件
対象範囲・前提条件では、今回の詳細設計書でどこまでを設計するのかを明確にします。
例えば、ユーザー登録機能であれば、次のように整理します。
| 項目 | 内容 |
|---|---|
| 対象機能 | ユーザー登録API |
| 対象処理 | 入力チェック、重複確認、パスワードのハッシュ化、ユーザー情報の保存 |
| 対象外 | 登録画面のデザイン、メール認証処理 |
| 関連文書 | ユーザー登録機能仕様書、ユーザー登録基本設計書 |
| 前提条件 | データベースおよび認証基盤が利用可能であること |
対象範囲を明確にしておくことで、ほかの機能や設計書との役割分担が分かりやすくなります。
また、基本設計書や共通設計書などに定義済みの内容は、必要に応じて参照先を記載し、同じ内容を重複して管理しないようにすることも大切です。
3. モジュール・クラス構成
モジュール・クラス構成では、機能を実現するために、どのようなモジュールやクラスを使用するのかを整理します。
例えば、ユーザー登録機能を次のような構成にします。
UserController
↓UserService
├─ UserRepository
└─ PasswordHasher
それぞれの役割は、次のようにまとめられます。
| クラス名 | 主な役割 |
|---|---|
UserController | HTTPリクエストを受け付け、処理結果を返す |
UserService | ユーザー登録に関する業務処理を制御する |
UserRepository | ユーザー情報の検索・保存を行う |
PasswordHasher | パスワードを適切な方式でハッシュ化する |
このように役割を分けておくと、どの処理をどこに実装するのかが明確になります。
また、クラス間の依存関係や責務を整理することで、変更しやすく、テストしやすい構成を検討できます。
クラス構成はあくまで一例です。小規模なプログラムでは関数単位で設計する場合もあり、必ずしもクラスを使用する必要はありません。使用する言語やフレームワークに合わせて適切な構成を選びます。
4. 関数・メソッド仕様
関数・メソッド仕様では、各関数やメソッドがどのような処理を担当するのかを定義します。
例えば、ユーザー登録処理のメソッドを次のように設計します。
| 項目 | 内容 |
|---|---|
| クラス名 | UserService |
| メソッド名 | registerUser |
| 概要 | 入力情報を検証し、新しいユーザーを登録する |
| 引数 | RegisterUserInput |
| 戻り値 | RegisteredUser |
| 主な処理 | 入力チェック、重複確認、パスワードのハッシュ化、保存 |
| 例外 | ValidationError、DuplicateEmailError、UserSaveErrorなど |
ここでは、関数の役割や入出力を明確にすることが重要です。実際の型名や例外の表現は、使用するプログラミング言語に合わせて定義します。
RegisterUserInputやRegisteredUserの具体的な項目については、後述する「データ構造・内部インターフェース」で定義します。
5. 処理フロー
処理フローでは、プログラムがどのような順序で処理を行うのかを記載します。
例えば、ユーザー登録処理は次のような流れになります。
登録リクエストを受信
↓
入力値を検証
↓
メールアドレスの重複を確認
↓
パスワードをハッシュ化
↓
ユーザー情報を保存
↓
登録結果を返す
さらに、条件分岐や異常時の処理も含めて整理します。
| No. | 処理 | 正常時の処理 | 異常時の処理 |
|---|---|---|---|
| 1 | 入力チェック | 必須項目や形式を検証する | 不正な場合は入力エラーとして処理する |
| 2 | 重複確認 | 同じメールアドレスが登録されていないか確認する | 登録済みの場合は重複エラーとして処理する |
| 3 | パスワード処理 | 適切な方式でパスワードをハッシュ化する | 処理に失敗した場合は登録処理を中断する |
| 4 | ユーザー保存 | データベースにユーザー情報を保存する | 一意制約違反や保存失敗を適切に処理する |
| 5 | 結果返却 | 登録結果を呼び出し元へ返す | 発生したエラーに応じた結果を返す |
処理フローでは、正常時だけでなく、条件分岐や異常時の処理も明確にすることが重要です。
例えば、メールアドレスが既に登録されている場合は重複エラーとし、保存に失敗した場合は必要に応じてロールバックやログ出力を行う、といった内容を定義します。
メールアドレスの重複確認だけでは、同時登録による競合を完全には防げません。実際の設計では、データベースの一意制約なども利用し、競合が発生した場合の処理を定義します。
6. データ構造・内部インターフェース
データ構造・内部インターフェースでは、モジュール間で受け渡すデータや、プログラム内部で使用するデータ構造を定義します。
例えば、ユーザー登録処理の入力データRegisterUserInputを次のようにします。
| 項目 | 型の例 | 説明 |
|---|---|---|
email | string | メールアドレス |
password | string | パスワード |
displayName | string | 表示名 |
登録結果として返すRegisteredUserは、次のような構造にします。
| 項目 | 型の例 | 説明 |
|---|---|---|
id | string | ユーザーID |
email | string | メールアドレス |
displayName | string | 表示名 |
createdAt | datetime | 登録日時 |
このように、データ構造を明確にしておくことで、モジュール間で受け渡す情報の認識を合わせやすくなります。
また、モジュール間の呼び出し関係も整理できます。
| 呼び出し元 | 呼び出し先 | 処理内容 |
|---|---|---|
UserController | UserService | 登録処理を依頼する |
UserService | UserRepository | ユーザー情報の検索・保存 |
UserService | PasswordHasher | パスワードのハッシュ化 |
外部APIの仕様は基本設計書などで定義し、詳細設計書では必要に応じて、プログラム内部のデータやインターフェースを具体化します。
7. データベース処理
データベースを使用する場合は、プログラム内部でどのような参照・更新処理を行うのかを記載します。
例えば、ユーザー登録処理では次のような内容を整理します。
| 項目 | 内容 |
|---|---|
| 対象テーブル | users |
| 参照処理 | メールアドレスによる既存ユーザーの確認 |
| 更新処理 | 新しいユーザー情報のINSERT |
| 一意制約 | メールアドレスの一意性を保証する |
| トランザクション | 必要な更新処理を適切な単位で管理する |
| 異常時 | 保存失敗や一意制約違反を適切に処理する |
SQLを詳細設計書に記載するかどうかは、プロジェクトの方針によって異なります。
例えば、複雑な検索処理や性能に影響するSQLは具体的に記載し、単純なCRUD処理はORMの操作内容を中心に記載することもあります。
重要なのは、実装に必要なデータベース処理の内容が明確になっていることです。
8. エラー・例外処理
エラー・例外処理では、処理が正常に完了しなかった場合に、どのような動作をするのかを定義します。
例えば、次のような内容です。
| エラー条件 | 内部処理の例 |
|---|---|
| 必須項目が未入力 | 入力エラーとして処理する |
| メールアドレスの形式が不正 | 入力エラーとして処理する |
| メールアドレスが重複 | 重複エラーとして処理する |
| データベースへの保存失敗 | 必要に応じてロールバックし、ログを記録する |
| 予期しない例外 | 共通例外処理へ渡し、適切に記録する |
詳細設計では、単に「エラーを表示する」と書くだけでなく、内部でどのように例外を扱うのかを明確にします。
例えば、ログに記録する情報、例外を呼び出し元へ伝える方法、トランザクションの扱いなどです。
ログを出力する場合は、パスワードや認証トークンなどの機密情報を記録しないように注意します。また、利用者へ返すエラーメッセージに、データベースの内部情報などを含めないようにします。
9. その他の設計事項
システムの特性に応じて、基本設計や非機能要件で決められた内容を、プログラム内部でどのように実現するのかについても記載します。
例えば、次のような内容です。
| 項目 | 記載する内容の例 |
|---|---|
| 権限・認可 | 処理を実行できるユーザーや権限の確認方法 |
| 排他制御 | 同時更新や競合が発生した場合の処理 |
| 性能 | 大量データ処理、キャッシュ、検索方法などの設計 |
| ログ | 出力するイベント、ログレベル、機密情報の扱い |
| 設定値 | タイムアウト、リトライ回数などの管理方法 |
| 外部連携 | 外部サービス呼び出し時の内部処理や障害対応 |
例えば、基本設計で「管理者のみ実行できる」と決められている処理であれば、詳細設計では、どのモジュールで権限を確認するのか、権限がない場合にどのような例外として扱うのかなどを具体化します。また、性能要件を満たすためのキャッシュや検索方法、外部サービスを呼び出す際のタイムアウトやリトライ条件などを設計する場合もあります。
ただし、すべての項目を詳細設計書に含める必要はありません。共通設計書や非機能設計書などにまとめ、詳細設計書から参照する方法もあります。
詳細設計書はどこまで細かく書く?
詳細設計書を書く際に迷いやすいのが、「どこまで細かく記載すればよいのか」という点です。
基本的には、実装に必要な設計上の判断が共有され、開発者によって処理方法や構造に大きな認識違いが生じない粒度を目指します。
ただし、すべての処理を細かく文章にする必要はありません。重要な処理条件や例外処理、モジュール間の役割分担など、実装時に判断が分かれやすい部分を中心に具体化することが大切です。
例えば、次のような記述だけでは不十分な場合があります。
ユーザー情報をチェックして保存する。
これでは、どのようなチェックを行うのか、重複時にどうするのか、保存失敗時にどうするのかが分かりません。
以下のように記載すれば、実装に必要な判断を十分に共有できる場合があります。
- 入力値の必須項目・形式を検証する。
- メールアドレスの重複を確認し、パスワードをハッシュ化したうえでユーザー情報を保存する。
- 保存時の一意制約違反は重複エラーとして扱い、そのほかの保存失敗は共通例外処理へ渡す。
詳細設計書の粒度は、開発者の経験、システムの複雑さ、チームのルール、保守の必要性などによって調整します。
詳細設計書にプログラムのコードは必要?
詳細設計書に、必ずしもプログラムのコードを記載する必要はありません。
詳細設計書は、プログラムの内部構造や処理方法を明確にするための文書であり、ソースコードそのものをすべて書き写すものではないためです。
ただし、複雑なアルゴリズムや処理を説明する場合は、擬似コードを使用すると分かりやすくなることがあります。
例えば、次のような擬似コードです。
入力値を検証する
メールアドレスが登録済みの場合
重複エラーとする
パスワードをハッシュ化する
ユーザー情報を保存する
登録結果を返す擬似コードは、特定のプログラミング言語の文法にこだわらず、処理の流れを表現する方法です。
一方、実装と同じコードを詳細設計書に大量に記載すると、コード変更時に文書との不一致が発生しやすくなります。そのため、何を文書として残すかは、保守性も考慮して判断するとよいでしょう。
詳細設計書を作成するときのポイント
詳細設計書を作成する際は、次の点を意識すると、実装やレビューで使いやすい文書になります。
基本設計との整合性を保つ
詳細設計は、基本設計で決めた内容を実現するためのものです。
そのため、画面仕様やAPI仕様、データベース設計などと矛盾していないか確認します。
例えば、基本設計書では「メールアドレスは重複登録できない」と定義されているのに、詳細設計書で重複確認や一意制約を考慮していなければ、設計に不整合が生じます。
詳細設計の段階で基本設計の変更が必要になった場合は、関係者と調整し、関連する文書も適切に更新します。
正常系だけでなく異常系も考える
詳細設計では、正常に処理が完了する場合だけでなく、エラーが発生した場合の動作も考えることが重要です。
例えば、ユーザー登録機能であれば、以下の内容などを考慮します。
- 必須項目が入力されていない場合
- メールアドレスの形式が不正な場合
- メールアドレスが既に登録されている場合
- データベースへの保存に失敗した場合
- 予期しない例外が発生した場合
特に、データの整合性やセキュリティに関わる処理は、異常時の動作を明確にしておくことが大切です。
処理の責務を明確にする
クラスやモジュールを設計する際は、それぞれが何を担当するのかを明確にします。
例えば、ユーザー登録機能であれば、HTTPリクエストの処理、業務ロジック、データベースアクセスなどの責務を分けることが考えられます。
すべての処理を1つのクラスや関数にまとめてしまうと、修正時に影響範囲が分かりにくくなったり、単体テストが難しくなったりすることがあります。
そのため、システムの規模や複雑さに合わせて、変更しやすく、テストしやすい構成を検討します。
文書を細かくしすぎない
詳細設計書は、細かければ細かいほどよいというものではありません。
すべての変数代入や単純な処理まで文章にすると、文書の作成や更新に時間がかかり、かえって重要な設計内容が分かりにくくなることがあります。
そのため、重要な設計判断や処理条件、実装する人によって認識が異なりやすい部分を中心に記載することが大切です。
例えば、複雑な条件分岐や例外処理は詳しく記載し、単純な処理は関数の役割や入出力を示す程度にとどめるなど、必要に応じて粒度を調整します。
実装後も必要に応じて更新する
実装中に設計変更が発生した場合は、必要に応じて詳細設計書も更新します。
例えば、実装中に処理方法を変更したり、エラー処理を追加したりすることがあります。
その結果、設計書と実際のプログラムが大きく異なる状態になると、後から保守する人が正しい仕様を判断しにくくなります。
そのため、詳細設計書を作成して終わりにするのではなく、必要な設計情報を最新の状態に保つことも重要です。
まとめ
詳細設計書とは、基本設計で決めた内容を、プログラムとして実装できるように内部構造や処理方法まで具体化した文書です。
主に、次のような内容を記載します。
- モジュールやクラスの構成
- 関数・メソッドの役割や入出力
- 処理フローや条件分岐
- データ構造や内部インターフェース
- データベース処理
- エラー・例外処理
- 必要に応じた性能・権限・排他制御などの設計
プロジェクトの規模や開発手法に合わせて、実装に必要な情報を過不足なく整理することが大切です。
また、詳細設計書の記載範囲や名称はプロジェクトによって異なるため、チーム内で役割や粒度を共有したうえで作成するとよいでしょう。
お読みいただきありがとうございました。