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図ではない。 「支援ステータスを受講者が持つのか、担当関係が持つのか」「支援メモは支援ステータスの一部なのか別概念なのか」といった次の問いを見つけるための地図である。

ドメインモデルは、設計の完成図ではない。 後続章で変換するための材料である。

受け入れ条件は、完了の見方を決める

受け入れ条件は、実装が要求を満たしたと言える具体的な条件である。 言い換えると、作ったあとに何を見れば終わったと言えるかである。

受け入れ条件は、前提、操作、結果に分けると書きやすい。 この形をGivenWhenThenと呼ぶことがある。

正常系の例: 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章のテーブル、カラム、制約の材料になる。

参考資料

教材を検索