Part 3 Webアプリケーション開発
第9章 要件からドメインを整理する
第8章までは、既存のWebアプリケーションを手元で動かし、HTTPを観察し、既存コードを小さく読んで修正する流れを扱った。 第9章からは、Part 3として、小さなWebアプリケーション機能を設計し、作り、守る流れに入る。
このPartの入口で、すぐDBカラムや画面部品を決めてはいけない。 要求文を受け取った直後は、まだ仕事の言葉、状態、ルール、例外、作る範囲が曖昧だからである。 ここを曖昧なまま進めると、第10章のデータ設計、第11章のAPI設計、第12章の画面設計、第13章のテストで、同じ判断を何度もやり直すことになる。
この章で扱う題材は、次の要求である。
「メンターが、担当受講者に支援ステータスを付けられるようにしたい。」
短い要求だが、中には多くの判断が含まれている。 メンターとは誰か。 担当受講者とは何か。 支援ステータスとは、学習ログの提出状態と同じものなのか、別のものなのか。 誰が変更できるのか。 自動アラートは作るのか。 どの状態になれば完成と言えるのか。
要件整理の目的は、文章をきれいにすることではない。 実装で迷う判断を、実装前に見つけることである。
この章でできるようになること
この章のゴールは、DDDの用語を正確に暗唱することではない。 短い要求文を、後続のDB、API、画面、テストへ渡せる設計材料に分解できるようになることである。
- 機能要求から、利用者、目的、事前条件、基本の流れ、例外、成功条件を取り出せる。
- 似た言葉を用語集で分け、画面文言、API field名、テスト名がずれないようにできる。
- 状態、イベント、ルールを分け、保存する値、起きる出来事、守る制約を混ぜずに説明できる。
- 今回作る範囲、今回は作らない範囲、後で検討する範囲を分けられる。
- ドメインモデルで、主要概念と関係をDB設計前のたたき台として書ける。
- 受け入れ条件を、前提、操作、結果の形で書ける。
- AIの案を、業務ルールとして確定せず、不明点や確認事項として扱える。
要求文を、すぐ実装名に変えない
要求文を受け取ると、すぐに「DBにstatusカラムを足す」「画面にセレクトボックスを置く」「APIを追加する」と考えたくなる。 それらは後で必要になるかもしれない。 しかし、最初に決めるべきことではない。
たとえば、支援ステータスをDBの文字列カラムにすればよいと決めたとする。 しかし、支援ステータスの値が何種類あるのか、誰が更新できるのか、未設定を許すのか、更新履歴が必要なのか、受講者本人に見えるのかが決まっていなければ、カラムだけ作っても設計は終わらない。
まず見るべきなのは、利用者と目的である。 この機能を使う人はメンターである。 目的は、担当受講者の支援状況を確認し、必要ならステータスを変更できるようにすることである。 この一文まで戻ると、画面部品やDBカラムより前に、仕事の流れが見える。
要件整理では、要求文を次の箱へ分ける。
- 利用者と目的。
- 使う言葉。
- 状態。
- イベント。
- ルール。
- 今回作る範囲と作らない範囲。
- 実装後に確認する受け入れ条件。
この箱に分けることで、後続の設計へ渡せる材料ができる。
要求、ドメイン整理、実装詳細は、粒度が違う。
| 粒度 | 例 | この章での扱い |
|---|---|---|
| 要求 | メンターが担当受講者に支援ステータスを付けたい | 出発点として使う |
| ドメイン整理 | 担当受講者、支援ステータス、変更できる人、対象外を定義する | この章で整理する |
| 実装詳細 | DBカラム、API path、UI component、SQL制約 | 第10章以降へ渡す材料にする |
この章でDBやAPIを一切考えてはいけない、という意味ではない。 思いついた実装案はメモしてよい。 ただし、まだ確定した設計として扱わず、用語、ルール、受け入れ条件へ戻して確認する。
ドメインは、仕事で使う言葉と決まりである
ドメインという言葉は難しく見えるが、この章では軽く扱う。 ドメインとは、その仕事で使う言葉、状態、ルール、例外のまとまりである。 研修用学習ログアプリでいえば、受講者、メンター、担当受講者、学習ログ、提出、支援ステータスといった言葉がドメインに含まれる。
ドメインを整理する理由は、実装者同士の誤解を減らすためである。
画面では「要支援」と表示し、APIでは alert と呼び、テストでは「未対応」と呼んでいると、同じものを指しているのか、別のものを指しているのか分からなくなる。
用語をそろえることは、初心者向けの補助ではない。 データベースのテーブル名、APIのfield名、画面の文言、テスト名、PR本文の説明が同じ仕事の言葉につながるための設計作業である。
この章では、DDDの専門理論を深く扱わない。 DDDはDomain-Driven Designの略で、業務の言葉と設計を近づける考え方を含む。 その入口として、言葉とルールを軽量に整理する。
この章でいうドメイン整理は、重い設計プロセスではない。 少なくとも次の問いに答えられれば、後続章の土台になる。
- その言葉は何を指すのか。
- 似た言葉と何が違うのか。
- 誰がその状態を見たり変えたりするのか。
- その状態が変わるきっかけは何か。
- 今回のリリースで扱わないことは何か。
- 実装後に、何を確認できれば完了と言えるか。
ユースケースは、利用者の動きを一つの流れにする
ユースケースは、誰が何のために何をするかを、一つの流れとして書いたものである。 画面操作の手順だけを書くものではない。 利用者、目的、事前条件、基本の流れ、例外、成功条件、対象外を書く。
支援ステータス機能なら、最初の一文は次のようにできる。
「メンターが担当受講者の支援状況を確認し、必要ならステータスを変更する。」
この一文を、さらに分解する。
利用者: メンター。
目的: 担当受講者の中で、追加支援が必要な人を見つけ、状態を後で見返せるようにする。
事前条件: メンターがログインしている。 メンターに担当受講者が割り当てられている。 担当受講者の進捗一覧を開ける。
基本の流れ: メンターが担当受講者一覧を開く。 受講者ごとの支援ステータスを見る。 必要に応じてステータスを変更する。 変更後のステータスが保存され、一覧で確認できる。
例外、分岐: 担当受講者がいない。 ステータスが未設定である。 担当外の受講者を変更しようとする。
成功条件: 担当メンターが、担当受講者の支援ステータスを確認し、変更後の状態を再表示して確認できる。
今回対象外: 自動アラート、CSV出力、詳細分析ダッシュボード。
このように書くと、機能名だけでは見えない前提や例外が出てくる。 ユースケースは、設計前の地図である。
ユースケースで大事なのは、画面名ではなく利用者の目的である。
弱い書き方:
支援ステータスのセレクトボックスを追加する。
よい書き方:
メンターが担当受講者の支援状況を一覧で確認し、
必要な受講者の支援ステータスを手動で変更できる。
前者は実装部品を示している。 後者は、誰が何のために何を達成したいかを示している。 画面部品は後で変わるかもしれないが、利用者の目的は設計判断の基準として残る。
不明点もユースケースに残す。 たとえば、担当受講者がいない場合に空状態をどう表示するか、支援ステータス未設定を許すか、変更履歴を初回から保存するかは、実装前に確認したい論点である。
用語集は、チームの小さな契約である
用語集は、辞書ではない。 チームが同じ言葉を同じ意味で使うための小さな契約である。
支援ステータス機能では、似た言葉を早めに分ける必要がある。 未提出、未対応、要支援、困っている、アラート対象は、似て見える。 しかし、同じ意味とは限らない。
未提出は、学習ログがまだ提出されていない状態である。 要支援は、メンターが追加支援が必要だと判断した支援ステータスである。 アラート対象は、システムが自動検知する候補かもしれない。 未対応は、メンターがまだ対応していない運用上の状態かもしれない。
これらを混ぜると、設計が崩れる。 学習ログの提出状態と支援ステータスを同じものとして扱うのか、別物として扱うのかを決める必要がある。 別物なら、データベースでもAPIでも画面でも、別の概念として扱うことになる。
glossary.mdでは、用語、意味、似た言葉や注意点、コード上の名前候補を書く。 迷っている用語は消さない。 迷いは設計上の重要な情報であり、レビューやメンター確認の論点になる。
用語集は、たとえば次のように書ける。
| 用語 | 意味 | 似た言葉、注意点 | コード上の名前候補 |
|---|---|---|---|
| 受講者 | 研修を受け、学習ログを提出する人 | ユーザー全般とは限らない | learner |
| メンター | 受講者を支援し、進捗を確認する人 | 管理者とは権限が違う可能性がある | mentor |
| 担当受講者 | そのメンターが支援対象として割り当てられた受講者 | 全受講者ではない | assignedLearner |
| 未提出 | 学習ログの提出日時がない状態 | 要支援とは別概念 | unsubmitted |
| 支援ステータス | メンターが支援状況を把握するための状態 | 提出状態、自動アラートとは別概念 | supportStatus |
コード上の名前候補は、すぐ確定するためではなく、後続章で名前がずれないようにするために置く。 日本語の業務用語と英語のfield名が一対一で対応しない場合は、注意点に残す。
状態、イベント、ルールを分ける
状態は、対象の今の様子を表す。 イベントは、状態を変えるきっかけになる出来事である。 ルールは、いつ、誰が、何を変えてよいか、何をしてはいけないかを決める条件である。
この三つを混ぜると、保存すべきもの、操作として扱うもの、確認すべき制約が曖昧になる。
支援ステータスの状態は、たとえば次の候補になる。
- 要支援。
- 支援中。
- 解決済み。
- 未設定。
状態候補は、意味とコード候補を分けて置くと後で扱いやすい。
| 状態 | 意味 | コード上の名前候補 |
|---|---|---|
| 未設定 | まだメンターが支援ステータスを付けていない | none または unset |
| 要支援 | 追加の支援が必要だとメンターが判断している | needs_support |
| 支援中 | メンターが支援対応中である | in_progress |
| 解決済み | 支援対応が一区切りした | resolved |
ここで大切なのは、状態の数を増やしすぎないことである。 「気になる」「要確認」「注意」「緊急」のような近い言葉を増やすと、メンターがどれを選べばよいか迷いやすい。 初回MVPでは、判断と運用が続けられる最小の状態から始める。
イベントは、状態を変えるきっかけである。 たとえば、メンターが支援ステータスを変更する、受講者が学習ログを提出する、メンターが支援メモを追加する、といった出来事である。
ただし、イベントが起きたからといって、必ず状態が変わるとは限らない。 受講者が学習ログを提出したら、支援ステータスは自動で解決済みになるのか。 それとも、メンターが確認して手動で変更するのか。 これはルールとして確認する必要がある。
ルールの例は次である。
- メンターは、担当受講者の支援ステータスだけ変更できる。
- 受講者本人は、支援ステータスを変更しない。
- 初回リリースでは、自動アラートを作らない。
- 支援ステータスが未設定の受講者を許すかどうかは確認する。
- 変更履歴を保存するかどうかは、今回の範囲として確認する。
状態、イベント、ルールを表に分けると、混乱しにくい。
| 種類 | 例 | 後続章で関係するもの |
|---|---|---|
| 状態 | 支援ステータスが要支援である | DBカラム、API response、画面表示、テスト期待値 |
| イベント | メンターが支援ステータスを変更した | API request、監査ログ、更新日時 |
| ルール | 担当メンターだけが変更できる | 認可、DB制約、APIエラー、テスト |
「受講者が学習ログを提出したら支援ステータスを自動で解決済みにする」は、状態ではなくルールである。 しかも初回リリースで採用するかどうかは別判断である。 このように分けておくと、便利そうな自動化をMVPへ混ぜすぎずに済む。
状態、イベント、ルールを分けておくと、第10章以降で設計へ変換しやすい。 状態は保存される値になる可能性がある。 イベントはAPIやログの設計に関係する。 ルールはDB制約、APIの認可、画面の制御、テスト条件へつながる。
境界を決めると、MVPが膨らみにくくなる
境界は、今回作る範囲、今回は作らない範囲、後で検討する範囲を分ける線である。 境界が曖昧なまま進めると、小さな機能がすぐに大きくなる。
今回作る範囲は、メンターが担当受講者の支援ステータスを手動で更新できることである。 今回作らない範囲は、自動アラート、CSV出力、詳細分析ダッシュボードである。 後で検討する範囲は、支援履歴の集計、メンター間の引き継ぎ、通知、分析機能などである。
境界は、次のように分けて書ける。
| 区分 | 内容 | 理由 |
|---|---|---|
| 今回作る | 担当メンターが担当受講者の支援ステータスを手動で変更し、一覧で確認できる | メンターが支援状況を見返せる価値を最小で確認するため |
| 今回作らない | 自動アラート、CSV出力、詳細分析ダッシュボード | 初回MVPの確認対象ではなく、条件や運用設計が増えるため |
| 後で検討 | 変更履歴、通知、メンター間引き継ぎ、集計 | 価値はあり得るが、初回で必要か確認が必要なため |
対象外には、理由も添える。 「やらない」とだけ書くと、価値を否定しているように見えることがある。 「初回MVPの確認対象ではない」「運用ルールがまだ未確認」のように理由を添えると、後で再検討しやすい。
対象外を書くことは、価値を小さくすることではない。 今回確認したい価値を見えるようにすることである。 第2章で扱ったMVPの考え方がここで再び使われる。
境界は、PR本文にも効く。 今回やらないことが明確なら、レビューで「なぜ通知がないのか」「履歴はどうするのか」という話を、別の検討事項として扱える。
ドメインモデルは、DB設計の前に作る概念の地図である
ドメインモデルは、業務で出てくる主な概念と関係を表すたたき台である。 最初から厳密な図を作る必要はない。 主要な言葉と関係のメモで十分である。
支援ステータス機能なら、主要概念は次のようになる。
- メンター。
- 受講者。
- 担当。
- 学習ログ。
- 提出。
- 支援ステータス。
- 支援メモ。
関係は、たとえば次のように書ける。
メンターは、複数の受講者を担当する。 受講者は、学習ログを提出する。 受講者は、支援ステータスを持つ。 メンターは、担当受講者の支援ステータスを変更する。
この段階では、まだDBテーブル名にしない。 「担当」をテーブルにするか、既存の関係で表せるかは第10章で考える。 「支援メモ」を初回MVPに含めるかどうかも、境界として残す。
簡単な図なら、箇条書きで十分である。
メンター
- 担当する -> 受講者
受講者
- 提出する -> 学習ログ
- 持つ -> 支援ステータス
支援ステータス
- 変更する人 -> 担当メンター
この図は、DBのER図ではない。 「支援ステータスを受講者が持つのか、担当関係が持つのか」「支援メモは支援ステータスの一部なのか別概念なのか」といった次の問いを見つけるための地図である。
ドメインモデルは、設計の完成図ではない。 後続章で変換するための材料である。
受け入れ条件は、完了の見方を決める
受け入れ条件は、実装が要求を満たしたと言える具体的な条件である。 言い換えると、作ったあとに何を見れば終わったと言えるかである。
受け入れ条件は、前提、操作、結果に分けると書きやすい。 この形をGiven、When、Thenと呼ぶことがある。
正常系の例: Given メンターが担当受講者の進捗一覧を開いている。 When 支援ステータスを要支援に変更する。 Then その受講者の支援ステータスが要支援として保存され、一覧で確認できる。
権限の例: Given メンターが担当外の受講者の情報を見ている。 When 支援ステータスを変更しようとする。 Then 変更できない。
例外の例: Given 支援ステータスが未設定の受講者がいる。 When メンターが一覧を開く。 Then 未設定として表示される、または初期値が表示される。
もう少し実務で使いやすく書くなら、正常系、権限、対象外を分ける。
正常系
前提: メンターが担当受講者の進捗一覧を開いている
もし: 支援ステータスを「要支援」に変更する
ならば: その受講者の支援ステータスが保存され、再読み込み後も「要支援」と表示される
権限
前提: メンターが担当外の受講者を指定している
もし: 支援ステータスを変更しようとする
ならば: 変更できず、権限不足として扱われる
今回対象外
前提: 受講者が学習ログを提出する
もし: 提出が完了する
ならば: 初回リリースでは支援ステータスを自動変更しない
受け入れ条件は、実装手順ではない。 「どのボタンをどのCSSで置くか」ではなく、「どの前提で、何をしたら、どんな結果になればよいか」を書く。 この粒度なら、API確認、画面確認、テストケースへ変換しやすい。
受け入れ条件は、後のテストだけのためにあるわけではない。 第6章のPR確認方法、第11章のAPI確認、第12章の画面状態、第13章のテスト設計へつながる。
AIは、抜け漏れ確認の相手として使う
AIは、ユースケース案、用語候補、状態やルールの抜け漏れ、ドメインモデルのたたき台、受け入れ条件の初稿づくりに使える。 ただし、AIに業務ルールの最終決定を任せてはいけない。
AIへ依頼するときは、制約を明記する。 たとえば、DB設計やAPI設計にはまだ入らない、自動アラートは今回対象外、不明点は不明点として分ける、個人情報や秘密情報は入れない、という条件を渡す。
依頼は次のように書ける。
目的: 実装前に、ユースケース、用語、状態、ルール、受け入れ条件を整理したいです。
制約: DB設計やAPI設計にはまだ入らない。 自動アラートは今回対象外。 不明点は不明点として分ける。 個人情報、秘密情報、社内だけの情報は入れない。
出してほしいこと: ユースケース案、用語集の候補、状態、イベント、ルール、受け入れ条件、確認すべき不明点。
AIの出力は、候補として扱う。 支援ステータスの値、担当メンターの権限、対象外にする範囲は、メンターや仕様を知っている人に確認して決める。
AIの出力を見るときは、次のように分ける。
| AIの出力 | 扱い |
|---|---|
| 用語候補 | glossary.mdへ候補として置き、似た言葉との差分を人が確認する |
| 状態候補 | 状態数が多すぎないか、運用で選べるかを確認する |
| ルール候補 | 権限、担当関係、対象外と矛盾しないか確認する |
| 受け入れ条件 | 実装後に観察できる形になっているか確認する |
| DB/API/UI案 | この章では確定せず、第10章以降のメモに回す |
AIが「自動通知も入れるべき」「緊急度を5段階にするべき」のように範囲を広げた場合は、今回のMVPと対象外へ戻る。 便利そうな案でも、初回の価値確認に必要とは限らない。
用語集と受け入れ条件で確認すること
use-case.md、glossary.md、domain-rules.md、domain-model.md、acceptance-criteria.md を作る。
use-case.md には、機能要求、利用者、目的、事前条件、基本の流れ、例外と分岐、成功条件、今回対象外、不明点を書く。
glossary.md には、受講者、メンター、担当受講者、学習ログ、支援ステータスなどの意味、似た言葉、コード上の名前候補を書く。
domain-rules.md には、状態、イベント、ルール、例外、迷うケース、今回決めないことを書く。
domain-model.md には、主要概念、関係、状態、重要なルール、今回対象外の概念を書く。
acceptance-criteria.md には、正常系、権限、例外、今回対象外、PRで説明する確認方法を書く。
提出前には、次を確認する。
- DB、API、画面の具体案に寄りすぎていないか。
- 未提出、要支援、未対応、アラート対象を混ぜていないか。
- 担当メンターだけが変更できる、という権限ルールがどこかに残っているか。
- 今回対象外の理由が書けているか。
- 受け入れ条件が、実装後に観察できる形になっているか。
- AIを使った場合、採用した候補と未確認の候補を分けているか。
成果物の目的は、きれいな設計書を作ることではない。 後続のデータ設計、API設計、画面設計、テスト設計で迷わないように、言葉と判断を残すことである。
ドメイン整理で起きやすい誤解
- 要求文をすぐDBカラムや画面部品に変換する。
- 画面の項目名を、そのまま業務用語だと決める。
- 未提出、要支援、未対応、アラート対象を同じ意味として扱う。
- 状態、イベント、ルールを混ぜて書く。
- 例外や対象外を残さず、後で仕様漏れとして戻ってくる。
- コード上の名前候補を、業務用語の確定だと思い込む。
- 受け入れ条件を、画面部品や実装手順の説明にしてしまう。
- 権限ルールを後回しにし、担当外の受講者を変更できるかを曖昧にする。
- AIが出した用語や状態を、業務確認なしに採用する。
ドメインを整理する章で持ち帰ること
第9章で身につけるべきことは、要求文を実装前の設計材料へ分解することである。 利用者と目的を確認する。 用語をそろえる。 状態、イベント、ルールを分ける。 境界を決める。 ドメインモデルで概念と関係を見えるようにする。 受け入れ条件で、完了の見方を決める。
この整理は、Part 3全体の土台である。 言葉とルールが曖昧なままでは、データベース、API、画面、テストも曖昧になる。
データを保存できる形にする章へ
次章では、このドメイン整理をデータベースの形へ変換する。 支援ステータスを保存するなら、どのテーブルに置くのか、どの値を許すのか、未設定をどう扱うのか、担当関係をどう守るのかを考える。 第9章の言葉とルールが、第10章のテーブル、カラム、制約の材料になる。