ストーリー
非機能要件とは何か
非機能要件(NFR: Non-Functional Requirements)は、システムがどのように動作すべきかを定義する要件です。機能要件が「何をするか」を記述するのに対し、非機能要件は「どのように実現するか」の品質を規定します。
機能要件と非機能要件の違い
| 観点 | 機能要件 | 非機能要件 |
|---|---|---|
| 定義 | システムが何をすべきか | システムがどのように動くべきか |
| 例 | ユーザーがログインできる | ログインは2秒以内に完了する |
| 発見方法 | ユーザーストーリー、ユースケース | 品質属性シナリオ、SLA定義 |
| テスト方法 | 機能テスト | 負荷テスト、セキュリティ診断 |
| 影響範囲 | 特定の機能 | システム全体のアーキテクチャ |
NFR分類体系(ISO 25010)
非機能要件は国際規格 ISO 25010 で体系的に分類されています。これを基にした実践的な分類を見ていきましょう。
8大カテゴリ
graph TD
NFR["非機能要件(NFR)"]
A["パフォーマンス<br/>Performance"]
B["スケーラビリティ<br/>Scalability"]
C["可用性<br/>Availability"]
D["セキュリティ<br/>Security"]
E["保守性<br/>Maintainability"]
F["ユーザビリティ<br/>Usability"]
G["移植性<br/>Portability"]
H["コンプライアンス<br/>Compliance"]
NFR --> A
NFR --> B
NFR --> C
NFR --> D
NFR --> E
NFR --> F
NFR --> G
NFR --> H
classDef titleStyle fill:#2c5f8a,stroke:#1a3d5c,color:#fff
classDef catStyle fill:#4a90d9,stroke:#2c5f8a,color:#fff
class NFR titleStyle
class A,B,C,D,E,F,G,H catStyle
各カテゴリの詳細
| カテゴリ | 説明 | 代表的な指標 |
|---|---|---|
| パフォーマンス | 応答速度、スループット、リソース効率 | レイテンシ、TPS、CPU使用率 |
| スケーラビリティ | 負荷増大への対応能力 | 最大同時接続数、水平スケール倍率 |
| 可用性 | システムが利用可能な時間の割合 | SLA(99.9%)、MTTR、MTBF |
| セキュリティ | 不正アクセスやデータ漏洩からの保護 | 脆弱性数、暗号化カバー率 |
| 保守性 | 変更・修正のしやすさ | コード変更のリードタイム、デプロイ頻度 |
| ユーザビリティ | ユーザーにとっての使いやすさ | タスク完了率、エラー率 |
| 移植性 | 異なる環境への移行のしやすさ | 対応プラットフォーム数 |
| コンプライアンス | 法規制・業界標準への準拠 | 準拠基準数、監査通過率 |
なぜNFRは忘れられるのか
「NFRが重要なのは分かりましたが、なぜ現場ではよく忘れられるんですか?」
「いくつか構造的な理由がある」と佐藤CTOが指摘しました。
NFRが見落とされる5つの理由
1. 暗黙の期待として存在する
// ユーザーストーリーにはこう書かれる
// 「ユーザーとして、商品を検索できる」
//
// しかし、以下は書かれない:
// - 検索結果は0.5秒以内に返す
// - 1万人が同時検索しても動作する
// - 検索クエリはSQLインジェクションに耐える
// → これらは「当たり前」だと思われている
2. ステークホルダーが技術に詳しくない
ビジネス側は「速くて安全で落ちない」ことを望むが、具体的な数値(99.99%のSLA、100msのレイテンシ)として表現できないことが多い。
3. 開発初期には問題が顕在化しない
| フェーズ | ユーザー数 | NFR問題 |
|---|---|---|
| 開発・テスト | 数人 | 表面化しない |
| ベータリリース | 数百人 | 軽微な遅延 |
| 正式リリース | 数万人 | パフォーマンス崩壊 |
| 急成長期 | 数十万人 | システム全体がダウン |
4. 機能要件に比べてテストが難しい
5. コストが見えにくい
「99.9%の可用性」と「99.99%の可用性」のコスト差を正確に見積もるのは困難。
NFR無視が引き起こした実際の失敗事例
事例1: パフォーマンス未定義 — ECサイトのセール
graph TD
A["状況: 大規模セール開始"] --> B["問題: NFRとして
パフォーマンス要件を定義していなかった"]
B --> C["結果: 通常の50倍のアクセスが殺到"]
C --> D["DBのコネクションプール枯渇"]
C --> E["APIレスポンスが30秒以上に"]
C --> F["最終的にシステム全体がダウン"]
D & E & F --> G["損失: 推定売上の70%を喪失"]
classDef startStyle fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e40af
classDef problemStyle fill:#fef3c7,stroke:#d97706,stroke-width:2px,color:#92400e
classDef resultStyle fill:#fee2e2,stroke:#dc2626,color:#991b1b
classDef lossStyle fill:#1e293b,stroke:#475569,color:#f8fafc
class A startStyle
class B problemStyle
class C,D,E,F resultStyle
class G lossStyle
事例2: セキュリティ要件の曖昧さ — 個人情報漏洩
状況: 「セキュリティは万全に」という曖昧な要件のみ
↓
問題: 暗号化範囲、アクセス制御の粒度が未定義
↓
結果: APIの認可チェックに漏れがあり、
他ユーザーの個人情報が閲覧可能に
↓
損失: 信頼失墜、法的対応コスト、ユーザー離脱
事例3: スケーラビリティ未考慮 — スタートアップの急成長
状況: MVPで単一サーバー構成
↓
問題: 「あとでスケールさせる」と先送り
↓
結果: セッションをローカルメモリに保存
ファイルアップロードをローカルディスクに保存
DBスキーマがシャーディング不可能な設計
↓
損失: アーキテクチャの全面的な作り直しが必要に(6ヶ月遅延)
隠れたNFRを発見する方法
「では、どうやってNFRを漏れなく洗い出すんですか?」
「いくつかの定番テクニックがある」と佐藤CTOが答えました。
テクニック1: カテゴリ別質問リスト
各カテゴリについて、ステークホルダーに具体的な質問をします。
// NFR発見のための質問フレームワーク
interface NFRDiscoveryQuestion {
category: string;
questions: string[];
}
const discoveryQuestions: NFRDiscoveryQuestion[] = [
{
category: 'パフォーマンス',
questions: [
'ユーザーが許容できる最大待ち時間は?',
'ピーク時に1秒あたり何リクエストを処理する?',
'バッチ処理の完了期限はいつまで?',
],
},
{
category: 'スケーラビリティ',
questions: [
'1年後のユーザー数の予測は?',
'データ量は年間どの程度増加する?',
'急激なアクセス増(バースト)は想定される?',
],
},
{
category: '可用性',
questions: [
'システムが停止した場合のビジネスインパクトは?',
'計画メンテナンスの許容時間は?',
'災害時の復旧目標は?',
],
},
{
category: 'セキュリティ',
questions: [
'扱うデータの機密レベルは?',
'準拠すべき法規制はあるか?',
'外部からのアクセスはあるか?',
],
},
];
テクニック2: ユーザーシナリオの拡張
機能要件のユーザーストーリーに「品質属性」を追加します。
[元のストーリー]
ユーザーとして、商品を検索できる
[NFR拡張版]
ユーザーとして、商品を検索できる
かつ、検索結果は0.5秒以内に表示される(パフォーマンス)
かつ、1万人の同時検索に耐える(スケーラビリティ)
かつ、検索クエリによるインジェクション攻撃を防ぐ(セキュリティ)
かつ、検索サービスが停止しても他の機能は使える(可用性)
テクニック3: 過去のインシデントレビュー
類似システムの障害事例を分析し、NFRとして定義すべき項目を洗い出します。
テクニック4: 利害関係者マッピング
エンドユーザー → パフォーマンス、ユーザビリティ
運用チーム → 可用性、保守性、監視性
セキュリティチーム → セキュリティ、コンプライアンス
経営層 → コスト効率、スケーラビリティ
法務 → コンプライアンス、データ保護
NFRドキュメントテンプレート
NFRは曖昧さを排除し、計測可能な形で記述することが重要です。
テンプレート構造
interface NFRDocument {
id: string; // 一意な識別子
category: NFRCategory;
title: string;
description: string;
metric: {
measure: string; // 何を計測するか
target: string; // 目標値
current?: string; // 現在値(既存システムの場合)
};
priority: 'MUST' | 'SHOULD' | 'COULD';
rationale: string; // この要件が必要な理由
testMethod: string; // 検証方法
tradeoffs: string[]; // トレードオフ
}
type NFRCategory =
| 'PERFORMANCE'
| 'SCALABILITY'
| 'AVAILABILITY'
| 'SECURITY'
| 'MAINTAINABILITY'
| 'USABILITY'
| 'PORTABILITY'
| 'COMPLIANCE';
記述例
## NFR-001: API応答時間
| 項目 | 内容 |
|------|------|
| カテゴリ | パフォーマンス |
| 説明 | 主要APIのレスポンスタイム |
| 指標 | 95パーセンタイルのレイテンシ |
| 目標値 | 200ms以内 |
| 優先度 | MUST |
| 根拠 | ユーザー調査で3秒以上の待ちは離脱率50%増 |
| 検証方法 | 負荷テスト(k6、Locust) |
| トレードオフ | キャッシュ導入によるデータ鮮度の低下 |
良いNFRと悪いNFRの比較
| 悪い例 | 良い例 |
|---|---|
| 「システムは速くなければならない」 | 「商品一覧APIは95%タイルで200ms以内」 |
| 「高い可用性を実現する」 | 「月間稼働率99.9%(月間ダウンタイム43分以内)」 |
| 「セキュリティを確保する」 | 「OWASP Top 10の脆弱性がゼロ」 |
| 「将来の成長に対応する」 | 「現在の10倍のトラフィックに30分以内にスケール可能」 |
NFRの優先順位付け
すべてのNFRを最高レベルで満たすことは、コスト的に現実的ではありません。優先順位付けが重要です。
MoSCoW法によるNFR優先度分類
| 分類 | 説明 | 例 |
|---|---|---|
| Must | 必須。これがないとリリースできない | データ暗号化、基本的なSLA |
| Should | 重要。可能な限り満たすべき | 高可用性、詳細な監視 |
| Could | あれば望ましい。余裕があれば実装 | 多言語対応、高度な分析 |
| Won’t | 今回は対象外。次フェーズ以降で検討 | マルチリージョン展開 |
NFR間のトレードオフ
パフォーマンス ←→ セキュリティ
暗号化処理はレイテンシを増加させる
スケーラビリティ ←→ 一貫性
分散システムはデータ一貫性の保証が困難(CAP定理)
可用性 ←→ コスト
冗長化はインフラコストを増加させる
保守性 ←→ パフォーマンス
抽象化レイヤーの追加はオーバーヘッドを生む
まとめ
| ポイント | 内容 |
|---|---|
| NFRの定義 | システムが「どのように」動作すべきかを定義する品質要件 |
| 8大カテゴリ | パフォーマンス、スケーラビリティ、可用性、セキュリティ、保守性、ユーザビリティ、移植性、コンプライアンス |
| 見落とされる理由 | 暗黙の期待、技術的な表現の難しさ、初期段階での非顕在化 |
| 発見方法 | カテゴリ別質問、ユーザーシナリオ拡張、インシデントレビュー |
| 記述のコツ | 計測可能・検証可能な形で具体的に記述する |
チェックリスト
- 非機能要件と機能要件の違いを説明できる
- NFRの8大カテゴリを列挙できる
- NFRが見落とされる構造的な理由を理解した
- 隠れたNFRを発見するテクニックを3つ以上挙げられる
- 計測可能なNFRの書き方を理解した
次のステップへ
NFRの全体像を把握できたところで、次は個別のカテゴリを深掘りしていきます。まずは「スケーラビリティとパフォーマンス」から。システムの成長にどう備えるか、具体的な設計パターンとメトリクスを学びましょう。
推定読了時間: 30分