LESSON 30分

ストーリー

あなた
要件定義書に”高い可用性”って書いてあるんですが、これをもとにアーキテクチャを決めてよいですか?

佐藤CTOは首を横に振りました。

佐藤CTO
“高い可用性”は要件ではない。願望だ。99.9%と99.99%ではダウンタイムが10倍違い、実現コストは数倍違う。“速い”も”安全”も同じ。曖昧な品質要件は、曖昧なアーキテクチャを生む
あなた
では、どうすれば…
佐藤CTO
品質属性シナリオを書くんだ。“誰が”、“どんな状況で”、“何をしたとき”、“システムはどう振る舞い”、“どう測定するか”。これを定義できれば、アーキテクチャの判断基準が明確になる

ISO 25010 品質モデル

まず、品質属性の全体像を把握しましょう。ISO 25010はソフトウェア品質を8つのカテゴリに分類しています。

// ISO 25010 品質モデル
interface ISO25010QualityModel {
  機能適合性: {
    説明: "要求された機能を正しく提供する度合い";
    副特性: ["機能完全性", "機能正確性", "機能適切性"];
  };
  性能効率性: {
    説明: "使用リソースに対するパフォーマンスの度合い";
    副特性: ["時間効率性", "資源効率性", "容量満足性"];
  };
  互換性: {
    説明: "他のシステムと情報交換・共存できる度合い";
    副特性: ["共存性", "相互運用性"];
  };
  使用性: {
    説明: "ユーザーが効率的・満足的に使える度合い";
    副特性: ["適切度認識性", "習得性", "運用操作性", "誤使用防止性"];
  };
  信頼性: {
    説明: "指定条件下で機能を維持する度合い";
    副特性: ["成熟性", "可用性", "障害許容性", "回復性"];
  };
  セキュリティ: {
    説明: "情報とデータを保護する度合い";
    副特性: ["機密性", "完全性", "否認防止性", "責任追跡性", "真正性"];
  };
  保守性: {
    説明: "修正の容易さの度合い";
    副特性: ["モジュール性", "再利用性", "解析性", "修正性", "試験性"];
  };
  移植性: {
    説明: "異なる環境に移行できる度合い";
    副特性: ["適応性", "設置性", "置換性"];
  };
}

アーキテクチャに特に影響する品質属性

すべての品質属性が等しくアーキテクチャに影響するわけではありません。以下の6つは特にアーキテクチャ設計を左右します。

品質属性なぜアーキテクチャに影響するか典型的なトレードオフ
パフォーマンスキャッシュ、非同期処理、データ配置などの構造決定が必要パフォーマンス vs 保守性
スケーラビリティサービス分割、ステートレス設計、データ分散が必要スケーラビリティ vs 一貫性
可用性冗長化、フェイルオーバー、障害分離が必要可用性 vs コスト
セキュリティ認証認可、暗号化、ネットワーク分離が必要セキュリティ vs 使用性
保守性モジュール分割、デプロイ戦略、テスト戦略が必要保守性 vs パフォーマンス
デプロイ容易性CI/CD、コンテナ化、ゼロダウンタイムデプロイが必要デプロイ頻度 vs 安定性

品質属性シナリオの書き方

シナリオの6つの要素

品質属性シナリオは、曖昧な要件を測定可能で検証可能な形に変換するフレームワークです。

// 品質属性シナリオの構造
interface QualityAttributeScenario {
  source: string;       // 刺激源:誰が/何が
  stimulus: string;     // 刺激:何をしたとき
  environment: string;  // 環境:どんな条件下で
  artifact: string;     // 成果物:対象のシステム/コンポーネント
  response: string;     // 応答:システムはどう振る舞うか
  measure: string;      // 測定値:どう測定するか
}

具体例:パフォーマンスシナリオ

// 曖昧な要件:「検索は速くしてほしい」
// ↓ 品質属性シナリオに変換

const performanceScenario: QualityAttributeScenario = {
  source: "エンドユーザー",
  stimulus: "商品検索リクエストを送信する",
  environment: "通常運用時(平日日中、同時接続10,000ユーザー)",
  artifact: "商品検索API",
  response: "検索結果(上位20件)を返却する",
  measure: "p99レイテンシが200ms以下",
};

具体例:可用性シナリオ

// 曖昧な要件:「システムは落ちないようにしてほしい」
// ↓ 品質属性シナリオに変換

const availabilityScenario: QualityAttributeScenario = {
  source: "ハードウェア障害",
  stimulus: "データベースの1台がクラッシュする",
  environment: "通常運用時",
  artifact: "注文処理システム",
  response: "フェイルオーバーによりスタンバイDBに切り替わり、処理を継続する",
  measure: "切り替え時間が30秒以内、年間稼働率99.99%以上",
};

具体例:セキュリティシナリオ

// 曖昧な要件:「セキュリティを強化してほしい」
// ↓ 品質属性シナリオに変換

const securityScenario: QualityAttributeScenario = {
  source: "認証されていない外部ユーザー",
  stimulus: "他のユーザーの個人情報にアクセスしようとする",
  environment: "通常運用時",
  artifact: "ユーザーAPI",
  response: "リクエストを拒否し、監査ログに記録し、管理者にアラートを送信する",
  measure: "不正アクセスの100%がブロックされ、検知から通知まで1分以内",
};

具体例:スケーラビリティシナリオ

// 曖昧な要件:「将来的にユーザーが増えても大丈夫にしてほしい」
// ↓ 品質属性シナリオに変換

const scalabilityScenario: QualityAttributeScenario = {
  source: "マーケティングキャンペーン",
  stimulus: "通常の10倍のトラフィックが発生する",
  environment: "セール期間中(事前に予測可能)",
  artifact: "ECプラットフォーム全体",
  response: "オートスケーリングにより自動でキャパシティを増強する",
  measure: "スケールアウト完了まで5分以内、p99レイテンシは通常時の2倍以内",
};

品質属性ツリー

品質属性シナリオを体系的に整理するためのツールが品質属性ツリーです。

graph TD
    Root["品質属性ツリー
[重要度, 難易度] H=高, M=中, L=低"] Root --- Perf["性能"] Root --- Avail["可用性"] Root --- Sec["セキュリティ"] Root --- Maint["保守性"] Root --- Scale["スケーラビリティ"] Perf --- P1["検索API
[H,H]"] Perf --- P2["注文API
[H,M]"] Perf --- P3["画像配信
[M,M]"] Avail --- A1["DB障害
[H,H]"] Avail --- A2["AZ障害
[H,M]"] Sec --- S1["認証認可
[H,H]"] Sec --- S2["暗号化
[H,M]"] Maint --- M1["通知モジュール
[M,L]"] Maint --- M2["コード分析
[M,M]"] Maint --- M3["デプロイ
[H,M]"] Scale --- Sc1["垂直
[M,M]"] Scale --- Sc2["水平
[H,H]"] Scale --- Sc3["DBスケール
[M,H]"] classDef rootStyle fill:#1e293b,stroke:#475569,color:#f8fafc classDef catStyle fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e40af classDef leafStyle fill:#d1fae5,stroke:#059669,color:#065f46 class Root rootStyle class Perf,Avail,Sec,Maint,Scale catStyle class P1,P2,P3,A1,A2,S1,S2,M1,M2,M3,Sc1,Sc2,Sc3 leafStyle
// 品質属性ツリーのデータ構造
interface QualityAttributeTree {
  attribute: string;
  refinements: {
    name: string;
    scenarios: QualityAttributeScenario[];
    importance: "H" | "M" | "L";
    difficulty: "H" | "M" | "L";
  }[];
}

const performanceTree: QualityAttributeTree = {
  attribute: "性能効率性",
  refinements: [
    {
      name: "検索APIのレイテンシ",
      scenarios: [/* performanceScenario */],
      importance: "H",
      difficulty: "H",
    },
    {
      name: "注文APIのレイテンシ",
      scenarios: [/* orderPerformanceScenario */],
      importance: "H",
      difficulty: "M",
    },
    {
      name: "画像配信のレイテンシ",
      scenarios: [/* imagePerformanceScenario */],
      importance: "M",
      difficulty: "M",
    },
  ],
};

品質属性の優先順位付け

すべての品質属性を最高レベルで実現することは不可能です。トレードオフが必ず存在します。

優先順位付けの手法

1. 品質属性ワークショップ(QAW)

ステークホルダーを集めて品質属性シナリオを洗い出し、投票で優先順位をつける手法です。

// QAWの結果例
interface QAWResult {
  scenario: string;
  votes: number;  // ステークホルダーの投票数
  priority: "必須" | "重要" | "あれば良い";
}

const qawResults: QAWResult[] = [
  { scenario: "注文処理の可用性 99.99%",       votes: 12, priority: "必須" },
  { scenario: "検索API p99 < 200ms",           votes: 10, priority: "必須" },
  { scenario: "個人情報の暗号化",              votes: 10, priority: "必須" },
  { scenario: "ピーク時10倍のスケーリング",    votes: 8,  priority: "重要" },
  { scenario: "新機能の週次デプロイ",          votes: 7,  priority: "重要" },
  { scenario: "障害時のRTO < 5分",             votes: 6,  priority: "重要" },
  { scenario: "マルチリージョン対応",          votes: 3,  priority: "あれば良い" },
];

2. トレードオフマトリックス

品質属性間のトレードオフを明示化します。

品質属性パフォーマンススケーラビリティ可用性セキュリティ保守性
パフォーマンス相反する場合あり独立相反相反
スケーラビリティ相反する場合あり相乗効果独立相反する場合あり
可用性独立相乗効果独立相乗効果
セキュリティ相反独立独立相反する場合あり
保守性相反相反する場合あり相乗効果相反する場合あり

「パフォーマンスを極限まで追求すると、キャッシュの多段化やデータの非正規化が必要になり、保守性が犠牲になる。セキュリティを厳しくすると、認証・認可のオーバーヘッドでパフォーマンスが落ちる。すべてを最高にすることはできない。だからこそ、優先順位が必要なんだ」 — 佐藤CTO


品質属性シナリオの実践テンプレート

実務で品質属性シナリオを書く際のテンプレートです。

// 実務テンプレート
interface PracticalQAScenario {
  id: string;                      // 一意の識別子
  qualityAttribute: string;        // 対象の品質属性
  scenario: {
    source: string;
    stimulus: string;
    environment: string;
    artifact: string;
    response: string;
    measure: string;
  };
  priority: "必須" | "重要" | "あれば良い";
  architecturalTactic: string;     // 実現するためのアーキテクチャ戦術
  verificationMethod: string;      // 検証方法
}

// テンプレートの使用例
const qa001: PracticalQAScenario = {
  id: "QA-001",
  qualityAttribute: "可用性",
  scenario: {
    source: "サーバーハードウェア",
    stimulus: "アプリケーションサーバー1台がダウン",
    environment: "通常運用時、ピーク時間帯",
    artifact: "注文処理サービス",
    response: "ロードバランサーが異常を検知し、トラフィックを健全なサーバーに転送",
    measure: "ユーザー影響なし(ダウンタイム0秒)、年間稼働率99.99%",
  },
  priority: "必須",
  architecturalTactic: "冗長化 + ヘルスチェック + 自動フェイルオーバー",
  verificationMethod: "カオスエンジニアリング(サーバー停止テスト)",
};

まとめ

ポイント内容
ISO 25010品質を8カテゴリに体系化した国際標準
品質属性シナリオ6要素(刺激源、刺激、環境、成果物、応答、測定値)で品質を定量化
品質属性ツリーシナリオを体系的に整理し、重要度と難易度を可視化
トレードオフすべてを最高にはできない。優先順位付けが必須
QAWステークホルダーの合意に基づく優先順位決定手法

チェックリスト

  • ISO 25010 の8つの品質カテゴリを把握した
  • 品質属性シナリオの6要素を理解し、書けるようになった
  • 曖昧な要件を品質属性シナリオに変換できる
  • 品質属性ツリーの作り方を理解した
  • 品質属性間のトレードオフを認識できる

次のステップへ

品質属性を定量化できるようになったところで、次は「要件からアーキテクチャへの変換」を学びます。品質属性シナリオを実現するための**アーキテクチャ戦術(Tactics)**と、要件からアーキテクチャパターンへのマッピング手法を身につけましょう。


推定読了時間: 30分