Startseite/Dokumentation/Graphen & Abhängigkeiten/Abhängigkeitsstrukturmatrix (DSM)

Abhängigkeitsstrukturmatrix (DSM)

Einführung

Die DSM (Dependency Structure Matrix) ist eine kompakte Art, Abhängigkeiten zwischen Komponenten darzustellen und durch sie zu navigieren. Für die meisten Ingenieure bedeutet das Sprechen über Abhängigkeiten das Sprechen über etwas, das so aussieht:

Graphbeispiel

DSM wird verwendet, um dieselben Informationen wie ein Graph darzustellen.

  • Matrix-Header-Elemente stellen Graph-Boxen dar
  • Nicht leere Matrixzellen entsprechen den Pfeilen des Graphen.

Folglich ist im Snapshot unten die Kopplung von Netto zu Foundation wird durch eine nicht leere Zelle in der Matrix und einen Pfeil im Graphen dargestellt.

Matrix vs. Graph

Warum zwei verschiedene Wege — Graph und DSM — nutzen, um dieselbe Information darzustellen? Weil es einen Trade-off gibt:

  • Der Graph ist intuitiver, kann aber völlig unverständlich werden, wenn die Anzahl der Knoten und Kanten wächst (ein paar Dutzend Boxen können ausreichen, um einen zu komplexen Graphen zu erzeugen)
  • DSM ist weniger intuitiv, kann aber sehr effizient sein, um große und komplexe Graphen darzustellen. Wir sagen, DSM skaliert mit dem Graphen vergleichen.

Sobald man die DSM-Prinzipien verstanden hat, bevorzugt man typischerweise DSM gegenüber Graphen zur Darstellung von Abhängigkeiten. Dies liegt hauptsächlich daran, dass DSM die Möglichkeit bietet, strukturelle Muster auf einen Blick erkennen Dies wird in der zweiten Hälfte dieses Dokuments erklärt.

CppDepend bietet Kontextsensitive Hilfe um den Benutzer über das aufzuklären, was er auf der DSM sieht. Die DSM von CppDepend basiert auf einem einfachen 3-Farben-Schema für DSM-Zellen: Blau, Grün und Schwarz. Beim Überfahren einer Zeile oder Spalte mit der Maus erklärt die kontextsensitive Hilfe die Bedeutung dieses Farbschemas:

Zeile Spalte

Eine nicht-leere DSM-Zelle enthält eine Zahl. Diese Zahl repräsentiert die Stärke der durch die Zelle dargestellten Kopplung. Die Kopplungsstärke kann als Anzahl der an der Kopplung beteiligten Member/Methoden/Felder/Typen oder Namespaces ausgedrückt werden, abhängig vom tatsächlichen Wert der Option Gewicht auf Zellen Zusätzlich zur kontextsensitiven Hilfe bietet das DSM auch Info-Panel das Kopplung mit einer Beschreibung in einfachem Englisch erklärt:

Zelle

Das DSM von CppDepend bietet zahlreiche Optionen zum Ausprobieren:

  • Es bietet zahlreiche Möglichkeiten, in die Abhängigkeitserkundung einzutauchen (eine übergeordnete Spalte/Zeile kann geöffnet, Zellen können expandiert werden...)
  • Es kann mit quadratischen symmetrischen DSM und rechteckigen nicht-symmetrischen DSM umgehen
  • Horizontale und vertikale Header können gebunden werden, um stets eine quadratische symmetrische Matrix zu erhalten
  • Es bietet die Option Indirekte Verwendung, wobei Zellen direkte und indirekte Verwendung zeigen
  • Der vertikale Header kann Tier-Code-Elemente enthalten
  • ...

Es wird empfohlen, all diese Funktionen selbst auszuprobieren, indem Sie Abhängigkeiten in Ihrer Codebasis analysieren.

Nach oben

Codestrukturmuster auf der Matrix identifizieren

Wie in der Einführung erläutert, bietet DSM die Besonderheit, gängige Codestrukturmuster leicht identifizieren zu können. Lassen Sie uns die häufigsten Szenarien vorstellen:

Geschichteter Code

Ein Muster, das eine DSM offensichtlich macht, ist geschichtete Struktur (d. h. azyklische Struktur). Wenn die Matrix dreieckig ist, mit allen blauen Zellen im unteren linken Dreieck und allen grünen Zellen im oberen rechten Dreieck, dann zeigt dies, dass die Struktur perfekt geschichtet ist. Mit anderen Worten: Die Struktur enthält keinen Abhängigkeitszyklus.

nivelliert

Im rechten Teil des Snapshots ist dieselbe geschichtete Struktur als Graph dargestellt. Alle Pfeile haben dieselbe Richtung von links nach rechts. Das Problem bei Graphen ist, dass das Graph-Layout nicht skaliert. Hier können wir das Gesamtbild der Struktur kaum erkennen. Würde die Anzahl der Boxen verdoppelt, wäre der Graph völlig unlesbar. Die DSM-Darstellung wäre dagegen nicht betroffen; wir sagen, dass DSM skaliert besser als Graph.

Randbemerkung: Interessanterweise beruhen die meisten Graph-Layout-Algorithmen auf der Tatsache, dass ein Graph azyklisch ist. Um das Layout eines Graphen mit Zyklen zu berechnen, verwerfen diese Algorithmen vorübergehend einige Abhängigkeiten, um mit einem geschichteten Graphen zu arbeiten, und fügen die verworfenen Abhängigkeiten im letzten Berechnungsschritt wieder hinzu.

Nach oben

Abhängigkeitszyklus

Wenn eine Struktur einen Zyklus enthält, wird der Zyklus durch ein rotes Quadrat auf der DSM angezeigt. Wir können sehen, dass innerhalb des roten Quadrats grüne und blaue Zellen über die Diagonale gemischt sind. Es gibt auch einige schwarze Zellen, die gegenseitige direkte Nutzung darstellen (d. h. A verwendet B und B verwendet A).

direkter Zyklus

Das DSM von CppDepend bietet die einzigartige Option Indirekte Abhängigkeit. Eine indirekte Abhängigkeit zwischen A und B bedeutet, dass A etwas verwendet, das etwas verwendet, das etwas verwendet ... das B verwendet. Unten ist dieselbe DSM mit einem Zyklus gezeigt, aber im indirekten Modus. Wir sehen, dass das rote Quadrat nur mit schwarzen Zellen gefüllt ist. Das bedeutet lediglich, dass für beliebige Elemente A und B im Zyklus A und B indirekt und gegenseitig abhängig sind.

indirekter Zyklus

Hier ist dieselbe Struktur als Graph dargestellt. Der rote Pfeil zeigt, dass mehrere Elemente gegenseitig voneinander abhängen. Der Graph hilft jedoch nicht dabei, alle am übergeordneten Zyklus beteiligten Elemente hervorzuheben.

Zyklengraph

Beachten Sie, dass wir in CppDepend eine Schaltfläche bereitgestellt haben, um Zyklen in der DSM hervorzuheben (falls vorhanden). Wenn die Struktur geschichtet ist, bewirkt diese Schaltfläche, die Matrix zu triangularisieren und nicht-leere Zellen so nah wie möglich an der Diagonale zu halten.

Matrix triangularisieren

Nach oben

Hohe Kohäsion – geringe Kopplung

Die Idee von hoher Kohäsion (innerhalb einer Komponente) / loser Kopplung (zwischen Komponenten) ist heutzutage populär. Aber wenn man Abhängigkeiten nicht messen und visualisieren kann, ist es schwer, Kohäsion und Kopplung konkret zu bewerten. DSM zeigt hohe Kohäsion sehr gut. In der DSM unten ist ein deutliches quadratisches Aggregat um die Diagonale zu sehen. Es bedeutet, dass die im Quadrat beteiligten Elemente eine hohe Kohäsion haben: Sie sind stark voneinander abhängig. Zudem sehen wir, dass sie geschichtet sind, da es keinen Zyklus gibt. Sie sind sicher Kandidaten, um in ein Eltern-Artefakt (wie einen Namespace oder ein Assembly) gruppiert zu werden.

Andererseits spricht die Tatsache, dass die meisten Zellen um das Quadrat herum leer sind, für eine lose Kopplung zwischen den Elementen des Quadrats und anderen Elementen.

hohe Kohäsion 1

In der DSM unten sehen wir 2 Komponenten mit hoher Kohäsion (oberes und unteres Quadrat) und einer ziemlich niedrigen Kopplung zwischen ihnen.

hohe Kohäsion 2

Beim Refactoring kann ein solcher Indikator sehr nützlich sein, um zu erkennen, ob es Möglichkeiten gibt, grobe Komponenten in mehrere feiner granulierte Komponenten aufzuteilen.

Nach oben

Zu viele Verantwortlichkeiten

Der Single-Responsibility-Prinzip (SRP) erfreut sich heutzutage in der Softwarearchitekten-Community wachsender Beliebtheit. Das Prinzip besagt: eine Klasse sollte nicht mehr als einen Änderungsgrund haben. Eine andere Interpretation des SRP ist, dass eine Klasse nicht zu viele verschiedene andere Typen verwenden sollte. Wenn wir die Idee auf andere Ebenen erweitern (Assemblies, Namespaces und Methoden), dann hat ein Codeelement, das Dutzende anderer verschiedener Codeelemente (auf derselben Ebene) verwendet, sicherlich zu viele Verantwortlichkeiten. Oft wird der Begriff God Class oder God Component wird verwendet, um solchen Code zu qualifizieren.

DSM kann helfen, Codeelemente mit zu vielen Verantwortlichkeiten zu identifizieren. Ein solches Codeelement wird durch Spalten mit vielen blauen Zellen und Zeilen mit vielen grünen Zellen dargestellt. Die DSM unten zeigt dieses Phänomen.

zu viele Verantwortlichkeiten

Nach oben

Wechselseitig abhängig

Sie können die Kopplung zwischen 2 Komponenten sehen, indem Sie mit der rechten Maustaste auf eine nicht leere Zelle klicken und das Menü Diese Abhängigkeit öffnen.

MutualDependency 1

Wenn die geöffnete Zelle schwarz war wie im Snapshot oben (d. h. wenn A und B gegenseitig abhängig sind), dann enthält die resultierende rechteckige Matrix sowohl grüne als auch blaue Zellen (und eventuell auch schwarze Zellen), wie im Snapshot unten.

MutualDependency 2

In dieser Situation werden Sie oft ein Defizit an grünen oder blauen Zellen bemerken (hier 3 blaue Zellen für 1 grüne Zelle). Das liegt daran, dass zwischen zwei gegenseitig abhängigen Codeelementen oft eine natürliche Ebenenreihenfolge existiert. Betrachten Sie zum Beispiel die System.Threading Namespaces und die System.String Klasse. Sie sind gegenseitig abhängig; beide verlassen sich aufeinander. Aber die Matrix zeigt, dass Threading ist viel stärker abhängig von Zeichenfolge als umgekehrt (es gibt viel mehr blaue Zellen als grüne Zellen). Dies bestätigt die Intuition, dass Threading ist höherstufig als Zeichenfolge.

Threading zu String

Testen Sie CppDepend noch heute

Starten Sie Ihre 14-tägige kostenlose Testversion mit vollem Zugriff auf alle Dokumentationsfunktionen. Keine Kreditkarte erforderlich.