Mittwoch, 24. September 2014

Das Acyclic-Dependencies Prinzip

Dieser Artikel ist Teil der folgenden Serie über zyklische Abhängigkeiten. Zahlreiche Grundbegriffe, Konzepte und empirische Befunde wurden im Rahmen dieser Serie detailliert dargestellt. Der vorliegende Artikel fasst diese Betrachtungen in Form eines Katalogeintrags zusammen.

Die Serie

Einführung
Terminologie
Werkzeugunterstützung für Java
Wo liegt eigentlich das Problem?
Einfluss auf Qualitätsmerkmale
Die Praxis
Verschiedene Erscheinungsformen
Zusammenhang mit der Pakethierarchie
Zusammenhang mit der Domäne
Einige Metriken
Durchbrechung von Zyklen
Das Prinzip (dieser Artikel)

Katalogeintrag

Name, Kurzform Acyclic-Dependencies Prinzip
Synonyme
ADP,
Prinzip der azyklischen Abhängigkeiten
Beschreibung
Die Abhängigkeiten zwischen Software-Elementen auf den Ebenen der Typen, der Pakete und der physischen Einheiten sollten azyklisch sein.
Erläuterung
Etablierte Fassungen des Prinzips wie z. B. diejenige von Robert C. Martin („Die Abhängigkeiten zwischen Packages müssen einem gerichteten azyklischen Graphen entsprechen. Das bedeutet, dass es keine Zyklen in der Abhängigkeitsstruktur geben darf.“ [Granularity1996]) beziehen sich unnötigerweise lediglich auf Pakete und erheben einen absoluten Anspruch auf Einhaltung. Dieser Absolutheitsanspruch diskreditiert jedoch die Korrektheit des Prinzips, da es nach der Intuition vieler Entwickler auch zahlreiche harmlose Ausnahmen gibt. Dies führt wiederum zu einer generellen Missachtung oder zu pauschalen Rechtfertigungsmustern.

Die obige Fassung des Prinzips umfasst alle relevanten Ebenen und fordert keine absolute Einhaltung. Zahlreiche der oben referenzierten Artikel liefern Differenzierungsmöglichkeiten, um für jedes Software-System auf der Grundlage der Systemeigenschaften und der verfügbaren Analysewerkzeuge entscheiden zu können, welche Zyklen als potentiell schädlich eingestuft werden sollen. Wichtige Kriterien bei dieser Einstufung sind die Topologie der Zyklen, ihre metrischen Eigenschaften, die Eigenschaften der Domäne sowie im Falle von Typ-Zyklen deren Einbettung in die Pakethierarchie.

Entscheidend ist im Einzelfall, welchen potentiellen Schaden ein Zyklus anrichten kann oder bereits anrichtet. Zwei Arten der Schädlichkeit wurden in dem Artikel Wo liegt das Problem? identifiziert:
  • Zyklen erhöhen erstens die Infizierbarkeit der beteiligten Elemente, d. h. die unerwünschte Ausbreitung negativer Eigenschaften und Fehler innerhalb eines Software-Systems.
  • Und sie erhöhen zweitens die Schwergewichtigkeit der beteiligten Elemente, d. h. ihre leichte unabhängige Verwendung im Rahmen von Entwicklungsaktivitäten wie Verstehen, Test, Änderung, Wiederverwendung, Build usw.
Bei der Beurteilung von Zyklen ist also immer zu beurteilen, inwieweit durch sie Symptome der Infizierbarkeit und Schwergewichtigkeit verursacht werden.

Für die Ebene physischer Einheiten kann festgehalten werden, dass Zyklen praktisch immer als schädlich einzustufen sind, da sie den Existenzgrund einer solchen Einheit, der auf ihrer unabhängigen Releasefähigkeit und Wiederverwendbarkeit basiert, generell in Frage stellen. Siehe hierzu auch das Reuse-Release Equivalence Prinzip. [Knoernschild2012], der sich auf die Ebene physischer Einheiten bezieht, schreibt: „Allgemein gesprochen sind Zyklen immer schädlich. Einige sind jedoch schädlicher als andere.
Beispiel(e) Siehe zahlreiche ausführliche Beispiele in der oben referenzierten Artikelserie.
Historie
  • Als früheste namhafte Referenz, die auf Probleme durch Zyklen aufmerksam macht, wird oftmals der Artikel „Designing Software for Ease of Extension and Contraction“ von David L. Parnas aus dem Jahr 1978 genannt [Parnas1978]. Parnas spicht noch von „Loops in the 'Uses' Relation“ und bezieht sich eher allgemein auf „components“ oder gar „programs“. Nichtsdestrotrotz zielt er bereits auf den Aspekt der Schwergewichtigkeit ab, der sich durch Zyklen ergibt: „One may end up with a system in which nothing works until everything works.
  • Fast zeitgleich erfolgen 1996 die Veröffentlichungen „Large-Scale C++ Software Design“ von John Lakos [Lakos1996] und der Artikel „Granularity“ von Robert C. Martin [Granularity1996]. Lakos betrachtet die Probleme von Zyklen sehr ausführlich im Kontext der Entwicklung umfangreicher Software-Systeme im C++-Umfeld, mit einem Schwerpunkt auf Build-Prozessen (Kompilieren, Linken) und Test-Aspekten. In Umfang und Detaillierungsgrad geht er dabei weit über die Ausführungen von Martin hinaus. Beispielsweise formalisiert er das Problem der durch Zyklen besonders verstärkten transitiven Abhängigkeiten durch die Einführung der Metrik Cumulative Component Dependency (CCD). Martin hingegen gibt dem Kind seinen heutigen Namen und führt es gewissermaßen als „Prinzip“ ein, wenn auch eingeschränkt auf die von ihm so genannten "Packages".
  • Wie im Falle anderer Prinzipien auch, spricht Martin ab 2002 in „Agile Software Development. Principles, Patterns, and Practices“ nicht mehr von „Packages“, sondern von „Components“ [Martin2002].
  • Im Rahmen seiner ausführlichen Behandlung von Prinzipien für den Entwurf physischer Einheiten (bei ihm "Module" genannt) geht [Knoernschild2012] auch auf zyklische Abhängigkeiten ein und beschreibt einige Lösungsmuster, die im Wesentlichen an Lakos angelehnt sind (Eskalation, Herabstufung und Callbacks).
Art des Prinzips
  • Grundlegende Einteilung: Produkt.
  • Technologiebezug: Übergreifend.
  • Entwurfsgüte: Strukturprinzip.
  • Handlungsbezug: Erleichterung von Änderung, Überprüfung, Build, Verteilung und Wiederverwendung.
  • Kognitionsbezug: Komplexitätsreduktion, Hierarchisierung.
(Siehe Kategorisierung der Prinzipien.)
Grad der formalen Spezifikation Hoch. In vielen Fällen werkzeuggestützt überprüfbar.
Vorteile
  • Globale Wirkung auf zahlreiche Qualitätsmerkmale und Entwicklungsaktivitäten.
  • Vergleichsweise gute werkzeuggestützte Überprüfbarkeit.
  • Vergleichsweise differenzierte empirische Befunde liegen vor.
  • Die Beseitigung von Zyklen basiert im Wesentlichen auf zwei gut umsetzbaren Operationen, nämlich (1) der Verschiebung von Software-Elementen und (2) der Einführung von Abstraktionen, siehe Zyklische Abhängigkeiten durchbrechen.
  • Nur in sehr seltenen Fällen (z. B. durch die Einführung von Redundanzen) gehen strukturelle Mängel mit der Vermeidung von Zyklen einher.
Nachteile
  • Die oben als Vorteil benannte „globale Wirkung“ ist zugleich auch ein wesentlicher Nachteil: Der mit der Beseitigung von Zyklen angestrebte Nutzen ist oftmals schwer konkret zu benennen oder gar zu beziffern.
  • Die bis heute vorliegende Werkzeugunterstützung ermöglicht noch keinen ganzheitlichen Ansatz zur Einschätzung und Priorisierung von Zyklen. In Einzelfällen kann die Beseitigung von Zyklen mit erheblichen Aufwänden verbunden sein.
  • Die Existenz von harmlosen Zyklen wird in der Praxis regelmäßig zur Rechtfertigung aller Zyklen herangezogen.
Übergeordnete Prinzipien Prinzip der losen Kopplung
Abgleitete Prinzipien -
Qualitätsmerkmale
(+) Änderbarkeit, (+) Wartbarkeit,
(+) Komplexität, (+) Wiederverwendbarkeit,
(+) Austauschbarkeit, (+) Überprüfbarkeit
 

Quellen

[Granularity1996] Granularity, Robert C. Martin, in: IEEE Software. Dezember 1996, S. 4, siehe http://www.objectmentor.com/resources/articles/granularity.pdf
 
[Knoernschild2012] - Java Application Architecture: Modularity Patterns with Examples Using OSGi,  Kirk Knoernschild (2012)  

[Lakos1996] - Large-Scale C++ Software Design, John Lakos (1996)

[Martin 2002] – Agile Software Development. Principles, Patterns, and Practices, Robert C. Martin (2002)

[Parnas1978] - Designing Software for Ease of Extension and Contraction, siehe Abschnitt "D. Loops in the 'Uses' Relation", David L. Parnas (1978), siehe http://www.cs.umd.edu/class/spring2003/cmsc838p/Design/family.pdf