Übung aus Software Engineering, WS03/04
Entwürfe zum Metriktool
[JHF, 16.1.2004]

Vorwort

V.1 Die hier zur Diskussion gestellten Entwürfe sind drei Varianten A, B, (Variante B in C#) und C des gleichen Lösungsansatzes für ein Werkzeug zur Verwaltung von Messobjekten.
V.2 Die Darstellungen konzentrieren sich auf strukturelle Zusammenhänge zwischen Klassen aus dem Anwendungsbereich in Form von Klassendiagrammen. Der Lösungsansatz soll grundsätzliche Lösungsideen vermitteln und das Verständnis von objektorientierten Begriffen und Klassendiagrammen vertiefen. Der Lösungsansatz deckt jedoch nicht vollständig den funktionalen Umfang der gestellten Aufgabe (Verwaltung von Messobjekten) ab. Der Lösungsansatz kann sich durch die Berücksichtigung weiterer Anforderungen aus dem Anwendungsbereich ändern.
V.3 Die Klassendiagramme sind in einer UML-ähnlichen Notation dargestellt. Es wird davon ausgegangen, dass der Leser mit der UML-Notation für Klassendiagramme grundsätzlich vertraut ist. Abweichungen oder aus der Sicht des Verfassers selten verwendete Darstellungselemente werden erläutert (siehe Abschnitt Notation) z.T. sind die Erläuterungen direkt in den Klassendiagrammen enthalten. Ausführliche Informationen zu UML finden Sie z.B. hier [1][2].

Variante A

Bemerkungen zur Variante A

A.1 Zusammengehörende Funktionen von Metrikobjekten und Aggregatobjekten sind in Typdeklarationen (Interfaces) zusammengefasst, zum Einen in den Interfaces ICounter und ICompositeCounter und zum Anderen im Interface IComposite.
A.2 Ein Aggregatobjekt, d.h. ein Objekt der Klasse, die das Interface IComposite implementiert, kann beliebige Metrikobjekte, d.h. Objekte von Klassen, die ICounter implementieren, enthalten (Synonym: aggregieren). Das ist typunsicher, weil dadurch z.B. ein Objekt der Klasse CDirectory eine Objekt der Klasse CMethod enthalten könnte, obwohl im zu modellierenden Gegenstandsbereich eine Methode in einem Dateiverzeichnis (Englisch: Directory) nicht enthalten sein kann. Daher signalisiert die Methode "void Add(ICounter element)" eines Aggregatobjektes eine AggregationException, wenn ein Teilobjekt (Parameter element) konzeptionell nicht zu dem Aggregatobjekt passt (vergleiche mit Bemerkungen B.2, C.1).
A.3 Die Klassen CDirectory, CFile, CClass und CMethod besitzen jeweils eine gleichnamige und gleich gestaltete Assoziation contains, die jeweils die gleiche Aufgabe erfüllt: Teilobjekte aggregieren. Diese Instanzvariable kann in eine gemeinsame Oberklasse ausgelagert werden (vergleiche mit Bemerkung B.3)
A.4 Zur Bedeutung der Attribute der Interfaces ICounter und ICompositeCounter:
- int ICounter.Sum: Liefert die Anzahl der Elemente eines Messobjektes, z.B. die Anzahl der Klassen in einer Datei, oder die Anzahl der Dateien und Unterverzeichnisse eines Verzeichniss.
- float ICompositeCounter.Average: Liefert die durchschnittliche Anzahl aller indirekten Elemente eines Elements, z.B. die durchschnittliche Anzahl der Codezeilen (LOC1) aller Methoden einer Klasse und die durchschnittliche Anzahl der Methoden aller Klassen einer Datei.
- Dictionary ICompositeCounter.SumPerElement: Liefert die Anzahl aller indirekten Elemente eines Elements in Form einer Tabelle (Dictionary), z.B. die Anzahl der Codezeilen (LOC1) pro Methode einer Klasse.
A.5 Eine gerichtete, strichlierte Linie kennzeichnet implements-Beziehungen zwischen einer Klasse und einem Interface eindeutig. Um das Lesen zu erleichtern, werden implements-Beziehungen zusätzlich (redundant) mit dem Stereotyp <<implements>> markiert.

Variante B

Bemerkungen zur Variante B [Umsetzung in C#]

B.1 Diese Lösungsvariante kommt ohne Interfaces aus.
B.2 Die Methode "void Accept(Type element)" der Klasse CCompositeCounter erwartet als Parameter die Klasse (reflektive Programmierung) von Teilobjekten eines Aggregatobjekts. Dabei müssen zur Programmlaufzeit als Argumente des Parameters type die Klasse CCounter oder einer ihrer Unterklassen übergeben werden. Zum Beispiel ist es sinnvoll, dass ein CDirectory ausschließlich Objekte der Klasse CFileSystemElement akzeptiert und ein CFile akzeptiert ausschließlich Objekte der Klasse CClass. Damit kann auch die Implementierung der Methode "void Add(CCounter element)" in die Oberklasse aller Aggregatklassen CCompositeCounter ausgelagert werden. Die Implementierung dieser Methode kann die Typsicherheit für alle Aggregatklassen dynamisch garantieren (vergleiche mit Bemerkungen A.2, C.1).
B.3 Die Instanzvariable contains ist in die Klasse CCompositeCounter ausgelagert (Synonyme: ausgeklammert, faktorisiert). CCompositeCounter ist die gemeinsame Oberklasse aller Klassen, die Aggregatobjekte beschreiben (vergleiche mit Bemerkung A.3).

Variante C

Bemerkungen zur Variante C

C.1 Die generische Klasse CCompositeCounter (die Klasse der Aggregatobjekte, CCompositeCounter<T ...>) gewährleistet die statisch typsichere Implementierung von Aggregatobjekten. CCompositeCounter kann nur mit der Klasse CCounter oder einer ihrer Unterklassen parametrisiert werden (CCompositeCounter <T requires CCounter>). Vergleiche mit Bemerkungen A.2, B.2.
C.2 Java und C# werden in den kommenden Versionen generische Klassen unterstützen (nähere Informationen zu generischen Klassen in C# 2.0 und Java).

Notation

N.1 Alle Assoziationen eines Klassendiagramms können traversiert werden. Eine Assoziation ohne Pfeil kann in beide Richtungen traversiert werden. Andernfalls geben Pfeilspitzen Traversierungsrichtungen an.
N.2 Eine Restriktion beschreibt eine Assoziation oder Klasse genauer.
Eine Restriktion ist in { ... } eingeschlossen.
N.3 Ein Stereotyp klassifiziert Modellelemente bzw. erläutert die Bedeutung von Modellelementen näher.
Ein Stereotyp ist in << ... >> eingeschlossen.
N.4 Parameter von generischen Klassen werden nach dem Namen der generischen Klasse (Synonyme: parametrisierte Klasse, Schablone, Template) in < ... > eingeschlossen. Die genereische Klasse kann an den Klassenparameter Mindestandforderungen stellen mit dem Schlüsselwort requires, z.B. <T requires CCounter>.  
N.5 Namen von Klassen beginnen mit einem C, Namen von Interfaces mit einem I und Namen von Aufzählungstypen mit einem E, z.B. CFile bezeichnet eine Klasse, ICounter bezeichnet ein Interface und ECalculationBase bezeichnet einen Aufzählungstyp.
N.6 Attribute werden nach Methoden angeführt.
N.7 Abgeleitete Attribute beginnen mit /, z.B. /version. Werte von abgeleiteten Attributen werden berechnet.