Donnerstag, 4. Dezember 2014

Einfachheit der Struktur - Architekturkomplexität

Bei meinem bisherigen Betrachtungen zur Einfachheit von Strukturen habe ich praktische Erwägungen noch weitgehend ausgeklammert. Ich habe Strukturen allgemein als eine Menge von Elementen und Relationen zwischen diesen Elementen aufgefasst, wobei die Elemente wiederum aus Subelementen bestehen, die ihrerseits durch Relationen verbunden sind usw. Diese Betrachtungsweise ist eng an die Mathematik angelehnt, so dass die Bewertung von Strukturen u. a. auf Konzepte aus der Mengenlehre und der Graphentheorie zurückgreifen kann. 

Nun spielt sich die Konstruktion von Software-Systemen nicht im sterilen Betrachtungsraum der Mathematik ab, sondern wird stark von praktischen Aspekten beeinflusst. Dies gilt insbesondere auch für die Architektur von Software-Systemen. Aus rein struktureller Sicht können wir die Architektur eines Software-Systems als seine höchste Struktur-Ebene auffassen, also als die Ebene der Subsysteme. Die bereits behandelten Konzepte der Größe, Kohäsion und Kopplung sind auf diese Subsystem-Ebene direkt anwendbar. In praktischer Hinsicht sind jedoch eine Reihe weiterer Kriterien für die Bewertung von Software-Architekturen relevant. Neben den Aspekten individueller Kognition gehören hierzu auch Fragen der arbeitsteiligen Beherrschung von Software-Systemen sowie die Auswahl und Kombination von Technologien zur Realisierung des Systems.

In diesem Artikel stelle ich ein Komplexitätsmodell vor, das speziell für die Ebene der Software-Architektur entwickelt wurde und das diese praktischen Fragen berücksichtigt. Ausgehend von der Arbeit "Komplexität von Softwarearchitekturen" von Carola Lilienthal [Lilienthal2008] wurde dieses Modell in [Lilienthal2010] unter der Bezeichnung Software Architecture Complexity Model (SACM) weiterentwickelt und stellt nach meiner Kenntnis das derzeit umfassendste Modell dieser Art dar. 

1. Kognitive Grundlagen

In [Lilienthal2008] werden die kognitiven Grundlagen des Modells beschrieben. Es werden drei elementare kognitive Prozesse unterschieden, die der Mensch zur Bewältigung von Komplexität einsetzt:
  • Chunking: das Zusammenfassen von Informationen zu höherwertigen Einheiten
  • Bildung von Hierarchien: die Nutzung hierarchischer Strukturen  (z. B. in Form von Kategoriensystemen, Teile-Ganzes-Beziehungen oder Vererbungsbeziehungen) zur Erleichterung des Verstehens, des Lernens und des Abrufens von Information
  • Aufbau von Schemata: der Einsatz von Wissenseinheiten, die sowohl abstrahiertes Wissen (Festlegung typischer Zusammenhänge und Eigenschaften) als auch konkretes Wissen (die Beschreibung prototypischer Exemplare) umfassen
Für Lilienthal ergibt sich nach der Untersuchung dieser Prozesse
"(...) die Erkenntnis, dass der Mensch mit Chunking, der Bildung von Hierarchien und dem Aufbau von Schemata auf komplexe Strukturen reagiert. Ein Softwaresystem, das von seiner Architektur her diese Prozesse unterstützt, hat geringe Architekturkomplexität." [Lilienthal2008]
Sie ordnet daher den drei Prozesstypen Faktoren zu, die sich in einer gegebenen Software-Architektur wiederfinden müssen, damit diese Architektur kognitiv beherrschbar bleibt. Es handelt sich um die folgenden Faktoren (Hervorhebung von mir):
  • "Modularität: prüft, ob die implementierte Architektur in kohäsive Einheiten zerlegt ist, die ihr Verhalten kapseln und kohäsive Schnittstellen anbieten.
  • Geordnetheit: prüft, ob die Beziehungen zwischen den Elementen der implementierten Architektur einen gerichteten azyklischen Graphen bilden.
  • Mustertreue: prüft, ob das Muster der beabsichtigten Architektur und der eingesetzten Technologie in der implementierten Architektur wiedergefunden werden kann, und ob ihre Regeln eingehalten wurden." [Lilienthal2010]
Gemeinsam werden diese Faktoren als "persönliche Faktoren" bezeichnet.

2. Umgebungsfaktoren

Während sich die persönlichen Faktoren unmittelbar aus kognitiven Prozessen ableiten, die der Beherrschung von Komplexität dienen, leiten sich zwei weitere Faktoren aus dem Kontext der arbeitsteiligen Beherrschung von Software-Systemen ab.

Diese Faktoren waren im ursprünglichen Modell aus [Lilienthal2008] noch nicht enthalten und wurden später insbesondere in Zusammenarbeit mit Eric Bouwers und Kollegen hinzugefügt. Ausgangspunkt für diese Erweiterung war die empirische Untersuchung [Bouwers2009], in welcher ein Katalog aus fünfzehn Systemeigenschaften erarbeitet wurde, welche die Wartbarkeit einer Software-Architektur stark beeinflussen. In [Lilienthal2010] wird argumentiert, dass sich diese Ergebnisse auch auf die Komplexität einer Architektur übertragen lassen, da eine Systemeigenschaft zunächst verstanden werden muss, bevor sie gewartet werden kann ("Since a system attribute has to be understood bevor it can be maintained (...)" [Lilienthal2010]).

Wie sich zeigte, decken die oben beschriebenen persönlichen Faktoren lediglich einen Teil der von Bouwers und Kollegen gefundenen Attribute ab. Insbesondere werden solche Attribute nicht erfasst, die in der Praxis dazu führen, dass ein Individuum die notwendige Arbeit nicht alleine bewältigen kann, so dass sich zu den individuellen kognitiven Prozessen zusätzliche Organisationsaufwände zwischen verschiedenen Individuen gesellen. Bezogen auf die Information, die erforderlich ist, um die Architektur des Systems zu verstehen, werden die folgenden Faktoren ergänzt:
  • Umfang der Information: Mit dem Umfang der Information steigt die Wahrscheinlichkeit, dass es zur Verteilung kognitiver Arbeit auf unterschiedliche Individuen kommt.
  • Zugänglichkeit der Information: Damit die architekturbezogene Information effektiv verarbeitet werden kann, muss sie für das bearbeitende Entwicklerteam gut zugänglich sein. Zugänglichkeit (engl. availability) wird hier in einem sehr weiten Sinn verstanden: Beispielsweise spielt die Repräsenationsform der Architektur ebenso eine Rolle wie das Alter oder die Zusammensetzung der eingesetzten Technologien.

3. Gesamtbild

Die fünf Faktoren werden nun um Kriterien zu einem Factor-Criteria-Metrics-Modell ergänzt, das auf höchster Ebene ein festgelegtes Ziel aufweist und in welchem die auf unterster Ebene zu definierenden Metriken noch fehlen. 

Als Ziel vermerken Lilienthal und Kollegen in [Lilienthal2010] zwar "Complexity", sie notieren jedoch im Text: "(...) this goal is named 'complexity', although strictly speaking the goal of SACM is to evaluate and reduce complexity." Ich habe mir daher erlaubt, den positiven Begriff der "Einfachheit" in das Modell einzusetzen. Es ergibt sich das folgende Gesamtbild:
Die Beschreibung der insgesamt 18 Einzelkriterien möchte ich mir an dieser Stelle sparen. Eine gute Übersicht wird in [Lilienthal2010] gegeben. Statt dessen möchte ich einige allgemeine Anmerkungen machen. 

Am leichtesten fällt uns die Einordnung der Kriterien zur Modularität und Geordnetheit:
  • Die Kriterien der Modularität basieren größtenteils auf Prinzipien, die ich bereits ausführlich in früheren Artikeln behandelt habe, darunter hohe Kohäsion, lose Kopplung, Geheimnisprinzip und Vermeidung von Redundanz. Dem Aspekt der Ausgewogenheit sind wir bereits im Komplexitätsmodell von Roger Sessions begegnet, der die Komplexität einzelner Elemente mit der Anzahl ihrer Funktionen exponentiell steigen lässt, was zu einer großen Ausgewogenheit beim Erzeugen einer Partitionierungs-Lösung führt.
  • Die Kriterien der Geordnetheit basieren allesamt auf dem Acyclic-Dependencies Prinzip, zu dem ich eine ausführliche Artikelserie veröffentlicht habe.
Die Kriterien zur Mustertreue zielen im Wesentlichen auf die Frage ab, ob sich Architekturvorgaben im realisierten System wiederfinden lassen. Im Rahmen meines allgemeinen Modells für Software-Systeme lässt sich dieser Faktor also in das Konzept der Repräsentation einordnen, das ich wie folgt veranschaulicht habe:
Da sich Architekturvorgaben (wie z. B. Schichtenmodelle, größere Subsysteme usw.) häufig nicht unmittelbar in der Syntax der verwendeten Programmiersprache ausdrücken lassen, thematisiert Lilienthal die Übereinstimmung von Spezifikation/Dokumentation mit der eigentlichen Realisierung des Systems. Verstößt die ausführbare Systembeschreibung gegen Spezifikation oder Dokumentation, so wird dies als Komplexitäts-erhöhend bewertet. Diesem Thema werde ich mich in einem späteren Artikel zum Konzept der Repräsentation noch etwas eingehender widmen.

Bleiben schließlich noch die Umgebungsfaktoren. Hier wird die pragmatische Ausrichtung von SACM am deutlichsten:
  • Die Kriterien zum Umfang zielen keineswegs lediglich auf die Repräsentation des Systems selbst ab (entweder als Spezifikation/Dokumentation oder als ausführbare Systembeschreibung), sondern auch auf die Lernkurve hinsichtlich der Verwendung von Technologien, Bibliotheken und Mustern.
  • Die Kriterien zur Zugänglichkeit thematisieren die Art der Bereitstellung von architekturbezogener Information, das Alter dieser Information sowie die Geläufigkeit der Kombination eingesetzter Technologien. Auch dies ist sehr pragmatisch gedacht. Komplexität wird hier nahezu gleichgesetzt mit dem Aufwand des Kennenlernens eines Systems.

4. Grenzen von SACM

4.1. Konzeptionelle Grenzen

SACM setzt die beiden vieldimensionalen Konzepte "Architektur" und "Komplexität" in einem Zusammenhang. Die Gefahr eines solchen Modells besteht darin, einen Bewertungsraum zu schaffen, der in seiner Vieldimensionalität kaum mehr als Einheit wahrgenommen werden kann. SACM löst dieses Problem, indem die Bedeutung der beiden Begriffe eingeschränkt wird. 

So wird mit Komplexität in den meisten Fällen Verstehenskomplexität gemäß der Darstellung in [Lilienthal2008] bezeichnet:
Verstehenskomplexität in der Software-Entwicklung [Lilienthal2008:Verstehenskomplexität]
Auch die durch Brouwers eingebrachten Attribute, die aus einer Studie bezogen wurden, welche die Wartbarkeit von Architekturen untersucht hat, werden mit dem Argument in das Modell aufgenommen, dass einer Wartungstätigkeit zunächst das Verstehen vorausgehen muss. (Diesem Argument muss man nicht ohne Einschränkung zustimmen.)

Der Architekturbegriff, der dem Modell zu Grunde liegt, erscheint hingegen weitaus unschärfer. Im realisierten System werden insbesondere die Ebenen der Subsysteme und Klassen als das Wesentliche der Architektur angesehen. Durch die Berücksichtigung von Spezifikation/Dokumentation im Rahmen des Faktors Mustertreue wird diese Sicht jedoch über das realisierte System hinaus ausgedehnt. Schließlich verschwimmen diese Grenzen durch die Berücksichtigung der Arbeit von Bouwers und Kollegen vollends, indem zur Architektur praktisch jede Information gehört, die erforderlich ist, um die implementierte Architektur zu verstehen (" (...) information needed to understand the implemented architecture" [Lilienthal2010]). Auf diese Weise kommen Elemente ins Spiel, die über eine rein strukturelle Betrachtung aus Elementen und Relationen weit hinausgehen (z. B. Technologien oder Medien).

4.2. Grenzen beim Einsatz im Software-Lebenszyklus

Die SACM-Kriterien zerfallen in zwei Gruppen, nämlich in
  • solche Kriterien, die bereits als Entscheidungshilfe in frühen Entwurfs- und Entwicklungsphasen geeignet sind 
  • und solche, die sich lediglich zur Evaluation bereits realisierter Systeme eignen
Zur ersten Gruppe gehören die Kriterien der Faktoren Modularität, Geordnetheit und Umfang der Information, zur letzteren die Kriterien des Faktors Mustertreue. Von den Kriterien des Faktors Zugänglichkeit der Information eignet sich allenfalls "Informations-Medium" bereits in frühen Phasen des Lebenszyklus, während "Alter" und "Technologie-Kombination" erst in späteren Phasen relevant werden.

5. Fazit

Insgesamt ist das Modell vergleichsweise umfassend. Von den vier Grundkonzepten eines Software-Systems (Funktion, Struktur, Hierarchie und Repräsentation, siehe System-Modell) wird das Struktur-Konzept am besten abgedeckt, das Hierarchie-Konzept zumindest ansatzweise (Vermeidung von Zyklen) und das Repräsentations-Konzept in einer eher pragmatischen Weise. Das funktionale Konzept spielt allerdings eine untergeordnete Rolle, obwohl einige funktionale Aspekte (die Berücksichtigung der Daten und der verhaltensbezogenen Eigenschaften) sicherlich auch für die Architekturkomplexität relevant sind. 

Das Modell ist eine gute Orientierungshilfe, wenn man sich dem Zusammenhang von Software-Architektur und Komplexität annähern möchte. Während die weitgehende Gleichsetzung von Komplexität mit "Verstehenskomplexität" noch eine akzeptable Vereinfachung darstellt, die von vielen anderen Autoren geteilt wird, scheint der Architekturbegriff des Modells (insbesondere auch ggü. seiner ursprünglichen Fassung in [Lilienthal2008]) jedoch etwas zu unscharf geraten zu sein. Diese Unschärfe ist andererseits dem Anspruch geschuldet, ein Modell zur Verfügung zu stellen, das alle praxisrelevanten Aspekte der "Architekturkomplexität" abdeckt.

6. Quellen

[Bouwers2009] - Criteria for the evaluation of implemented architectures, Eric Bouwers, Joost Visser, Arie van Deursen (2009)

[Lilienthal2008] - Komplexität von Softwarearchitekturen. Stile und Strategien, Carola Lilienthal (2008) 

[Lilienthal2008:Verstehenskomplexität] - Abbildung aus [Lilienthal2008], S. 13, mit freundlicher Genehmigung von Carola Lilienthal

[Lilienthal2010] - A Cognitive Model for Software Architecture Complexity, Eric Bouwers, Carola Lilienthal, Joost Visser, Arie van Deursen, Delf University of Technology (2010)

Donnerstag, 27. November 2014

Einfachheit der Struktur - ein allzu einfaches Modell

In seinem 2008 erschienenen Buch "Simple Architectures for Complex Enterprises" [Sessions2008] sowie in seinem White Paper "The Mathematics of IT Simplification" [Sessions2011] stellt Roger Sessions ein Komplexitätsmodell vor, das eine mathematisch fundierte Bewertung der Komplexität von Strukturen verspricht. Wie sich herausstellen wird, ist dieser Anspruch etwas zu hoch gegriffen. Ich werde den Bewertungsansatz hier dennoch etwas ausführlicher vorstellen, um die allgemeinen Probleme, die mit einem solchen Gesamtmodell verbunden sind, an einem Beispiel verdeutlichen zu können.

1. Funktionen und Partitionen

Sessions bezeichnet das fundamentale Element, das es zu strukturieren gilt, in [Sessions2011] als "Funktion" (engl. function). In seinem White Paper weicht er terminologisch ggü. seinem umfassenderen Buch [Sessions2008] leicht ab, was sich ggf. dadurch begründen lässt, dass im Buch das Thema "Enterprise Architecture" zur Diskussion steht und daher Business-Prozesse und IT-Systeme gemeinsam betrachtet werden, während das White Paper den Schwerpunkt auf die IT-Systeme legt. Ich übernehme hier die Terminologie des White Papers. 

Der Ausgangspunkt der Betrachtung besteht also in einer unpartitionierten Menge an Funktionen. Dies ist grundsätzlich konform zu meinem allgemeinen Modell für Software-Systeme, das sich auf unterster Ebene (ausgenommen die Repräsentation) aus Funktionen und Daten-Objekten konsitutiert. (Siehe hierzu auch Einfachheit der Struktur - Grundlagen, dort den Abschnitt "3. Funktionen und Daten als Ursprung aller Relationen").

Sessions geht davon aus, dass die Komplexität, die sich durch eine unstrukturierte Menge von Funktionen in einem modernen Software-System ergibt, bei weitem zu groß ist, um noch handhabbar zu sein. Die einzige Möglichkeit, diese Komplexität zu bändigen, besteht in der Partitionierung der Funktionen: ihrer Aufteilung in kleinere, noch handhabbare Einheiten. Da Sessions von der Mengenlehre ausgeht, bezeichnet er eine solche Einheit als "Untermenge" (engl. subset). Die Aufteilung aller Funktionen in Untermengen, so dass jede Funktion genau einer Untermenge angehört, bezeichnet er als "Partition" (engl. partition). Eine Partition ist also eine Menge von Untermengen aus Funktionen.

Man könnte den Begriff "Partition" misverstehen und damit eine der Untermengen einer bestimmten Partitionierungs-Lösung meinen. Um hier jegliche Probleme zu vermeiden, werde ich statt von "Partition" immer von "Partitionierungs-Lösung" sprechen, wenn eine konkret gebildete Menge von Untermengen gemeint ist. Den Vorgang der Erzeugung einer solchen Partitionierungs-Lösung bezeichne ich als "Partitionierung" (engl. partitioning oder driving the partition).

2. Die Anzahl möglicher Partitionierungs-Lösungen: Bellsche Zahl

Die Abbildung unten zeigt die möglichen Partitionierungs-Lösungen für fünf Elemente - es handelt sich um 52 Möglichkeiten. Wieviele Lösungen sind allgemein für n Elemente möglich? Diese Größe wird durch eine Folge beschrieben, die als Bellsche Zahl bekannt ist. Die Folge beginnt (für n >= 1) wie folgt: 1, 2, 5, 15, 52, 203, 877, 4140, 21147, 115975, 678570, …
Quelle: Wikipedia Commons, 
siehe [Bild1]

Der Beginn dieser Folge zeigt, dass es bereits ab einer kleinen Zahl der zu partitionierenden Elemente praktisch unmöglich ist, alle möglichen Lösungen einzeln zu betrachten und zu evaluieren. Doch selbst wenn es möglich wäre, eine solche Evaluation für eine ausgewählte Zahl möglicher Lösungen durchzuführen: Worauf sollte sie basieren? Welche Eigenschaften sind es konkret, die eine Lösung "einfacher" als eine andere sein lassen?

3. Die Bewertung einer Lösung

Roger Sessions unterscheidet zwei Eigenschaften einer Lösung, die er als functional complexity und coordination complexity bezeichnet:
  • Functional complexity bezeichnet die Komplexität einer einzelnen Untermenge innerhalb der Partionierungs-Lösung.
  • Coodination complexity bezeichnet die Komplexität, die sich aus den Relationen zwischen den Untermengen einer Partitionierungs-Lösung ergibt. 
Er präsentiert eine Möglichkeit zur Evaluation dieser beiden Eigenschaften, die auf den mathematischen Eigenschaften der Partitionierungs-Lösung basiert. Durch additive Verknüpfung der beiden Eigenschaften kommt er zu einer Gesamtbewertung, die ihm schließlich den Vergleich zweier Lösungen erlaubt. Wir werden uns nun den Gedankengang näher anschauen, auf dem die mathematische Bewertung beruht.

4. Die Bewertung der functional complexity

Enthält eine Untermenge nur eine Funktion F1, so kann auch nur eine Funktion für ein Problem verantwortlich sein. Enthält eine Untermenge zwei Funktionen F1 und F2, so entstehen drei mögliche Konstellationen: Entweder ist die Funktion F1 oder die Funktion F2 oder das Zusammenspiel von F1 und F2 für das Problem verantwortlich. Es lässt sich leicht erkennen, dass die Zahl möglicher Konstellationen mit der Zahl der Funktionen exponentiell anwächst. Andererseits existieren zahlreiche völlig abwegige Partitionierungs-Lösungen, deren Betrachtung einem halbwegs erfahrenen Experten nichteinmal einfallen würde. Sessions betrachtet den exponentiellen Zusammenhang dennoch als nachgewiesen und macht einen Vorschlag zur Wahl des Exponenten.

Dabei orientiert er sich an einer Aussage von Robert Glass aus dessen Buch "Facts and Fallacies of Software Engineering" [Glass2002], nach der eine Erweiterung der System-Funktionen um 25% zu einer Verdoppelung der Komplexität führt. Nach einiger Umrechnung führt dies zu einem Exponenten von 3,11. Setzt man die Komplexität einer einzelnen Funktion gleich 1 und verwendet diese als Maßeinheit namens SCU (Single Complexity Unit), so ergibt sich für eine Anzahl n von Funktionen:
SCU(n) = n3,11
Was lässt sich über diesen Gedankengang sagen? Einerseits steht die Annahme eines exponentiellen Wachstums in Einklang mit den Annahmen anderer Autoren wie z. B. [Wang2007], der als Komplexität eines Systems aus n Subsystemen den Wert n * (n - 1) annimmt. Andererseits gibt es doch auch einige Bedenken:
  1. Der Gedankengang ignoriert die tatsächliche Zahl der inneren Relationen einer Partition. 
  2. Der Gedankengang ignoriert auch die Form, die sich aus den konkreten inneren Relationen einer Partition ergibt.
  3. Aus (1) und (2) ergibt sich, dass das Konzept der Kohäsion weitgehend ignoriert wird.
  4. Der Gedankengang ignoriert mögliche Unterschiede in der Komplexität der einzelnen Funktionen innerhalb der Untermenge.
  5. Nicht jede Tätigkeit am System ist eine "Problemlösung" in der hier angenommenen Form.
Aus dem Gesagten ergibt sich, dass es einige Gründe gibt, den behaupteten mathematischen Zusammenhang anzuzweifeln. Andererseits ist es unbestritten, dass die Komplexität einer Einheit im Durchschnitt stärker ansteigt als ihre Größe. Dies hatten wir auch bereits im Artikel über die Zusammenhänge zwischen Größe, Kohäsion und Kopplung festgestellt. Diese Zusammenhänge sind jedoch wesentlich unklarer als es von Roger Sessions suggeriert wird. Um eine derart konkrete Modellierung zu untermauern, müsste sowohl empirisch als auch theoretisch (z. B. mengentheoretisch oder graphentheoretisch) wesentlich präziser argumentiert werden.

5. Die Bewertung der coordination complexity

Für die Bewertung der coordination complexity einer konkreten Untermenge nimmt Sessions trivialerweise an, dass
"... the amount of complexity added by increasing the dependencies by one is roughly equal to the amount of complexity added by increasing the number of functions by one" [Sessions2011],
wobei unter dependencies alle Abhängigkeiten der betrachteten Untermenge von anderen Untermengen, also nur die ausgehenden Abhängigkeiten gewertet werden. Die Begründung des exponentiellen Anstiegs der Komplexität erscheint hier jedoch äußerst dürftig. Warum sollte der Beitrag einer Abhängigkeit zur Gesamtkomplexität gleich hoch sein wie der Beitrag einer Funktion?

6. Gesamtbild der Bewertungsmethode

Die Gesamtkomplexität ergibt sich in Sessions Modell aus der Addition der functional complexity mit der coordination complexity. Die noch stärkere Multiplikation zieht Sessions ebenfalls in Betracht, wählt aber in dieser Hinsicht den konservativeren Ansatz. Somit gelangt er zu einer Gesamtformel der strukturellen Komplexität je gebildeter Untermenge, die er selbst als "Total Complexity" bezeichnet. Gehen wir von einer Untermenge U mit n Elementen und m ausgehenden Abhängigkeiten aus, so ergibt sich
SCU(U) = n3,11 + m3,11
Die Komplexität des Gesamtsystems ergibt sich dann einfach aus der Addition der SCU-Werte aller Untermengen. Was lässt sich auf der Grundlage dieser Modellbildung über den entstehenden Charakter einer "optimalen" Partitionierungs-Lösung sagen? 

Die functional complexity steigt mit wachsender Zahl der Elemente einer Untermenge exponentiell, die coordination complexity steigt mit wachsender Zahl der ausgehenden Abhängigkeiten einer Untermenge exponentiell. Daraus folgt, dass Ausreißer hinsichtlich der Größe oder der Anzahl ausgehender Abhängigkeiten "bestraft" werden. Der exponentielle Komplexitätsanstieg dieser Ausreißer würde die Gesamtkomplexität des Systems stark ansteigen lassen.
 
Die Anwendung des Bewertungsmodells muss also zu einer großen Ausgewogenheit hinsichtlich der Größe einzelner Untermengen sowie zu einem gleichmäßigen Grad der Eigenständigkeit der Untermengen führen. Übermäßig große oder übermäßig unselbständig arbeitende Partionen werden sanktioniert. 

Während diese Erwägungen nicht unplausibel erscheinen, will doch nicht ganz einleuchten, warum es nicht doch einzelne Elemente mit einer größeren Zahl von Subelementen geben soll, wenn diese Subelemente beispielsweise in einer sehr engen kohäsiven Beziehung stehen, wie wir es im Artikel zur Kohäsion bereits an folgendem Beispiel verdeutlicht haben:

Es fällt auf, dass das Konzept der Kohäsion überhaupt nicht in das Bewertungsmodell einfließt. Zwar schlägt Sessions ein Konzept vor, das mit Kohäsion eng verwandt ist (er nennt es Synergie) und das dabei helfen soll, eine Partitionierungs-Lösung zu erzeugen, doch dieses Konzept fließt nicht in den Bewertungs-Mechanismus ein.

6. Fazit

Das Modell von Roger Sessions ist auf den ersten Blick aus mehreren Gründen attraktiv:
  • Es basiert auf einer nachvollziehbaren mengentheoretischen Grundlage.
  • Es führt die Komplexität gebildeter Struktur-Elemente und die Komplexität der Abhängigkeiten dieser Elemente zu einer Gesamtkomplexität zusammen.
  • Es liefert vergleichbare Bewertungen unterschiedlicher Lösungen.
Bedauerlicherweise ist Sessions dabei jedoch die mathematische Präzision auf halbem Wege verlorengegangen. An dem Bewertungsmodell lassen sich mindestens die folgenden Kritikpunkte anbringen:
  • Der behauptete exponentielle Komplexitätsanstieg durch das Hinzufügen von Funktionen basiert lediglich auf einer intuitiv geführten Argumentation und wird keineswegs mengentheoretisch nachgewiesen (wie es an einigen Stellen suggeriert wird).
  • Der behauptete exponentielle Komplexitätsanstieg durch das Hinzufügen weiterer Abhängigkeiten wird noch schwächer begründet.
  • Das wichtige Konzept der Kohäsion bleibt bei der Bewertungsfunktion völlig unberücksichtigt.
Es war mir dennoch wichtig, das Modell an dieser Stelle etwas detaillierter vorzustellen, da es zeigt, dass auch in der jüngsten Literatur noch kein fundierter Ansatz existiert, der uns eine zuverlässige Bewertung der strukturellen Komplexität einer gegebenen Struktur-Ebene ermöglicht. Zudem werden die Probleme bei der Bildung eines solchen Gesamtmodells sichtbar: Es ist keineswegs klar, wie sich z. B. der Aspekt der Kohäsion in das Modell einfügen könnte. Auch über den Beitrag der Größe im Verhältnis zum Ausmaß der Kopplungen werden hier bestenfalls triviale Annahmen gemacht, die einem zweiten Blick nicht standhalten. 

Nach mehr als einem halben Jahrhundert der Praxis und Theoriebildung im Software Engineering ist es ernüchternd, wie rudimentär unser Verständnis elementarer Konzepte noch ist.

7. Quellen

[Bild1] -  "Set partitions 5; circles" by mate2code - Own work. Licensed under CC BY 3.0 via Wikimedia Commons.

[Glass2002] - Facts and Fallacies of Software Engineering, Robert Glass (2002)

[Sessions2008] - Simple Architectures for Complex Enterprises, Roger Sessions (2008)

[Sessions2011] - The Mathematics of IT Simplication, Roger Sessions (2011), siehe http://dl.dropboxusercontent.com/u/97323460/WebDocuments/WhitePapers/MathOfITSimplification-103.pdf

[Wang2007] - Software Engineering Foundations - A Software Science Perspective, Wang, Yingxu (2007) 

Einfachheit der Struktur - Größe, Kohäsion und Kopplung

In den vorhergehenden Artikeln haben wir die Konzepte der Kohäsion sowie der Kopplung besprochen. Im vorliegenden Artikel möchte ich nun die Zusammenhänge zwischen Kohäsion, Kopplung und der Größe von Software-Elementen betrachten. Wir können diese Zusammenhänge als ein Spiel der Kräfte auffassen, die sich antagonistisch gegenüberstehen. Einige Kräfte wirken in Richtung einer Ausdehnung der Struktur-Elemente einer Ebene. Andere Kräfte wirken eingrenzend auf dieselben Elemente. Es lassen sich drei fundamentale Kräfte identifizieren:
  • Internalisierungskraft: die Tendenz, Relationen zu internalisieren (ausdehnend)
  • kohäsive Abstoßung zwischen Subelementen, die nicht zusammengehören (eingrenzend)
  • Überdehnung von Elementen, die zu viele Subelemente aufnehmen (eingrenzend)
Es ergibt sich das folgende Gesamtbild, das wir in den folgenden Abschnitten eingehend behandeln werden:

1. Internalisierungskraft

Wir können das Streben nach Entkopplung auf einer gegebenen Ebene des Software-Systems als eine Kraft auffassen, die uns dazu bewegen möchte, Relationen zu internalisieren. Um dies etwas zu präzisieren, führe ich folgende Sprachregelung ein:

Gegeben sei eine aktuelle Betrachtungs-Ebene, z. B. die Ebene der Typen oder die Ebene der Pakete. Wir sprechen auf dieser Ebene von "Elementen", die aus "Subelementen" zusammengesetzt sind. Und wir sprechen weiterhin
  • von einer internen Relation, wenn diese Relation zwischen zwei Subelementen besteht, die beide zu einem einzigen Element gehören
  • von einer externen Relation, wenn diese Relation zwischen zwei Subelementen besteht, die zu verschiedenen Elementen gehören.
Wären unsere Elemente Module, so könnten wir von intramodularen und extramodularen Relationen sprechen. Da wir uns sprachlich nicht auf Module festlegen wollen, sprechen wir von internen und externen Relationen. Dabei behalten wir im Sinn, dass diese Sprachregelung immer eine festgelegte System-Ebene voraussetzt, d. h. es muss klar sein, welcher Art die Elemente und Subelemente sind.

Interne Relationen fassen wir als positiv auf, da sie die strukturelle Kohäsion verstärken. Externe Relationen fassen wir als negativ auf, da sie den Kopplungsgrad auf der gegebenen System-Ebene erhöhen. Das Streben nach Internalisierung von Relationen basiert also sowohl auf der Forderung nach hoher Kohäsion als auch auf der Forderung nach schwacher Kopplung. Ich nenne diese Kraft Internalisierungskraft.

Da beide Subelemente einer Relation zum selben Element gehören müssen, damit die Relation zu einer internen Relation wird, wirkt die Internalisierungskraft tendentiell in Richtung einer Vergrößerung der Elemente. Um eine Relation zu internalisieren, muss immer auch mindestens ein neues Subelement in das Element aufgenommen werden.

2. Kohäsive Abstoßung

Die Internalisierungskraft drängt uns also dazu, immer mehr Subelemente in ein Element aufzunehmen. Würde dieser Kraft nichts entgegenstehen, so führte dies zu einem monolithischen Gesamtelement, in dem alle Relationen interne Relationen wären und es keine externen Relationen mehr gäbe. Der erste Antagonist dieser Tendenz leitet sich aus dem Konzept der Kohäsion ab.

Die Forderung nach Kohäsion bedeutet, dass in einem Element nur solche Subelemente zusammengefasst werden sollen, die zusammengehören (engl. togetherness). Bei aller Unschärfe dieses Zusammengehörigkeits-Konzepts ist doch klar, dass in einem hinreichend großen System Subelemente existieren, die nicht zusammengehören und die also nicht in dasselbe Element aufgenommen werden sollten. Ich bezeichne diese Kraft, die sich dagegen sträubt, dass unzusammengehörige Subelemente in dasselbe Element aufgenommen werden, als kohäsive Abstoßung.

An dieser Stelle bemerken wir, dass das Konzept der Kohäsion zwei Facetten hat, denn es ist auch sinnvoll, von einer kohäsiven Anziehung zu sprechen. Stellen wir fest, dass zwei Subelemente zusammengehören, so möchten wir sie intuitiv in dasselbe Element aufnehmen, da dies die Kohäsion des Elements erhöht. Die kohäsive Anziehung wirkt auf die Subelemente selbst, während die Internalisierungskraft auf die Relationen wirkt. In der Regel wird jedoch die kohäsive Anziehung dadurch widergespiegelt, dass die beiden Subelemente durch eine Relation verbunden sind. In solchen Fällen wirkt bereits die Internalisierungskraft. Wir können daher die kohäsive Anziehung als enge Verwandte der Internalisierungskraft auffassen und müssen nicht gesondert auf sie eingehen.

Wichtig ist, dass die kohäsive Abstoßung jeweils vom einzelnen Subelement ausgeht, das sich der Internalisierungskraft des Elements widersetzt. Dies unterscheidet die kohäsive Abstoßung von der Überdehnung, die wir im folgenden Abschnitt behandeln.

3. Überdehnung

Unter den meisten Autoren besteht Einigkeit darüber, dass die Komplexität eines Elements schneller ansteigt als seine Größe. Einige Autoren (z. B. [Wang2007] oder [Sessions2011]) unterstellen gar ein exponentielles Wachstum. Ohne in die Details dieser Diskussion einsteigen zu wollen, geht das oben gezeigte Kräftemodell davon aus, dass die Komplexität eines Elements mit seiner Größe (d. h. der Zahl seiner Subelemente) ansteigt und dass dieser Anstieg (zumindest ab einer bestimmten Mindestzahl) steiler ist als der Größenanstieg.

Ein Teil dieses Komplexitätsanstiegs mag auf fehlende Kohäsion zurückzuführen sein, die wir bereits als kohäsive Abstoßung beschrieben hatten. Es spielen jedoch auch andere Aspekte eine bedeutsame Rolle:
  • Zahlreiche Autoren (z. B. [Wang2007] oder [Lilienthal2008]) heben kognitive Aspekte hervor, die mit der Beschränkung der kognitiven menschlichen Ressourcen zu tun haben. Werden solche Größenlimits überschritten, so können die Subelemente eines Elements nicht mehr innerhalb eines einzigen kognitiven Verarbeitungsvorgangs erfasst oder erinnert werden, so dass der Vorgang sequentialisiert (in mehrere aufeinanderfolgende Teilvorgänge aufgeteilt) oder parallelisiert (= auf verschiedene Personen aufgeteilt) werden muss.
  • Andere Autoren stellen den exponentiellen Anstieg potentieller Relationen [Wang2007] oder gar potentieller Partinionierungen [Sessions2011] in einen Zusammenhang mit dem Komplexitätsanstieg.
Diese Aspekte haben eher mit der Größe des Elements selbst zu tun als mit den Zusammenhängen zwischen einzelnen Elementen, wie es bei der kohäsiven Abstoßung der Fall war. Wir können diese Aspekte als eine der Vergrößerung entgegenwirkende Kraft auffassen, da mit zunehmender Größe ein immer größerer Preis gezahlt werden muss, um weitere Subelemente in das Element aufzunehmen. Um diesen Preis nicht allgemein mit "Komplexität" bezeichnen zu müssen (der Begriff, an den wir uns im Rahmen dieser Artikelserie wesentlich vielschichtiger annhähern wollen), nenne ich diese Kraft Überdehnung.

4. Der Wunsch nach einer Gesamtformel

Nur zu gerne würden wir strukturelle Komplexität als Funktion einer festen Anzahl von Eigenschaften betrachten, z. B. als f(Größe, Kohäsionsgrad, Kopplungsgrad). Die oben gezeigte Abbildung könnte den Eindruck vermitteln, als wäre dies möglich. Derzeit existiert jedoch kein allgemein akzeptiertes Modell, das eine solche Funktion zur Verfügung stellt. In [Sessions2011] wird ein Modell vorgestellt, das zumindest den Versuch macht. Dieses Modell werde ich im nächsten Blogartikel vorstellen.

5. Zusammenfassung

Obwohl Größe, Kohäsion, Kopplung und Komplexität zu den meist untersuchten Eigenschaften von Software gehören, existiert bis heute kein zufriedenstellendes Modell, dass diese Eigenschaften in Beziehung setzt. Insbesondere sind diese Zusammenhänge nicht so formal untersucht worden, dass es möglich wäre, eine mathematisch fundierte Gesamtfunktion zu entwickeln.

Im vorliegenden Artikel haben wir versucht, eine grundlegende Zusammenhänge zu beschreiben und zu veranschaulichen. Zu diesem Zweck haben wir auf die Metapher eines Kräftemodells zurückgegriffen und die genannten Konzepte als Kräfte modelliert, die auf die Ausdehnung oder Eingrenzung einzelner Software-Elemente einer Struktur-Ebene wirken. Wir konnten drei Grundkräfte identifizieren:
  • die Internalisierungskraft, die darauf abzielt, Relationen zwischen Subelementen in das Innere von Elementen aufzunehmen (sowie ihre enge Verwandte, die kohäsive Anziehung)
  • die kohäsive Abstoßung, die als Widerstand einzelner Subelemente aufgefasst werden kann, in ein bestimmtes Element aufgenommen zu werden
  • die Überdehnung, die als ein mit der Größe eines Elements immer steiler ansteigender Widerstand aufgefasst werden kann, weitere Subelemente in das Element aufzunehmen.
Die Modellierung von Struktur-Ebenen bewegt sich im Spannungsfeld dieser Kräfte.

6. Quellen

[Lilienthal2008] - Komplexität von Softwarearchitekturen, Carola Lilienthal (2008)

[Sessions2011] - The Mathematics of IT Simplication, Roger Sessions (2011), siehe http://dl.dropboxusercontent.com/u/97323460/WebDocuments/WhitePapers/MathOfITSimplification-103.pdf

[Wang2007] - Software Engineering Foundations - A Software Science Perspective, Wang, Yingxu (2007) 

Mittwoch, 12. November 2014

Einfachheit der Struktur - Kopplung

Der vorherige Blogartikel, der den Zusammenhang zwischen Einfachheit und Kohäsion untersucht hat, führte Kopplung bereits als ein zur Kohäsion komplementäres Konzept ein. Der vorliegende Artikel untersucht nun die Entstehung hoher Kopplungsgrade etwas genauer. Insbesondere werden die folgenden beiden Aspekte betrachtet:
  • Richtige Grenzziehung: Während das Konzept der Kohäsion eher die richtige Größe von Software-Elementen höherer Ebenen in den Vordergrund stellt, liegt der Schwerpunkt des Konzepts der Kopplung auf den richtigen Grenzen dieser Elemente. 
  • Stärke verschiedener Kopplungsarten: Des weiteren kann zwischen verschiedenen Arten der Kopplung unterschieden werden, die hinsichtlich ihrer Stärke unterschiedlich bewertet werden müssen.

1. Die richtigen Grenzen ziehen

Warum der Kopplungsgrad einer Ebene davon abhängt, ob die Grenzen von Software-Elementen höherer Ebenen richtig gezogen werden, soll wieder an einem Beispiel veranschaulicht werden.
Wie im Artikel Einfachheit der Struktur - Grundlagen ausgeführt, ändert sich durch die Gruppierung auf höherer Ebene nichts an den Relationen der darunterliegenden Ebenen. In diesem Beispiel wurden einfach die drei roten Elemente inklusive ihrer bestehenden Relationen in die linke Einheit verschoben. Berechnen wir die Kohäsion eines Elements E nach dem vereinfachten Modell von [Wang2007], d. h. ohne Berücksichtigung der durchschnittlichen Distanz der Subelemente, gemäß der Formel
und berücksichtigen, dass die Kopplung zur Kohäsion in diesem Modell komplementär ist, d. h. Kohäsion + Kopplung = 1, so ergeben sich die folgenden Kohäsions- und Kopplungswerte:

Kohäsion Linkes Element Rechtes Element
Vorher 94,44% 95,00%
Nachher 86,96% 81,25%


Kopplung Linkes Element Rechtes Element
Vorher 5,56% 5,00%
Nachher 13,04% 18,75%

Aus der Sicht der Kohäsion könnte man noch von einem geringen Effekt sprechen. Der Kopplungsgrad hingegen erhöht sich hier um das Zwei- bis Dreifache. Berücksichtigen wir, dass sich gemäß der Studie [Kemerer2005] insbesondere die Kombination geringer Kohäsion und starker Kopplung negativ auf die Komplexität der Software auswirkt, so fällt der negative Effekt dieser falschen Grenzziehung durchaus ins Gewicht.

Dieser Fall mag trivial erscheinen. Im Entwicklungsalltag kann es aber durchaus sein, dass Lösung (2) durch Hinzufügen neuer Elemente allmählich entsteht und dass die Möglichkeit einer Restrukturierung zu Lösung (1) irgendwann erkannt und durchgeführt werden muss. Insbesondere wenn weitere Elemente vom rechten Struktur-Element abhängen, kann dies zu einer Kette von Folgeaufwänden führen, auf die man gerne verzichten würde. Auf Dauer entstehen dann aber hohe Kopplungsgrade zwischen den Elementen der jeweiligen Struktur-Ebene.

2. Die Art der Kopplungen

Im Einzelfall kann die Entscheidung zwischen zwei Grenzziehungen schwerfallen. Ein vereinfachtes Kohäsions-/Kopplungsmodell wie das von Wang, das nur auf der Zahl der internen und externen Relationen beruht, ist dann ggf. nicht mehr in der Lage, zwei Lösungen ausreichend deutlich voneinander zu unterscheiden. In das Kohäsionsmodell hatten wir daher bereits den Faktor Nähe eingeführt, um das Konzept der Zusammengehörigkeit, das der Kohäsion zu Grunde liegt, in die Betrachtung aufzunehmen. Nun gilt es, auch das Kopplungsmodell noch etwas zu verfeinern.

Verschiedene Autoren unterscheiden unterschiedliche Kopplungsarten. Es wäre nun hilfreich, die Kopplungsart in der Abwägung zu berücksichtigen. So schreibt z. B. Balzert:
"Um eine Kopplung zu minimieren, muss die jeweils schwächste Kopplungsart jeder Komponente angestrebt werden." [Balzert1998]
Balzert selbst schlägt folgende Unterscheidungen für Kopplungen auf der Ebene der Funktionen und Daten-Objekte vor:
  • Kopplungsmechanismus
    • Aufruf
    • Verzweigung (goto)
  • Schnittstellenbreite
    • Anzahl der Parameter
    • Datentyp der Parameterelemente (elementar oder strukturiert)
  • Kommunikationsart 
    • Datenkopplung
    • Steuerungskopplung
Eine andere Unterteilung wird in [Aloysius2012] vorgenommen, wobei das umfassende Element jeweils als module bezeichnet wird und ein objektorientiertes Szenario vorausgesetzt wird:
  • Control Coupling: "Passing control flags between modules ...".
  • Global Data Coupling: "Two or more modules share the same global data structures."
  • Internal Data Coupling: "One module directly modifies local data of another module."
  • Data Coupling: "Output from one module is the input of another ...".
  • Lexical Content Coupling: "Some or all the contents of one module are included in the contents of another." (Alle Zitate dieser Liste gemäß [Aloysius2012].)
Eine bereits über 50 Jahre alte Einteilung stammt von Glenford J. Myers [Myers1974]. Hier stammt die entsprechende Zusammenfassung aus dem Wikipedia-Artikel zum Thema Kopplung:
  • "Content coupling: Das Modul verlässt sich auf die konkrete inhaltliche Umsetzung eines anderen Moduls bzw. modifiziert die internen Daten des anderen. Diese sehr starke Art der Kopplung sollte unbedingt vermieden werden.
  • Common coupling: Zwei Module kommunizieren über gemeinsame globale Daten.
  • External coupling: Zwei Module kommunizieren über einen extern vorgegebenen Mechanismus; beispielsweise eine bestimmte Datei mit definiertem Aufbau.
  • Control coupling: Ein Modul nimmt Einfluss auf den Kontrollfluss eines anderen; beispielsweise durch einen Parameter, der die Art der konkreten Aktion spezifiziert. Hierbei ist zu unterscheiden ob der Kontrollparameter ein Aufrufparameter oder ein Rückgabewert ist. Ersteres ist zu vermeiden, letzteres ist manchmal nicht zu ändern. Somit bildet die Kontrollkopplung die Grenze zwischen den „guten“ schwachen und den „schlechten“ starken Kopplungen.
  • Stamp coupling: Zwei Module kommunizieren über eine komplexe Datenstruktur, von der aber nur ein Teil verwendet wird.
  • Data coupling: Zwei Module kommunizieren über elementare Daten, beispielsweise einfache Parameter." [Url:Wikipedia:Kopplung]
Grundsätzlich können wir je nach Betrachtungsgegenstand auch ganz andere Einteilungen der Kopplungsarten vornehmen. Dies kann jedoch nicht der Anspruch dieses Artikels sein. An dieser Stelle sollte jedoch klar geworden sein, dass Kopplungen sich in ihrer Art unterscheiden und dass von der Kopplungsart auch die tatsächliche Stärke jeder einzelnen Kopplung abhängt.

[Aloysius2012] variieren in einem Experiment die von ihnen unterschiedenen Kopplungsarten und ermitteln auf diese Weise kognitive Gewichte, welche die Stärke der Kopplung widerspiegeln sollen. Wir können diesen Ansatz auf beliebige Kopplungsarten verallgemeinern und setzen zu diesem Zweck voraus, dass jede in einem konkreten System gefundene Kopplung einer Kopplungart zugewiesen werden kann, über die ihr ein entsprechendes Gewicht zuzuordnen ist. Dann können wir das folgende verfeinerte Kopplungsmodell angeben:
Bei der Bildung von Elementen auf höheren Struktur-Ebenen müssen die Grenzen also möglichst so gezogen werden, dass starke Kopplungsarten in das Innere der Elemente verschoben werden, während Kopplungen zwischen den Elementen möglichst schwach sein sollten.

3. Andere Kopplungsmodelle

Analog zur Betrachtung der Kohäsion mache ich an dieser Stelle deutlich, dass zahlreiche andere Kopplungsmodelle existieren und verweise auf die entsprechende Literatur (bspw. [Fenton2014], [Sneed2010] oder [Diederichs2005]). Es ist daher für die weitere Betrachtung sinnvoll, die Voraussetzungen explizit zu machen, die wir für Kopplungsmodelle allgemein unterstellen:
  1. Wir haben Kopplung bislang (gemäß dem Modell von Wang) als eine Eigenschaft einzelner Software-Elemente aufgefasst. Wir setzen voraus, dass sich aus den Ausprägungen der Kopplungen der einzelnen Software-Elemente eine Ausprägung der Gesamtkopplung auf System-Ebene ermitteln lässt. Ich nenne diese den Kopplungsgrad des Systems. Wäre dies nicht möglich, so könnten wir uns bei der Minimierung von Kopplungen einzelner Elemente eines Systems nicht sicher sein, ob wir nur lokale Optimierungen vornehmen, die ggf. zu Lasten des Gesamtsystems gehen. Kopplung wäre dann als Eigenschaft unbrauchbar, um Entscheidungen auf System-Ebene zu treffen.
  2. Der Kopplungsgrad zweier verschiedener Systeme S1 und S2 lässt sich vergleichen, d. h. für zwei beliebige Systeme S1 und S2 lässt sich feststellen, ob der Kopplungsgrad von S1 höher, gleich oder niedriger ist. Wäre dies nicht möglich, so würde der festgestellte oder vorhergesagte Kopplungsgrad zweier Lösungen keinen Beitrag zur Entscheidungsfindung zwischen verschiedenen Lösungen leisten können.
  3. Der Kopplungsgrad eines gegebenen Systems bewegt sich zwischen einem Minimum und einem Maximum. Die Zerlegung eines endlichen Systems in Elemente höherer Ebenen kann nicht zu einem unendlich großen Kopplungsgrad führen.

4. Quellen

[Aloysius2012] - Coupling Complexity Metric: A Cognitive Approach, A. Aloysius, L. Arockiam (2012)

[Balzert1998] - Lehrbuch der Softwaretechnik, Helmut Balzert (1998)

[Diederichs2005] - Komplexitätsreduktion in der Softwareentwicklung, Henner Diederichs (2005)

[Fenton2014] - Software Metrics: A Rigorous and Practical Approach, Third Edition, Norman Fenton (2014)

[Kemerer2005] - The Structural Complexity of Software: An Experimental Test - David P. Darcy, Chris F. Kemerer, Sandra A. Slaughter, James E. Tomayko (2005)  

[Myers1974] - Reliable Software through Composite Design, Glenford J. Myers (1974)

[Sneed2010] - Software in Zahlen - Die Vermessung von Applikationen, Harry M. Sneed, Richard Seidl, Manfred Baumgartner (2010)

[Url:Wikipedia:Kopplung] - Wikipedia-Artikel "Kopplung (Softwaretechnik)" (Stand 12.11.2014)

[Wang 2007] - Software Engineering Foundations - A Software Science Perspective, Wang, Yingxu (2007)  

Freitag, 7. November 2014

Einfachheit der Struktur - Kohäsion

Im vorherigen Artikel haben wir uns mit dem Unterschied tatsächlich realisierter System-Strukturen und möglicher System-Strukturen beschäftigt. Wir haben festgestellt, dass beide Aspekte einen Einfluss auf die Einfachheit eines Systems haben:
  • Je mehr tatsächlich realisierte (aktuale) Elemente und Relationen ein System aufweist, desto weniger einfach ist es.
  • Je weniger ein System die Anzahl der möglichen (potentiellen) Elemente und Relationen einschränkt, desto weniger einfach ist es.
In diesem Artikel werden wir uns nun mit dem Zusammenhang zwischen Einfachheit und Kohäsion beschäftigen.

1. Kohäsion im strukturierten Design

In der spezifischen Terminologie des strukturierten Designs von Edward Yourdon und Larry L. Constantine bezeichnet Kohäsion den Grad, in dem die Elemente eines Moduls zusammengehören (engl. "the degree to which the elements of a module belong together" [Yourdon1979]). In dieser Terminologie ist noch klar, von welchen Elementen die Rede ist, nämlich von Modulen im Sinne des strukturierten Designs und ihren inneren Elementen. Dies gilt insbesondere auch für den Zusammenhang zwischen Kohäsion und Kopplung: Während die Kohäsion der Elemente innerhalb eines Moduls hoch sein soll, soll die Kopplung der Module untereinander gering sein. Was ich Kohäsion und was Kopplung nenne, ergibt sich aus dem Zusammenhang: Intramodular spreche ich von Kohäsion, extramodular von Kopplung.

2. Kohäsion aus der Sicht der System-Hierarchie

In Bezug auf moderne Software-Systeme wird Kohäsion jedoch nicht nur als Eigenschaft von Modulen (oder ihren objektorientierten Nachfolgern, den Klassen) gesehen, sondern auch auf andere Ebenen wie Services, Subsysteme, Pakete oder physische Einheiten angewandt. In meinem Blogartikel zum Prinzip der hohen Kohäsion habe ich daher allgemeiner von "Software-Elementen" an Stelle von Modulen gesprochen. 

Im Zuge der Besprechung des allgemeinen Modells für Software-Systeme hat sich gezeigt, dass die verschiedenen Element-Typen, auf die man das Konzept der Kohäsion anwenden kann, hierarchisch strukturiert sind. Jede Betrachungs-Ebene setzt bestimmte Elemente in Relation. Auf der nächst tieferen Ebene enthält jedes dieser Elemente Subelemente, die ebenfalls in Relation zueinander stehen usw. Damit ergibt sich jedoch für die Konzepte der Kohäsion und der Kopplung ein grundlegendes Problem: Aus der Sicht einer bestimmten Ebene (z. B. der Pakete) wird der Zusammenhang der Subelemente dieser Ebene (in Bezug auf Pakete sind dies die Typen) als "Kohäsion" bezeichnet. Aus der Sicht der nächst tieferen Ebene wird jedoch der Zusammenhang derselben Elemente zur "Kopplung". 

Betrachte ich also beispielsweise ein Paket, so resultiert aus der Forderung nach hoher Kohäsion, dass die darin enthaltenen Typen eng zusammengehören sollen. Auf der Ebene der Typen wird jedoch das, was auf Paket-Ebene "hohe Kohäsion" war, zu einer "starken Kopplung". Was aus der Sicht der Paket-Ebene gut war (hohe Kohäsion), wäre demnach aus der Sicht der Typ-Ebene schlecht (starke Kopplung). Wie lässt sich dieser Widerspruch erklären?

3. Die Auflösung des Widerspruchs

Im letzten Artikel hatten wir festgestellt, dass alle Relationen letztlich auf die Ebene der Funktionen und Daten-Objekte zurückzuführen sind. Wir hatten diese Relationen, die entweder zwischen Funktionen und Funktionen oder zwischen Funktionen und Daten-Objekten bestehen, als funktionale Relationen bezeichnet. Relationen auf höheren Ebenen sind lediglich Projektionen der funktionalen Relationen auf die Elemente der höheren Ebene. Für die weitere Erläuterung treffe ich folgende begriffliche Unterscheidung:
  • Eine auf eine Struktur-Ebene E projizierte Relation zwischen zwei Struktur-Elementen dieser Ebene bezeichne ich als externe Relation.
  • Sei die Struktur-Ebene E die aktuelle Betrachtungs-Ebene und die Ebene F die nächst tiefere Ebene. Dann bezeichne ich die Relationen der Ebene F als interne Relationen.
Was eine interne und eine externe Relation ist, hängt somit von der Betrachtungs-Ebene ab. Es ist nun zunächst festzustellen, dass die Anzahl der funktionalen Relationen völlig unabhängig von der Gruppierung der Funktionen und Daten-Objekte in Elementen höherer Ebene ist.  Aus der Sicht des Gesamtsystems ändert sich also die aktuale Strukturkomplexität nicht abhängig davon, wie Funktionen und Daten-Objekte auf höheren Ebenen zusammengefasst werden. 

Hohe Kohäsion bedeutet in diesem Sinne keine Änderung der Kopplung des Gesamtsystems, sondern lediglich eine Bündelung der Kopplungen an bestimmten Positionen in höheren Struktur-Ebenen. Jede solche Struktur-Ebene ist dazu geschaffen, die Elemente der nächst tieferen Ebene zu partitionieren und dabei diejenigen Elemente, die besonders viele Relationen eingehen, aus der Sicht dieser Ebene möglichst nahe aneinander zu positionieren. Betrachten wir zur Veranschaulichung die folgende Abbildung:
Quelle: NASA, via Wikipedia Commons
Bereiche hoher Kohäsion lassen sich mit Ballungsräumen vergleichen. Im Bereich der Software müssen diese Ballungsräume, die tatsächlich lediglich auf der Ebene funktionaler Relationen bestehen, vom Entwickler oder Architekten erkannt und korrekt auf die jeweilige höhere Struktur-Ebene übertragen werden. Erst beim Ziehen der Grenzen dieser höheren Struktur-Elemente tritt das Phänomen der Kohäsion auf: Werden die Grenzen so gezogen, dass sie den Ballungen funktionaler Relationen entsprechen, so wird die Kohäsion der Elemente dieser Ebene hoch und die Kopplung dieser Elemente untereinander gering sein. Im nächsten Abschnitt werde ich diese Übertragungs-Aufgabe an einem Beispiel näher erläutern.

4. Beispiel einer Strukturbildung auf höherer Ebene

Die Abbildung zeigt eine beliebige Struktur, die wir keiner konkreten Ebene zuordnen müssen. Es wäre aber denkbar, dass es sich bei den Elementen um Funktionen und Daten-Objekte handelt und bei den Relationen um Funktionsaufrufe und Zugriffe auf die Daten-Objekte. Ich werde diese Ebene im Folgenden e1 bezeichnen. Auf Grund der Anzahl der Elemente und Relationen erscheint dem Betrachter diese Struktur alles andere als einfach.
Hier wird dieselbe Struktur wie zuvor dargestellt. Die Elemente sind jedoch etwas gruppiert worden. Es fällt auf, dass die Struktur sofort übersichtlicher erscheint.
Die an Hand ihrer Relationen nahe zusammenliegenden Elemente wurden jetzt in ein übergeordnetes Struktur-Element "eingeschlossen". Zwischen den übergeordneten Struktur-Elementen ergeben sich neue (projizierte) Relationen, die gepunktet in das Diagramm eingezeichnet wurden. Aus der Sicht der übergeordneten Struktur-Ebene hat sich die Struktur damit deutlich vereinfacht. Ich nenne diese Ebene im Folgenden die Ebene e2:

Die hier gewählte Aufteilung ist vergleichsweise grob. Es wäre auch eine etwas feinere Aufteilung möglich gewesen:
Wohlgemerkt hat sich auch hier nichts an den Relationen der Ebene e1 geändert, lediglich die Aufteilung der Elemente aus e1 in der Ebene e2 wurde anders vorgenommen. Aus der Sicht von e2 erscheint diese Lösung weniger einfach. Andererseits könnte man der gröberen Aufteilung vorwerfen, dass die einzelnen Struktur-Elemente der Ebene e2 etwas zu groß geraten sind. Vergleichen wir die einzelnen Struktur-Elemente der Ebene e2 in der ersten und zweiten Lösung:
Die Struktur-Elemente der grobgranularen Lösung weisen für sich genommen noch eine beachtliche Komplexität auf, während die Elemente der feingranularen Lösung bereits sehr einfach wirken. Die Frage lautet, ob das Konzept der Kohäsion bei weiterhin rein struktureller Betrachtung (wir blenden also semantische Aspekte bewusst aus) eine Entscheidungshilfe für dieses Problem anbietet. Zu diesem Zweck werde ich Kohäsion im folgenden Abschnitt etwas formaler betrachten.

5. Kohäsion nach Wang

[Wang2007] stellt ein Modell der Kohäsion vor, das sich sehr allgemein auf Systeme und Subsysteme anwenden lässt und damit für unsere Zwecke ein guter Ausgangspunkt ist. Ich werde im Folgenden, um die hier eingeführte Terminologie beizubehalten, allgemein von Elementen und Subelementen sprechen. Als "Element" bezeichne ich dabei die aktuell betrachtete Einheit einer bestimmten Ebene. Als "Subelement" bezeichne ich die Einheiten der nächst tieferen Ebene, die durch dieses Element gruppiert werden.

Jedes Element weist die folgenden Relationen auf:
  • Ri: eingehende Relationen (Input)
  • Ro: ausgehende Relationen (Output)
  • Rc: interne Relationen zwischen den Subelementen des Elements
Wang definiert nun die Kohäsion eines Elements E wie folgt:
Kohäsion und Kopplung sind in diesem Modell komplementär, d. h. es gilt: Kohäsion + Kopplung = 1. Das Modell ist insbesondere deshalb interessant, weil Kohäsion kein bloßes Attribut der betrachteten Einheit ist, sondern die externen Relationen dieser Einheit mitbetrachtet. Hohe Kohäsion führt hier automatisch zu schwacher Kopplung und umgekehrt.

Wenn wir diese Betrachtungsweise auf die beiden Lösungsansätze (grobgranular / feingranular) des vorherigen Absatzes anwenden, so zeigt sich, dass die grobgranulare Lösung über erheblich mehr interne Relationen verfügt und somit den besseren CH-Wert aufweist. Die Kohäsion wächst also mit der Anzahl der internen Relationen, so lange dabei nicht auch die externen Relationen wachsen. 

Das Problem dieser Betrachtungsweise ist, dass die Anzahl und Anordnung der Elemente nicht berücksichtigt wird. Es widerspricht der Grundidee der Kohäsion als "degree to which the elements belong together" dass Elemente, in die immer mehr Subelemente und ihre Relationen aufgenommen werden, zu immer höherer Kohäsion führen. 

Tatsächlich zielt die Kohäsion letztlich auf eine Größenbeschränkung ab: Es sollen eben gerade nicht Subelemente zusammengefasst werden, die nicht zusammengehören. Je mehr Subelemente ein Element enthält, desto größer wird jedoch die Wahrscheinlichkeit, dass diese Subelemente nicht alle zusammengehören.

6. Anpassung von Wangs Kohäsions-Modell

Um diesen Mangel an Wangs Kohäsionsmodell besser zu verstehen, betrachten wir die folgenden beiden Lösungen, wobei die linke Lösung der oben gezeigten grobgranularen Lösung entspricht:
Die Lösungen (a) und (b) weisen dieselbe Anzahl von Elementen und Relationen und somit auch einen identischen CH-Wert auf (gleiche externe Relationen vorausgesetzt). In Lösung (b) gruppieren sich jedoch die Subelemente um ein Zentrum, was den Eindruck großer Zusammengehörigkeit vermittelt. Es ist kaum vorstellbar, dass es sinnvoll sein könnte, eines der Subelemente in ein anderes Element zu verlagern. Ganz anders bei Lösung (a). Die Zusammengehörigkeit erscheint hier viel weniger stark, und es ist durchaus nicht klar, ob eine weitere Partitionierung (siehe feingranulare Lösung oben) nicht doch sinnvoller sein könnte.

Eine Möglichkeit, diesen Unterschied auszudrücken, besteht in der Berücksichtigung der Distanzen zwischen den Subelementen. Ignoriert man die Gerichtetheit der Relationen, so kann man zwischen je zwei Subelementen einen kürzesten Pfad finden, der diese beiden Subelemente verbindet. In Lösung (a) liegt die durchschnittliche kürzeste Distanz etwas über 4, in Lösung (b) liegt sie bei 2. Die maximale durchschnittliche kürzeste Distanz entsteht bei Ketten oder Kreisen und liegt bei maxavg_dist = (n - 1) * n / 2. Die minimale durchschnittliche kürzeste Distanz entsteht bei vollständigen Graphen und beträgt minavg_dist = n - 1. Je näher sich die durchschnittliche kürzeste Distanz dem Wert minavg_dist nähert, desto weniger scheinen die Subelemente zusammengehörig. 

Wir können uns vorstellen, dieses Konzept auf einen Faktor zwischen 0 und 1 zu normalisieren. Der Faktor nimmt den Wert 0 an, wenn der Graph der Subelemente aus unverbundenen Teilgraphen besteht. Er nimmt den Wert 1 an, wenn jedes Subelement in direkter Relation zu jedem anderen Subelement steht, also für vollständige Graphen. Bezeichnen wir diesen Faktor als Nähe, so lässt er sich wie folgt in die Kohäsionsformel von Wang integrieren:
Auch diese Lösung differenziert verschiedene Formen der Kohäsion noch nicht perfekt. Ein Problem des Konzepts der Nähe ist, dass es im Einzelfall durchaus sinnvoll sein kann, Verkettungen der folgenden Art zu konstruieren:
Derartige Konstrukte können Pipelines oder auch geschachtelte Funktionsaufrufe sein, die im Einzelfall gerechtfertigt sind und faktisch auch eine große Zusammengehörigkeit aufweisen. Andererseits sind sehr lange Verkettungen dieser Art doch eher eine Seltenheit.

7. Andere Kohäsionsmodelle

Das Kohäsionsmodell von Wang setzt interne Relationen zu externen Relationen in ein Verhältnis. Insbesondere im Kontext der Software-Messung wurden jedoch zahlreiche andere Vorschläge zur Modellierung von Kohäsion gemacht. Da es die Möglichkeiten eines einzelnen Artikels übersteigen würde, all diese Ansätze zusammenzufassen, sei an dieser Stelle auf die einschlägige Literatur verwiesen. Übersichten vorgeschlagener Kohäsionsmaße geben bspw. [Fenton2014], [Sneed2010] oder [Diederichs2005].

Für die spätere Betrachtung von Kohäsion auf System-Ebene sowie ein besseres Gesamtverständnis dafür, wie Kohäsion und Kopplung im Zusammenspiel die Komplexität von Software-Systemen beeinflussen, möchte ich an dieser Stelle jedoch einige Annahmen explizit machen, die wir beim Nachdenken über Kohäsion oftmals unausgesprochen voraussetzen:
  1. Wir haben Kohäsion bislang als eine Eigenschaft einzelner Software-Elemente aufgefasst. Wir setzen voraus, dass sich aus den Ausprägungen der Kohäsionen der einzelnen Software-Elemente eine Gesamtkohäsion auf System-Ebene ermitteln lässt. Ich nenne diese den Kohäsionsgrad des Systems. Wäre dies nicht möglich, so könnten wir uns bei der Zusammenfassung der Elemente eines Systems nicht sicher sein, ob wir nur lokale Optimierungen vornehmen, die ggf. zu Lasten des Gesamtsystems gehen. Kohäsion wäre dann als Eigenschaft unbrauchbar, um Entscheidungen auf System-Ebene zu treffen.
  2. Der Kohäsionsgrad zweier verschiedener Systeme S1 und S2 lässt sich vergleichen, d. h. für zwei beliebige Systeme S1 und S2 lässt sich feststellen, ob der Kohäsionsgrad von S1 höher, gleich oder niedriger ist. Wäre dies nicht möglich, so würde der festgestellte oder vorhergesagte Kohäsionsgrad zweier Lösungen keinen Beitrag zur Entscheidungsfindung zwischen verschiedenen Lösungen leisten können.
  3. Der Kohäsionsgrad eines gegebenen Systems bewegt sich zwischen einem Minimum und einem Maximum. Die Annahme einer unendlich großen Zusammengehörigkeit ist ebenso sinnlos wie die Annahme einer unendlich großen Zusammengehörigkeit.
Ich möchte an dieser Stelle nicht näher untersuchen, warum diese Annahmen getroffen werden können. Ohne diese Voraussetzungen wäre Kohäsion als Eigenschaft von Software-Systemen jedoch nur sehr eingeschränkt nützlich.
 

8. Kohäsion und Einfachheit

Warum steigert hohe Kohäsion die Einfachheit einer Struktur? 
  • Hohe Kohäsion auf einer Struktur-Ebene geht mit einer geringeren Anzahl von Relationen auf der nächst höheren Struktur-Ebene einher. Diese nächst höhere Ebene wird daher als einfacher wahrgenommen.
  • Die Forderung nach enger Zusammengehörigkeit (engl. togetherness) verhindert ein übermäßiges Wachstum der einzelnen Einheiten. Jede Einheit weist für sich genommen eine kompakte und dichte Struktur auf, die im Vergleich zu einer weitläufigen und verstreuten Struktur als einfacher wahrgenommen wird.
  • Allgemein führt die enge Zusammengehörigkeit der Elemente in einer kohäsiven Einheit dazu, dass die Einheit als ein sinnvolles Ganzes wahrgenommen wird. Der Umgang mit sinnvollen Einheiten ist einfacher als der Umgang mit Einheiten, deren Bedeutung nicht klar umrissen ist.

9. Empirische Bestätigung

Das hier vorgestellte Kohäsionsmodell und der Zusammenhang zwischen Kohäsion und Einfachheit wird durch die Untersuchung "The Structural Complexity of Software" von C. F. Kemerer und Kollegen [Kemerer2005] empirisch unterstützt. Die Untersuchung trifft folgende Annahmen:
  • Komplexität wird in Form von Aufwand (engl. effort) bei der Durchführung von Wartungsaufgaben operationalisiert.
  • Kohäsion und Kopplung eines Beispielprogramms werden systematisch modifiziert, so dass sich die vier Varianten (1) geringe Kohäsion/geringe Kopplung, (2) geringe Kohäsion, starke Kopplung, (3) hohe Kohäsion/geringe Kopplung und (4) hohe Kohäsion/starke Kopplung ergeben. Dieses Programm wird erfahrenen Software-Entwicklern zwecks Durchführung einer Wartungsaufgabe übergeben. Die Zeit zur Durchführung der Aufgabe wird gemessen und als Maß für den erforderlichen Aufwand interpretiert.
Ein wesentliches Ergebnis der Studie ist, dass geringe Kohäsion insbesondere im Zusammenhang mit starker Kopplung (Variante (2) zu einer deutlichen Komplexitätssteigerung führt. Es wird die folgende Schlussfolgerung gezogen:
"The implication of this result is that when designing, implementing, and maintaining software to control complexity, both coupling and cohesion should be considered jointly, instead of independently." [Kemerer2005]
Das oben vorgeschlagene Kohäsions-Modell wird dieser Forderung gerecht, indem Kohäsion als Funktion sowohl der internen wie auch der externen Relationen betrachtet wird.

10. Zusammenfassung

In diesem Artikel haben wir den Zusammenhang zwischen Einfachheit und Kohäsion aus einer strukturellen Perspektive untersucht. 

Dabei war zunächst das Konzept der Kohäsion, das ursprünglich nur auf eine klar definierte Struktur-Ebene angewandt wurde, auf eine Hierarchie von Struktur-Ebenen zu übertragen, wie man sie in modernen Software-Systemen antrifft. Es wurde festgestellt, dass die Eigenschaft der Kohäsion erst bei der Bildung von Elementen höherer Struktur-Ebenen auftritt. Erfolgt die Grenzziehung bei der Bildung solcher Elemente richtig, so wird die Kohäsion maximiert und gleichzeitig die Kopplung unter den Elementen der neuen Ebene minimiert. 

Das Kohäsionsmodell von Wang spiegelt diesen Zusammenhang in einem einfachen Verhältnis der internen Relationen zur Summe der internen und externen Relationen. Um dem Größenwachstum der einzelnen Elemente entgegenzuwirken wurde zusätzlich das Konzept der Nähe eingeführt. Sind sich die Subelemente eines Elements im Durchschnitt weniger nahe, so führt dies zu einer Schwächung der Kohäsion. 

Die Grenzen dieses Modells sind im Bereich der Semantik anzutreffen und gehen somit über die hier angestellte rein strukturelle Betrachtung hinaus. Semantische Kohäsionskonzepte wie z. B. das Single-Responsibility Prinzip sind im Einzelfall immer erforderlich, um die strukturelle Sicht zu ergänzen.

10. Quellen

[Diederichs2005] - Komplexitätsreduktion in der Softwareentwicklung, Henner Diederichs (2005)

[Fenton2014] - Software Metrics: A Rigorous and Practical Approach, Third Edition, Norman Fenton (2014)

[Kemerer2005] - The Structural Complexity of Software: An Experimental Test - David P. Darcy, Chris F. Kemerer, Sandra A. Slaughter, James E. Tomayko (2005) 

[Sneed2010] - Software in Zahlen - Die Vermessung von Applikationen, Harry M. Sneed, Richard Seidl, Manfred Baumgartner (2010)

[Wang 2007] - Software Engineering Foundations - A Software Science Perspective, Wang, Yingxu (2007) 

[Yourdon1979] -  Structured design. Fundamentals of a discipline of computer program and systems design, Yourdon, E., Constantine, L. (1979)