依存構造マトリクス(DSM)
Dependency Structure Matrix によるコード構成の強化
はじめに
DSM(Dependency Structure Matrix)は、コンポーネント間の依存関係を表現し、ナビゲートするためのコンパクトな方法です。ほとんどのエンジニアにとって、依存関係について話すとは、次のようなものについて話すことを意味します。

DSM はグラフと同じ情報を表現するために使用されます。
- マトリクスヘッダーの要素はグラフのボックスを表します
- マトリックスの空でないセルはグラフの矢印に対応します。
その結果、下のスナップショットでは、次からの結合度が ネット へ Foundation マトリックスの空でないセルとグラフの矢印で表されます。

同じ情報をグラフと DSM の 2 つの異なる方法で表現するのはなぜでしょうか?トレードオフがあるからです:
- グラフはより直感的ですが、ノードとエッジの数が増えるとまったく理解できなくなる可能性があります(数十個のボックスでも複雑すぎるグラフが生成されることがあります)
- DSM は直感的ではありませんが、大規模で複雑なグラフを表現するのに非常に効率的です。DSM は スケール グラフと比較。
DSM の原則を理解すると、通常、依存関係の表現にはグラフよりも DSM が好まれます。これは主に、DSM が次の可能性を提供するためです 構造パターンを一目で把握 これは本ドキュメントの後半で説明します。
CppDependは提供 コンテキストヘルプ DSM に表示されている内容についてユーザーを教育するためです。CppDepend の DSM は、DSM セルの単純な 3 色の配色スキーム(青、緑、黒)に依存しています。マウスで行または列にカーソルを合わせると、コンテキスト依存ヘルプがこの配色スキームの意味を説明します。

空でない DSM セルには数値が含まれます。この数値は、セルが表す結合の強さを表します。結合の強さは、オプションの実際の値に応じて、結合に関与するメンバー/メソッド/フィールド/型または名前空間の数で表すことができます セルの重み コンテキスト センシティブ ヘルプに加えて、DSM は次も提供します 情報パネル 結合度を平易な英語で説明する次のメトリック:

CppDepend の DSM には試せる多数のオプションがあります:
- 依存関係の探索を深掘りするための多数の機能があります(親列/行を開く、セルを展開するなど)
- 正方対称 DSM と長方形の非対称 DSM の両方を扱えます
- 水平ヘッダーと垂直ヘッダーをバインドして、常に正方対称マトリックスにすることができます
- オプションが付属 間接使用、セルは直接および間接使用を示します
- 垂直ヘッダーには階層コード要素を含めることができます
- ...
コード ベースの依存関係を分析して、これらの機能をすべて実際に体験することをお勧めします。
マトリクスでコード構造パターンを特定
はじめに説明したように、DSM には一般的なコード構造パターンを簡単に識別できるという特徴があります。最も一般的なシナリオを紹介しましょう。
レイヤードコード
DSMで明らかになるパターンの1つは レイヤー構造 (つまり非巡回構造)。マトリックスが三角形で、すべての青色のセルが左下の三角形に、すべての緑色のセルが右上の三角形にある場合、構造が完全にレイヤードされていることを示します。言い換えれば、その構造には依存関係サイクルが含まれていません。

スナップショットの右側には、同じレイヤード構造がグラフで表現されています。すべての矢印は左から右への同じ方向を向いています。グラフの問題は、グラフレイアウトがスケールしないことです。ここでは、構造の全体像をかろうじて見ることができます。ボックスの数が 2 倍になると、グラフは完全に読み取れなくなります。一方、DSM 表現は影響を受けません。私たちはこれを DSMはグラフよりスケール.
補足:興味深いことに、ほとんどのグラフレイアウトアルゴリズムは、グラフが非巡回であるという事実に依存しています。サイクルを含むグラフのレイアウトを計算するために、これらのアルゴリズムは一時的に一部の依存関係を破棄してレイヤードグラフを扱い、計算の最終段階で破棄した依存関係を追加します。
依存関係サイクル
構造にサイクルが含まれている場合、そのサイクルは DSM 上に赤い四角形で表示されます。赤い四角形の内部では、緑色と青色のセルが対角線をまたいで混在していることがわかります。また、相互の直接使用(つまり A が B を使用し、B が A を使用する)を表す黒いセルもあります。

CppDepend の DSM には独自のオプションがあります 間接依存関係。A と B の間の間接的な依存関係とは、A が何かを使用し、その何かが何かを使用し、その何かが何かを使用し…それが B を使用していることを意味します。以下は、同じ DSM をサイクルありで間接モードで示したものです。赤い四角形が黒いセルのみで埋められていることがわかります。これは、サイクル内の任意の要素 A と B について、A と B が間接的かつ相互に依存していることを意味するだけです。

ここに同じ構造をグラフで表したものがあります。赤い矢印は、複数の要素が相互に依存していることを示しています。しかし、グラフは親サイクルに関与するすべての要素を強調表示するのには役立ちません。

CppDepend では、DSM 内のサイクル(存在する場合)を強調表示するボタンが提供されていることに注意してください。構造がレイヤードの場合、このボタンはマトリックスを三角化し、空でないセルをできるだけ対角線に近づける効果があります。

高凝集 - 低結合
高凝集性(コンポーネント内)/ 低結合性(コンポーネント間)という考え方は今日広まっています。しかし、依存関係を測定して可視化できなければ、凝集性と結合性の具体的な評価を得るのは困難です。DSM は高い凝集性を示すのが得意です。下の DSM では、対角線の周りに明確な正方形の集合が表示されています。これは、正方形に関わる要素が高い凝集性を持っていること、つまり互いに強く依存していることを意味します。さらに、サイクルがないため、それらがレイヤードされていることもわかります。これらは確かに親の成果物(名前空間やアセンブリなど)にグループ化される候補です。
一方、正方形の周囲のほとんどのセルが空であるという事実は、正方形の要素と他の要素との間の疎結合を示唆しています。

下の DSM では、高い凝集度を持つ 2 つのコンポーネント(上下の正方形)と、それらの間のかなり低い結合度が見られます。

リファクタリングの際、このような指標があると、粗いコンポーネントをより細かい複数のコンポーネントに分割する機会があるかどうかを知るのに非常に役立ちます。
責任が多すぎる
この 単一責任の原則 (SRP) は、現在ソフトウェア アーキテクトのコミュニティで人気が高まっています。この原則は次のとおりです: クラスは変更の理由を 1 つだけ持つべきです。SRP のもう 1 つの解釈は、クラスは他の多くの異なる型を使用すべきではないということです。この考えを他のレベル(アセンブリ、名前空間、メソッド)に拡張すると、コード要素が(同じレベルの)他の数十もの異なるコード要素を使用している場合、そのコード要素は確実に多すぎる責任を持っています。多くの場合、次の用語が ゴッドクラス または ゴッドコンポーネント そのようなコードを評価するために使用されます。
DSM は、責任が多すぎるコード要素を特定するのに役立ちます。このようなコード要素は、青色のセルが多い列と緑色のセルが多い行で表されます。以下の DSM はこの現象を示しています。

人気のコード要素
人気のあるコード要素は、他の多くのコード要素によって使用されます。人気のあるコード要素は避けられません(次を考えてみてください 文字列 たとえばクラス)ですが、人気のあるコード要素は欠陥ではありません。これは、すべてのコードベースには、人気のあるクラスで表現される中心的な概念がいくつかあることを意味するだけです。
人気のあるコード要素は、緑色のセルが多い列と青色のセルが多い行で表されます。以下の DSM は、人気のあるコード要素を強調表示しています。

注目すべき点は、コード構造を完全にレイヤードに保つと、人気のあるコンポーネントは自然に低レベルに保たれるということです。実際、人気のあるコンポーネントは事実上多くのものを使用できません。人気のあるコンポーネントは低レベルであるため、より高いレベルのものを使用できないからです。これは低レベルから高レベルへの依存関係を生み出し、構造の非巡回性を破壊します。
相互依存
空でないセルを右クリックしてメニューを選択すると、2 つのコンポーネント間の結合度を確認できます この依存関係を開く.

上のスナップショットのように、開いたセルが黒だった場合(つまり A と B が相互に依存している場合)、結果の矩形マトリックスには、下のスナップショットのように緑色と青色のセルの両方(および場合によっては黒色のセルも)が含まれます。

この状況では、緑色または青色のセルの不足によく気づくでしょう(ここでは緑色のセル 1 つに対して青色のセル 3 つ)。これは、2 つのコード要素が相互に依存している場合でも、それらの間に自然なレベルの順序が存在することが多いためです。たとえば、次を考えてみましょう System.Threading 名前空間と System.String クラス。これらは相互に依存しています。しかし、マトリックスは次を示しています スレッディング により強く依存 文字列 逆よりも(青いセルが緑のセルよりはるかに多い)。これは次の直感を裏付けています スレッディング より上位 文字列.

