✍️

C4モデル

2022/06/28に公開

はじめに

株式会社エヌ・エイ・シーの高橋です。
ソフトウェアアーキテクチャを表現するための色々図はあるけど、ルールが多くて書くのも読むのもだるかったりしますよね。
C4モデル使ってコミュニケーション取ったら結構いい感じだったので、今回はその紹介です。

C4モデルとは

  • ソフトウェアアーキテクチャを表現するための表記法
  • UML4+1アーキテクチャビューモデルが元になっている
    • UML
      • 統一モデリング言語
      • 表現できる図も豊富だし、表記ルールも豊富
    • 4+1アーキテクチャビューモデル
      • 4つの視座(利用者,プログラム開発者,システムエンジニア,インテグレータ)+小規模なユースケースでソフトウェアアーキテクチャを表現する

解決すること

  • ソフトウェアアーキテクチャを表現する図を見ると同じような問題をよく見かける
    • 一貫性のない表記のせいで余計混乱する
    • 色分けが謎
    • 抽象度がグチャグチャ
    • 図の中の色々な箱が何を示しているかが謎
    • 箱と箱の間を結ぶ線が関係を示しているんだろうけど、何を意味しているか分からない
    • UMLは統一的な表記ルールを決めているけど、ルールが多すぎてパパッと書けないから結局使わなくなることが多い
    • etc…
  • 解決法として
    • 抽象化レベルと図の種類を少なくして、とっつきやすくした
    • Google Mapsで興味のある地域を拡大したり縮小したりするように、ソフトウェアアーキテクチャを表現した
      c4-overview

表現するもの

ソフトウェアシステムの階層化された構成要素を書く。

  • ソフトウェアシステムの構成要素を抽象化すると次の4つの要素が階層関係になっていることがわかる
    abstractions
    • ソフトウェアシステムは1つ以上のコンテナ(Webアプリケーション/モバイルアプリケーション/デスクトップアプリケーション/データベース/ファイルシステムなど)で構成され
    • それらが1つ以上のコンポーネントを含み
    • さらにそれらは1つ以上のコード(クラス、インタフェース、オブジェクト、関数など)で実装されている
  • 構成要素のざっくり説明
    • ソフトウェアシステム
      • ユーザー(人間であるかどうかにかかわらない)に価値を提供するもの
    • コンテナ
      • ソフトウェアシステム全体が動作するために実行される必要があるもの
      • アプリケーションやデータストアの境界を指す
    • コンポーネント
      • 明確に定義されたインタフェースの背後にカプセル化された関連機能のグループのことを指す
      • JavaやC#などの言語を使用している場合、コンポーネントを考える最も簡単な方法は、インタフェースの背後にある実装クラスの集合体と捉える
  • 構成要素の階層関係を表現するのがC4モデル
    c4-overview
      1. システムコンテキスト図
      • 出発点となる図
      • 対象となるソフトウェアシステムと周囲のソフトウェアシステム、ユーザーとの関連を示す
      1. コンテナ図
      • 対象となるソフトウェアシステムにズームインし、高レベルの技術的な構成要素を示す
      1. コンポーネント図
      • 個々のコンテナにズームインし、その中のコンポーネントを示す
      1. コード図
      • UMLのクラス図等を使用して個々のコンポーネントがどのように実装されているかを示す

書き方

1. システムコンテキスト図

bigbankplc-SystemContext

  • この図の役割
    • 全体を俯瞰できる
    • 人と外部のソフトウェアシステムに焦点が当たっている
  • 表現しない情報
    • 技術やプロトコルなどの低レベルな技術要素に関する情報
  • 対象となる読者
    • ソフトウェア開発チーム内外の技術者、非技術者を問わず、全員
  • 作るべきか
    • Yes

2.コンテナ図

bigbankplc-SystemContext

  • この図の役割
    • ソフトウェアシステムのざっくりとした構成が俯瞰できる
    • 次の3つが理解できる
      • ソフトウェアシステムが選択した主要な技術
      • 複数のコンテナの責務
      • コンテナ同士の通信
  • 表現しない情報
    • デプロイメントシナリオ
    • クラスタリング
    • レプリケーション
    • フェイルオーバー etc…
  • 対象となる読者
    • ソフトウェア開発チーム内外の技術者(ソフトウェアアーキテクト、開発者、運用・サポートスタッフなど)
  • 作るべきか
    • Yes

3.コンポーネント図

bigbankplc-Components

  • この図の役割
    • コンテナの主要な構成要素が俯瞰できる
    • 次の3つが理解できる
      • 複数のコンポーネントの責務
      • コンポーネント同士の通信
      • 技術/実装の詳細
  • 対象となる読者
    • ソフトウェア設計者、開発者
  • 作るべきか
    • コンテナが複雑だったら作ってもいいかも
    • メンテナンスコストがかかるので長いこと保守してくなら自動を検討した方が良い

4.コード図

bigbankplc-Classes

  • この図の役割
    • どのように実装されているかを、UMLのクラス図や実体関係図などで理解できる
    • 最も重要なコンポーネントや複雑なコンポーネントがどう実装されているか理解できる
  • 対象となる読者
    • ソフトウェア設計者、開発者
  • 作るべきか
    • No
    • メンテナンスコストがかかりすぎるので、自動化は必須

利用していて得た学び

🙅‍♀️ 線をいいかんじに書こうとしすぎない

  • メンテナンスコストが激増する、ざっくり見やすければそれでよし
  • コンテナ図以降は時間が経つにつれ結構変化していく、メンテナンスの機会は結構多い

意識すること

全般

  • 図の種類と範囲を説明するタイトルが必要
    • その四角の囲いは何を意味しているか
    • このシステムコンテキスト図は何を示しているか
  • 使用されている表記法(図形、色、枠線、線種、矢印など)を説明するキーや凡例が必要
    • いきなり紫色の矢印があちこちに書かれ始めたら混乱しちゃうよね
  • 略語(ビジネス/ドメインまたはテクノロジー)は読み手が理解できるようにするか、凡例で説明する必要がある
    • あなたが知っている言葉を誰もが知ってると思っちゃいけない

要素を書く時

  • 要素の種類は明示的に指定すること
    • Person,Software System,Container,Component etc…
    • 見た目がかっこいいアイコンを並べまくっても、悪夢みたいな図しかできなくなる
  • 要素には簡単な説明をつけ、主要な責任を「一目でわかる」ようにすること
  • すべてのコンテナとコンポーネントは、採用した技術を明示的に指定すること

関係を書く時

  • 要素と要素の繋ぎ方に明確なルールは無い。分かりやすが一番大事
  • 「AがBのAPIを呼び出すー」のように声に出して読んでみるといい、読めないものは何かが間違っている
  • 関係の方向性や意図(依存関係やデータフローなど)と一致するように、すべての線にラベル付ける必要がある
  • ラベルは「利用」のような単一単語は避け、できるだけ具体的に書くようにすること
すべての線は一方向の関係を表す必要がある
  • リクエストとレスポンスは本来双方向の通信が生じるので、ちゃんと書こうとするとこんな感じになる
    lines-two-way
  • 冗長で複雑になるので線は一方向にしたほうがわかりやすい
    lines-one-way
  • もちろん例外もあって単純なリクエスト/レスポンスを超えた意味を表現する場合とかは、こんな風にかくとわかりやすい
    lines-exception
  • have & spokeな図を書く時も線の書き方に注意
    lines-hava_and_spoke-bad
  • この図では「誰がどこに何をしたいか」が大事なので、こうしてみたらいいかも
    lines-hava_and_spoke-good

参考

Discussion