はじめに
「要件は聞いたはずなのに、できあがったものが全然違った」
── ソフトウェア開発でよく耳にする失敗の一つです。
自分も最初はこう思っていました。
「顧客が欲しいものを言ってくれて、PMがまとめてくれて、それを実装すればいい」と。
ところが実際には、顧客は自分が何を求めているか正確には説明してくれません。
エンドユーザーの言葉は曖昧で、複数のステークホルダーの要求は普通に矛盾します。
しかも要件はプロジェクトの途中で変わり続けます。
こうした状況に対処するための体系的な取り組みが
「要件エンジニアリング」と呼ばれる領域で、
要件を引き出し、構造化し、検証する一連のプロセスとして整理されています。
この記事では、要件を正確に掴むために開発者が向き合うべき4つの問いを軸に、
要件エンジニアリングの全体像を整理してみました。
- 問い1: 誰のためのシステムか?
- 問い2: 何をどう使うシステムか?
- 問い3: 何を扱い、どう振る舞うか?
- 問い4: この理解は正しいか? そして変わらないか?
なお、この記事のスコープは要件エンジニアリングの全体像と各技法の位置づけです。
個別のモデリング記法(UMLなど)の詳細な書き方までは踏み込みません。
TL;DR
- 要件は「聞けばわかる」ものではなく、ステークホルダーとの協働を通じて段階的に引き出し、構造化し、検証する反復プロセスです
- ユースケースやクラスモデル、状態図などのモデリング技法は、
「正確な仕様書を書く」ためではなく「関係者の理解を揃える」ために使います - 要件に関する活動はプロジェクトの全期間にわたって反復されるもので、
一度書けば終わる「上流の仕事」ではありません
問い1:「誰のためのシステムか?」── ステークホルダーの世界を理解する
どんなに優れたモデリング技法を使っても、
そもそも「誰の要件を掴むのか」が定まっていなければ意味がありません。
要件を考えるうえでの出発点は、
システムに関わる人々の全体像を把握することにあります。
ここで使える基本的な視点を整理してみます。
+------------------+
| エンドユーザー |
| (日々の操作) |
+--------+---------+
|
+----------------+ | +-------------------+
| ビジネスオーナー | | | 運用・サポート担当 |
| (事業成果) |---------+--------| (保守・監視) |
+----------------+ | +-------------------+
|
+--------+---------+
| システム本体 |
+--------+---------+
|
+----------------+ | +-------------------+
| マーケティング | | | 規制当局・外部機関 |
| (売れる機能) |---------+--------| (法令・基準) |
+----------------+ | +-------------------+
|
+--------+---------+
| 開発・設計チーム |
| (実装可能性) |
+------------------+
ステークホルダーを特定する ── 「話を聞くべき人」は誰か
システムに関わる人は、エンドユーザーだけではありません。
ビジネスオーナー、マーケティング、運用担当、サポートチーム、
場合によっては規制当局や外部システムの管理者まで含まれます。
最初にざっとリストを作ったうえで、
各ステークホルダーに「他に誰に話を聞くべきか?」と尋ねていくのが有効です。
芋づる式に対象が広がっていき、最初は見えていなかった関係者が浮かび上がってきます。
プロジェクトの初期段階では、基本的な問題の理解・関係者の特定・解決の方向性の把握を行います。
このとき有効なのが「コンテキストフリー質問」
── 技術的な詳細ではなく、事業目標や全体の文脈を把握するための質問群です。
[ コンテキストフリー質問の例 ]
(1) 関係者を把握する質問
- この仕事を依頼しているのは誰か?
- この解決策を使うのは誰か?
- 成功した場合の経済的な効果は?
(2) 問題と解決の方向性を探る質問
- 良い出力とはどのようなものか?
- この解決策が使われる業務環境はどうなっているか?
- 性能や制約に関する特別な事情はあるか?
(3) メタ質問(質問自体を見直す質問)
- この質問に答えるべき人は本当にあなたか?
- 私の質問はあなたが抱える問題に関連しているか?
- 他に追加情報を提供できる人はいるか?
メタ質問が地味に大事だと感じています。「この質問に答えるべき人は本当にあなたか?」と素直に聞くことで、見落としていたキーパーソンが浮かび上がることがあります。
複数の視点を受け止める ── ビューポイントの衝突と協働
ステークホルダーが見つかると、次にぶつかるのが「視点の衝突」です。
| ステークホルダー | 主な関心 | ありがちな主張 |
|---|---|---|
| マーケティング | 競争力・差別化 | 「売れる機能を増やしたい」 |
| ビジネスオーナー | 予算・スケジュール | 「予算内で期限通りに」 |
| エンドユーザー | 操作性・学習コスト | 「使い慣れた操作のままで」 |
| 運用・サポート | 安定性・運用容易性 | 「監視・復旧しやすい構成で」 |
| 開発・設計 | 実装可能性・保守性 | 「保守可能なインフラで」 |
これらの主張は必然的に衝突します。
ここで大事なのは、これらの視点を「正解/不正解」で切り捨てないことです。
全ての情報を分類し、
意思決定者が内部的に一貫性のある要件セットを選択できるようにするのが、
要件エンジニアリングの仕事の一つになります。
協働を実現するためのテクニックとして、「優先度ポイント投票」
── 各ステークホルダーに持ち点を配り、要件に投票してもらう進め方 ──
が有効です。
優先度ポイント投票の進め方
- 全ステークホルダーに同じ数のポイント(例: 100点)を配る
- 要件のリストを提示し、各自が重要だと思う要件にポイントを「使う」
- 一度使ったポイントは使い回せない。手持ちが0になったら追加投票はできない
- 全員の合計ポイントが、要件の相対的な重要度を表す
「どれも重要」と言いがちなステークホルダーに、
痛みを伴う優先順位づけをしてもらえる点が肝です。
ただし、協働は「委員会方式」を意味しません。
最終決定はプロジェクトチャンピオン(ビジネスマネージャーやシニアエンジニアなど)が担う場合が多くあります。
全員の希望を全部叶えるのではなく、
合意できる部分と相違点を明示的に整理したうえで、最後は誰かが決める、
という構造です。
機能だけでは足りない ── 非機能要件を引き出す
ステークホルダーに「何が欲しいか」を聞くと、多くの場合「機能」が返ってきます。
しかし、システムの使い勝手・性能・セキュリティ・保守性といった「非機能要件」
── 機能以外に求められる特性 ── は、聞かれなければ言語化されにくいものです。
非機能要件は次のように分類できます。
| 分類 | 着目点 | 曖昧な表現の例 | 検証可能な表現への変換例 |
|---|---|---|---|
| 品質属性 | 使いやすさ・保守性 | 「使いやすいこと」 | 「主要操作が3タップ以内で完了する」 |
| 性能属性 | レスポンス・スループット | 「速いこと」 | 「APIの95%が500ms以内に応答する」 |
| セキュリティ属性 | 認証・認可・耐侵入性 | 「安全であること」 | 「不正アクセス成功確率が0.0001未満」 |
| システム制約 | 環境・互換性 | 「既存と動くこと」 | 「Pythonランタイムは3.10以上」 |
「使いやすい」のような表現は検証不能なので、テストできる形に書き直すのがコツです。
「主要な操作が3タップ以内で完了すること」のように、測定可能な形に落とし込みます。
非機能要件の引き出しには、2フェーズで進めるアプローチが知られています。
- フェーズ1(土台作り): ベストプラクティス、アーキテクチャスタイル、設計パターンといったソフトウェアエンジニアリングのガイドラインを並べ、それぞれを行と列に置いた表で「補完/重複/衝突/独立」を評価する。これでガイドラインの相互関係が見える
- フェーズ2(優先順位付け): 各非機能要件に優先順位をつけ、決定ルールに基づいて実装するガイドラインを選ぶ
ここで決めた非機能要件は、
後の問い4で「検証可能な形になっているか」を再びチェックする対象になります。
ここまでで「誰のためのシステムか」という最初の問いに対する技法を見てきました。
ステークホルダーの全体像と、その視点の衝突を扱う方法、
そして機能だけでは見落とされがちな非機能の側面まで含めて扱うのが第一歩です。
次の問いでは、
これらの関係者がシステムを「どう使うか」をモデルで描く作業に進みます。
問い2:「何をどう使うシステムか?」── 使い方をモデルで描く
ステークホルダーが分かったとして、
次に必要なのは「このシステムを誰がどう使うのか」を具体的に描くことです。
抽象的な機能一覧ではなく、ユーザーの行動の流れとしてシステムの使われ方を描くと、
全員の理解が揃いやすくなります。
ここから「分析モデル」
── 要件を複数の視点で表現する一連のモデル群 ── の世界に入ります。
分析モデルには大きく3つの視点があります。
+--------------------------------------------------------+
| 分析モデルの3つの視点 |
+--------------------------------------------------------+
| 視点1: シナリオ視点 視点2: 構造視点 視点3: 振る舞い視点 |
| 「どう使うか」 「何を扱うか」 「どう動くか」 |
| |
| ユースケース クラスモデル 状態図 |
| アクティビティ図 CRCモデル シーケンス図 |
| |
| ↓ 問い2で扱う ↓ 問い3で扱う ↓ 問い3で扱う |
+--------------------------------------------------------+
これら3つの視点は補完関係にあり、どれか1つだけでは要件を掴みきれません。
問い2ではまずシナリオの視点から始めます。
ユースケース ── 「使う場面」を物語で捉える
ユースケースとは「特定の状況下で、アクター(ユーザーや外部デバイス)がシステムとどうやり取りするか」を物語として記述したものです。
最初にユースケースを学んだとき、
「単にユーザーの操作手順を書くだけでは?」と思っていました。実は違いました。
ポイントは「物語」であること、つまり、各ステップを追うことで関係者全員が「この場面ではこういう動きになるよね?」と確認できる点にあります。
ユースケースを構成する要素を整理しておきます。
+----------------+ +------------------+
| アクター | ---> | トリガー |
| (誰が使うか) | | (きっかけとなる事象)|
+----------------+ +--------+---------+
|
v
+------------------+
| メインシナリオ |
| (正常時の流れ) |
| 1. 〇〇する |
| 2. △△する |
| 3. ××する |
+--------+---------+
|
+-------------+-------------+
v v
+----------------+ +----------------+
| 例外フロー | | 代替フロー |
| (エラー条件) | | (別の進み方) |
+----------------+ +----------------+
アクターの定義には少し注意が必要で、エンドユーザーとは必ずしも同じではありません。
1人のユーザーが複数のアクターの役割を果たすことがあります。
たとえば、同じ人が「設定者」と「モニター」と「トラブルシューター」の役割を持つ、といった具合です。
アクターは「人」ではなく「役割」だと捉えると整理しやすくなります。
アクターには2種類あります。
- プライマリアクター: 主要な目的を果たすアクター。システムから直接的な価値を得る
- セカンダリアクター: システムを支援するアクター。プライマリアクターが目的を達成できるよう、システムを助ける
ユースケースの書き方には段階があります。最初から完璧な形を目指す必要はなく、
用途に合わせて使い分けます。
| レベル | 形式 | 内容 | 使いどころ |
|---|---|---|---|
| 1 | ユーザーストーリー | 散文の自由記述 | アイデア段階・要件の発見 |
| 2 | プライマリシナリオ | 番号付き手順の箇条書き | 主要な流れの合意形成 |
| 3 | フォーマルユースケース | テンプレート形式 | 安全性・セキュリティが重要な機能の詳細化 |
レベル3のフォーマルユースケースには、アクター・目標・前提条件・トリガー・シナリオ・例外・優先度・頻度などの項目が含まれます。次のような構造です。
ユースケース名: ホームセキュリティの監視を有効化する
プライマリアクター: 利用者
ゴール: システムをアクティブ化して監視を開始する
前提条件: パスワードが設定済みであること
トリガー: 利用者が外出のため監視を有効にしようとする
シナリオ:
1. 利用者が操作画面を確認する
2. 利用者がパスワードを入力する
3. システムがパスワードを照合する
4. 利用者が「在宅」または「外出」を選択する
5. システムがインジケータで状態を示す
例外:
E1. パスワード不一致 → 再入力を求める
E2. パスワード未認識 → サポート連絡が必要
優先度: 必須(最初のリリースに含める)
頻度: 1日に複数回
重要なのは、ユースケースは要件が進化的に明らかになっていくプロセスの一部だということです。
最初から完璧を目指さず、対話を通じて反復的に精緻化していく姿勢が前提になります。
例外を洗い出す ── 「もし〜だったら?」の問いかけ
プライマリシナリオ(正常系)だけでは要件の把握は不十分です。
各ステップに対して、次の3つの問いを投げかけて例外を洗い出します。
- このステップでアクターは他の操作をする可能性があるか?(代替フロー)
- このステップでエラー条件が発生する可能性はあるか?(エラー処理)
- このステップでアクターの制御外の事象が起こる可能性はあるか?(外部要因)
さらに掘り下げるための追加の問いもあります。
- バリデーション機能が呼び出されるか?(呼ばれるならエラー条件の可能性がある)
- 支援機能やアクターが適切に応答しない場合は?(タイムアウトの設計)
- システム性能の低下が不適切なユーザー操作を引き起こすか?(例: 反応が遅くて二重送信されるなど)
ここで気をつけたいのは、例外をいくらでも増やせてしまう点です。
ユースケースを書く際、「考えうる全ての例外」を書き出すと収拾がつかなくなります。
そこで「合理化」という考え方が役立ちます。
ソフトウェアが検知可能で、かつ検知後に対処可能な条件のみを例外として記載する、
というシンプルな絞り込みルールです。
検知も対処もできない事象は要件としては書かない、と割り切ります。
例外を別ユースケースに切り出すべきか?
例外のなかには、独立した別のユースケースとして切り出すべきものもあります。
たとえば「アラーム条件発生」のように複数のユースケースから参照される共通の例外は、毎回ベタ書きするより1つに集約したほうが管理しやすくなります。
判断基準のヒント: その例外が複数のユースケースから参照されるか、
または単独でストーリーとして成立するなら、別ユースケースに切り出す価値があります。
使い方の流れを図にする ── アクティビティ図とユースケース図
ユースケースを文章で書くだけでなく、図で補完すると理解が深まります。
UMLにはこの目的で使える図がいくつかあります。
- ユースケース図: システム境界(箱)の中にユースケース(楕円)、外にアクター(棒人間)を配置し、関係性を俯瞰する。複数のユースケースの関係を一望できる
- アクティビティ図: ユースケース内の処理フローをフローチャート的に表現する。分岐、並列処理、決定ポイントを可視化できる
- スイムレーン図: アクティビティ図に「責任の所在」のレーンを加えたもの。どのアクター(または、後で扱うクラス)がどのアクティビティを担当するかを明示する
アクティビティ図が威力を発揮するのは、機能の複雑性が高いケースです。
シンプルなユーザー操作でも、
裏側の処理が複雑な場合はアクティビティ図で可視化する価値があります。
たとえば、ログイン後に機能を選択して操作するシンプルな流れでも、
認証チェック・状態判定・エラーハンドリングが絡むと意外に分岐します。
スイムレーン図は、複数の登場人物が絡むフローでとくに有効です。
「この処理は誰の責任で動くのか」を可視化したい場面で使います。
これらの図は使い分けが大事で、単純なユースケースなら文章で十分です。
処理の分岐が複雑な場合にアクティビティ図、責任分担を可視化したい場合にスイムレーン図、という棲み分けで使うとちょうどいい粒度になります。
ここまでで、システムの「使われ方」をシナリオとして描く道具が揃いました。
次の問いでは、シナリオの中に登場した「モノ」(センサー、操作パネル、アラームなど)の
正体を掘り下げ、システムの構造と振る舞いに踏み込みます。
問い3:「システムは何を扱い、どう振る舞うか?」── 構造と動きを可視化する
ユースケースで「使い方」を描いたとしても、
そこに登場する「モノ」の正体はまだ曖昧なままです。
「センサー」「コントロールパネル」「アラーム」
── これらに対して、次のような問いが残ります。
- 何を属性として持つのか
- どんな操作ができるのか
- 互いにどう連携するのか
- システム全体は外部からの刺激にどう反応するのか
ここでは構造と動きの両面から、要件の解像度をもう一段上げます。
ユースケースから「モノ」を抽出する ── 分析クラスの特定
最初に必要なのは「分析クラス」
── 問題領域に登場する"もの"をソフトウェア的に整理したもの ──
を見つけることです。
定番の手法に「文法解析アプローチ」があります。ユースケースや処理記述に含まれる言葉を品詞で分けて、クラスや操作の候補を機械的に洗い出すやり方です。
[ 文法解析アプローチの流れ ]
ユースケース記述
|
v
+---------------------+
| 名詞・名詞句を抽出 | → クラス候補
+---------------------+
+---------------------+
| 動詞・動詞句を抽出 | → 操作(メソッド)候補
+---------------------+
|
v
候補リストの作成
|
v
+---------------------+
| 6つの選定基準で絞り込む |
+---------------------+
|
v
分析クラス
抽出された名詞は、いくつかのカテゴリに分類できます。
- 外部エンティティ: 他システム、デバイス、人など
- もの: レポート、表示、通知など、情報領域に属するもの
- 出来事: イベント、トランザクションなど、特定の時点で起こること
- 役割: マネージャー、エンジニア、利用者など、人が果たす役割
- 組織単位: 部門、チーム、グループ
- 場所: 業務環境のなかの特定の場所
- 構造: 関連するオブジェクトのまとまり
ここで一つ補足しておくと、文法解析は「クラス候補を機械的に洗い出す入口」にすぎません。
実務では関係者との対話を通じて少しずつドメインモデルを育てていく進め方も多く、
文法解析が唯一の正解というわけではないと理解しています。
候補が出揃ったら、次は絞り込みです。
候補クラスの全てがモデルに含まれるわけではないので、選定基準で取捨選択します。
| # | 選定基準 | 確認ポイント |
|---|---|---|
| 1 | 情報の保持 | このクラスについて記憶すべき情報があるか |
| 2 | 識別可能なサービス | 属性を変化させる操作を持つか |
| 3 | 複数の属性 | 複数の属性を持つか(単一属性なら他クラスの属性として吸収) |
| 4 | 共通の属性 | 全インスタンスに共通する属性が定義できるか |
| 5 | 共通の操作 | 全インスタンスに共通する操作が定義できるか |
| 6 | 本質的な要件 | 問題領域に本質的に必要な外部エンティティか |
選定はある程度主観的にならざるを得ません。
後の評価で見直されるということを考慮して、まず判断することが大事だと感じています。
クラスの中身を定義する ── 属性と操作
クラスを採用したら、次は中身を埋めます。属性と操作の2つを定義します。
属性 ── クラスを特徴づけるデータ項目
属性は各クラスを問題領域の文脈で特徴づけるデータ項目です。
「このクラスを完全に定義するためにどんなデータが必要か?」
と問うと整理しやすくなります。
属性を定義する際に気をつけたいのは次の点です。
- 複合データは分解して属性に落とし込む
(例: 「アラーム応答情報」→ 「遅延時間」「電話番号」) - 別のクラスとして定義済みのものは属性に含めない
(例: 「センサー」は「システム」の属性ではなく、独立したクラス)
操作 ── クラスの振る舞いを定義する
操作はクラスの振る舞いを定義します。大きく4つのカテゴリに分類できます。
[ 操作の4分類 ]
(1) データの操作 (2) 計算の実行
- 追加 - 集計
- 削除 - 変換
- 整形 - 算出
- 選択
(3) オブジェクトの状態の照会 (4) 制御イベントの監視
- 現在状態の取得 - イベント検知
- 属性の問い合わせ - トリガー発火
属性と操作が決まったら、UMLクラス図にまとめます。
クラス名・属性・操作を1つの箱に整理して表現する、おなじみの形式です。
+---------------------+
| System |
+---------------------+
| systemID |
| status |
| delayTime |
| masterPassword |
+---------------------+
| program() |
| arm() |
| disarm() |
| display() |
+---------------------+
クラスの関係を整理する ── 関連とCRCモデル
クラス単体が定義できたら、次はクラス同士の関係です。
UMLでは「関連」と呼ばれる線で、クラス間のつながりを示します。
集約(全体-部分の関係)も関連の一種です。
ただ、関連線だけだと「クラス同士がどう協力してシステムの機能を実現するか」までは見えません。そこで使われるのが、CRC(クラス-責務-協調者)モデルです。
CRCモデルは1枚のインデックスカードに以下を記載します。
+----------------------------------------------+
| クラス名: ControlPanel |
+----------------------------------------------+
| 責務(Responsibility) 協調者(Collaborator) |
+----------------------------------------------+
| センサー状態を判定する Sensor |
| 入力パスワードを照合する System |
| 表示メッセージを更新する Display |
| アラームを発火する AlarmDevice |
+----------------------------------------------+
責務とは、属性と操作のうち、そのクラスが「何をすべきか」を表したもの。
協調者とは、その責務を果たすために協力するクラスです。
たとえば、コントロールパネルの「センサー状態の判定」という責務は、
センサークラスの協力なしには果たせません。
「ControlPanelは自分一人ではできない、Sensorの協力が必要」と表現するわけです。
CRCモデルの面白いところは、レビュー方法にもあります。
CRCカードのロールプレイレビュー
- 参加者にカードを配る(協調する2枚を同じ人が持たないように分散)
- レビューリーダーがユースケースを読み上げる
- 該当クラスのカードの持ち主にトークンを渡す
- カードの持ち主が責務を説明し、
ユースケースの要求を満たしているかグループで判断する - 協調者が必要な責務に来たら、その協調者のカードの持ち主にトークンを回す
机上で「動かしてみる」感覚に近く、
責務の漏れや誤りが早期に発見できる効果があります。
一人でモデルを作るより、複数人でロールプレイするほうが穴を見つけやすい、
というのは納得感があります。
システムの「動き」を捉える ── 振る舞いモデリング
ここまでで「システムが何を扱うか」(構造)が見えてきました。
次は「システムが外部からの刺激にどう反応するか」(振る舞い)です。
振る舞いを捉える出発点は「イベントの識別」です。
ユースケースの中で「システムとアクターの間で情報がやり取りされるポイント」を洗い出します。
そのやり取り自体がイベントになります。
ここで初学者がつまずきやすいのが「イベントは情報そのものではない」という点です。
たとえば、「ユーザーがパスワードを入力する」というシナリオを考えてみます。このとき、
- 「パスワード入力」というイベント自体は、情報がやり取りされた事実
- パスワードの中身(具体的な文字列)は情報
という区別になります。イベントは「情報がやり取りされた事実」のほうを指します。
イベントには制御フローへの影響度合いで分類があります。
- 制御フローに直接影響するイベント: パスワードの照合結果(合致/不一致でその後の流れが変わる)
- 制御フローに直接影響しないイベント: パスワードの入力自体(入力されただけでは流れは分岐しない)
イベントが識別できたら、それを使って2種類の図を描きます。
UML状態図 ── ひとつのオブジェクトの一生を描く
UML状態図は、オブジェクトの「外部から観察可能なモード」と、
それを遷移させるイベントを表現します。基本的な構成要素は次の通りです。
- 状態: そのオブジェクトが取りうるモード
- 遷移: ある状態から別の状態へ移ること
- イベント(トリガー): 遷移のきっかけとなる事象
- ガード: 遷移が発生するために満たすべき条件
- アクション: 遷移に伴って実行される操作
なお、状態は2つの側面に分けると整理しやすい、という見方も知られています。
- パッシブな側面: 属性値の現在のスナップショット
- アクティブな側面: 変換や処理が進行中のステータス
前者は構造に近く、後者は振る舞いに近い側面で、
UML状態図ではこのうちアクティブな側面を中心に扱うイメージです。
UMLシーケンス図 ── オブジェクト間の会話を時間軸で描く
UMLシーケンス図は、オブジェクト間のメッセージのやり取りを時間軸に沿って描きます。
状態図とシーケンス図は補完関係にあります。
状態図は「ひとつのオブジェクトの一生」を描き、
シーケンス図は「複数オブジェクトの会話の一場面」を描く、というイメージです。
どちらか一方ではなく、両方を組み合わせて使うことで、
振る舞いの全体像が見えてきます。
ここまでで、構造(クラス)と動き(状態・シーケンス)の両面からシステムを描く道具が揃いました。
次は最後の問い、「この理解は本当に正しいのか? そして変わらないのか?」に進みます。
問い4:「この理解は正しいか? そして変わらないか?」── 要件を検証し管理し続ける
ユースケースを書き、クラスを定義し、振る舞いをモデル化しました。
しかしここで安心するのはまだ早いところがあります。
ステークホルダーの言ったことと、自分たちが理解したことは、本当に同じだろうか。
そして、今日合意した要件は明日も変わらないだろうか。
要件は揺れ続けるもの、という前提に立って、
次の3つの活動を組み合わせていくことになります。
- 交渉: ステークホルダーの優先順位を調整して合意を作る
- 妥当性確認: 合意した要件が本当に正しいかを確認する
- モニタリングと管理: 要件の変化を追跡し、トレーサビリティを保つ
合意形成の技術 ── 要件の交渉
「全部欲しい」は実現できません。
限られたリソースの中で、ステークホルダーに要件の優先順位をつけてもらい、
衝突を解消する必要があります。
これが「交渉(negotiation)」と呼ばれる活動です。
交渉の原則は、勝者も敗者もいない「win-win」を目指すことです。
双方が合意できる「十分な」要件セットを反復的に形成していきます。
具体的には次のような流れで進めます。
- 要件の優先順位付け: 問い1で扱った優先度ポイント投票なども使いつつ、何を優先するか整理する
- コストとリスクの評価: 各要件の実装コストと、入れた場合・入れなかった場合のリスクを見積もる
- 内部矛盾の解消: ステークホルダー間の矛盾する要件を、組み合わせの調整・優先度の調整で解消する
ここで知っておきたいテクニックに「ハンドシェイキング」というアプローチがあります。
[ 従来のアプローチ ]
顧客 ──→(要件仕様書)──→ ソフトウェアチーム
一方通行・渡したら終わり
[ ハンドシェイキング ]
顧客 ←──(解決策の提案・影響の説明)──── ソフトウェアチーム
顧客 ──(不足機能の指摘・新規要件の明確化要求)──→ ソフトウェアチーム
双方向・「十分」と認めた時点で確定
「要件仕様書をソフトウェアチームに渡す」一方通行ではなく、
ソフトウェアチームが解決策を提案し、
顧客がレビューする双方向コミュニケーションが特徴です。
要件は双方が「十分」と認めた時点で確定します。
最初にこの考え方を知ったとき、
「結局、誰が要件を決めるのか」が曖昧になるのではと思っていました。
実際には、双方向のやり取りを通じて「ここまでで十分」という合意点を見つけにいく形なので、責任の所在が消えるわけではありません。
本当に正しいか確認する ── 妥当性確認
合意が取れた要件でも、本当に正しいかは別の話です。
「妥当性確認(validation)」
── 成果物が本当に正しいかを確認する活動 ── が必要になります。
妥当性確認の主要なメカニズムは「テクニカルレビュー」です。
ソフトウェアエンジニア・顧客・ユーザー・その他のステークホルダーが集まって、
仕様書を検査します。
レビューで何を確認するか、チェックリストの形で整理しておきます。
| # | チェック項目 | 防ぎたい問題 |
|---|---|---|
| 1 | 各要件は全体目標と整合しているか | 目的と無関係な機能の混入 |
| 2 | 適切な抽象度で記述されているか | 詳細すぎ・抽象すぎによる誤解 |
| 3 | 本当に必要な要件か | 不要な機能の実装 |
| 4 | 限定的かつ曖昧でないか | 解釈のばらつき |
| 5 | 各要件に出典(人物)が紐づいているか | 後で確認できなくなる事態 |
| 6 | 他の要件と矛盾していないか | 実装段階での衝突 |
| 7 | 技術的に実現可能か | 実装途中で頓挫 |
| 8 | テスト可能か | 受け入れ判定ができない |
| 9 | 情報・機能・振る舞いが正しく反映されているか | モデル化の漏れ |
| 10 | 段階的に詳細化される構造になっているか | 全体像の見通し悪化 |
| 11 | 分析パターンが活用され、顧客要件と整合しているか | 既存知見の再利用機会の見逃し |
「ユーザーフレンドリーであること」のような曖昧な要件は、
このステップで検証可能な形に具体化されることが多いです。
ただし、「不正アクセス成功確率が0.0001未満」のような数値が入っていても、
テストに膨大なコストがかかる場合もあります。
そのときは、パスワード保護やハンドシェイキングといった補完的な要件で代替できないかを検討する余地があります。
「テストできるか」「ソースをたどれるか」あたりが、
レビューで効きやすい観点だと感じています。
要件は変わり続ける ── モニタリングとトレーサビリティ
全員が合意したとしても、要件は変わります。
変わることを前提に、変更を管理する仕組みが必要です。
要件のモニタリングには5つのタスクがあります。
[ 要件モニタリングの5つのタスク ]
(1) 分散デバッグ : エラーの発見と原因特定
(2) 実行時検証 : ソフトウェアが仕様に合致しているかの確認
(3) 実行時妥当性確認 : ソフトウェアがユーザー目標を満たしているかの確認
(4) ビジネス活動モニタリング : ビジネス目標の達成度の評価
(5) 進化と共同設計 : システムの進化に応じたステークホルダーへの情報提供
(2)実行時検証と(3)実行時妥当性確認は似ていますが、観点が違います。
検証は「仕様通りに動いているか」、
妥当性確認は「ユーザーの目標を満たしているか」を見ます。
仕様通りでも目標を満たさないことはありえますし、その逆もあります。
もう一つ重要な仕組みが「トレーサビリティ」
── 要件と他の成果物(設計、テスト等)のつながりを追跡できること ── です。
実装で使うのが「トレーサビリティマトリクス」です。
[ トレーサビリティマトリクスの例 ]
| 設計要素A | 設計要素B | テストケース1 | テストケース2 |
----------------+-----------+-----------+---------------+---------------+
要件 R-001 | ○ | | ○ | |
要件 R-002 | | ○ | | ○ |
要件 R-003 | ○ | ○ | ○ | ○ |
行に要件名、列に成果物名を配置し、リンクの有無をマークします。
これで「この要件がどの設計に反映され、
どのテストで確認されるか」が一目で分かります。
もちろん、要件数が増えるとマトリクスの維持はそれなりに大変です。
完璧なマトリクスを保ち続けるより、
要件の影響と進化を追跡する手段を何らかの形で確保することが大事だと考えています。
要件管理は、コードのバージョン管理(構成管理)と密接に関連します。
要件もコードと同じように、変更を追跡し、バージョンを管理する対象だ、と捉えるのが自然です。
4つの問いと7つのタスク ── 全体像の俯瞰
ここまで4つの問いに沿って要件エンジニアリングの技法を見てきました。
最後に、これらの活動を「7つのタスク」という別の切り口から見直して、
全体像を頭に入れます。
要件エンジニアリングには、伝統的に7つのタスクが定義されています。
- inception(開始): 問題の基本理解と関係者の特定
- elicitation(引き出し): ステークホルダーから要件を引き出す
- elaboration(精緻化): 要件をモデルとして詳細化する
- negotiation(交渉): 優先度や制約を調整する
- specification(仕様化): 要件を文書・モデル・プロトタイプとして表現する
- validation(妥当性確認): 成果物が本当に正しいかを確認する
- management(管理): 要件の変化を追跡し制御する
これらと4つの問いの対応を整理すると、次のようになります。
7つのタスクは明確に区切られるものではなく、境界は曖昧で、並行して進むことが多いものです。
設計中に要件が見つかることもありますし、要件の精緻化中に設計のヒントが得られることもあります。
重要なのは、これらのタスクが全て反復的に実行されるということです。
プロジェクトの進行に伴ってステークホルダーと情報を共有し、理解を更新し続ける ── その繰り返しが要件エンジニアリングの実体だと感じています。
おわりに ── モデリングは「理解を揃える」ためにある
要件エンジニアリングは「正確な仕様書を書くこと」が目的ではありません。
複数のステークホルダーの頭の中にある曖昧で矛盾した「欲しいもの」のイメージを、
チーム全員が共有できる形に整理するプロセスです。
ユースケース、クラス図、状態図、シーケンス図といった分析モデルは、
そのための道具であって、目的そのものではありません。
使わないモデルは作らなくてよい、と割り切ることで、
モデリングが目的化する罠を避けられます。
最後に、ここまでの整理を通じて自分のなかで残った学びを並べておきます。
- 要件の精度は、モデルの完璧さではなく、ステークホルダーとの対話の質で決まる
- 分析モデルは「ある時点のスナップショット」であり、完璧を求めて止まるより、設計の土台として十分な精度が得られたら次に進むほうが現実的
- 要件モデルは設計のインプットになるだけでなく、完成後のテストで品質を評価する基準にもなる
立派な仕様書を書いても、関係者の理解がズレていたら同じものは作れません。
逆に、シンプルな図でも理解が揃っていれば前に進めます。
要件エンジニアリングは「上流」で完結する仕事ではなく、
開発のあらゆる局面と地続きの活動だ、というのが今の自分の理解です。
