next up previous contents
Next: 1.8 Weitergehende Information Up: 1. Messen und Maße Previous: 1.6 Vorhersage und Validation

Unterabschnitte

  
1.7 Beispiel: Objektorientierte Entwurfsmaße

Chidamber und Kemerer (CK) haben 1991 einen Satz von Maßen zur Beurteilung objektorientierter Entwürfe vorgeschlagen. In [CK94] werden diese Maße ausführlich beschrieben und anhand empirischer Daten diskutiert. Die Daten entstammen zwei großen industriellen Klassensammlungen (eine in C++ und eine in Smalltalk) von zwei verschiedenen Firmen und umfassen hunderte von Klassen.

Basili, Briand und Melo (BBM) haben 1995 die gleichen Maße im Hinblick auf ihre Eignung zur Vorhersage der Fehleranfälligkeit von Klassenimplementationen validiert. Datenquelle hier waren 8 Implementationen eines Softwaresystems für eine hypothetische Videothek, die von Studenten in einem Praktikum über 4 Monate entwickelt wurden. Die Systeme wurden dabei mit OMT modelliert und mit C++ und verschiedenen Bibliotheken implementiert.

Die Analyse zur Validation bestimmte die Signifikanz $\alpha$, mit der jedes Maß zur Vorhersage verwendet werden kann, ob mindestens ein Fehler in der Testphase gefunden werden wird oder nicht (binäre Antwort). Diese Vorhersage wird mit einem logistischen Regressionsmodell gemacht, das die Form

\begin{displaymath}\log\left(\frac{p}{1-p}\right) = C_0 + C_1 M
\end{displaymath}

hat. Dabei ist M der jeweilige Meßwert und p die Wahrscheinlichkeit, daß ein Fehler auftritt. C0, C1 sind die freien Parameter des Modells, die mittels der logistischen Regression aus den Daten berechnet werden. Die Signifikanz gibt die Wahrscheinlichkeit dafür an, daß ein aus den Daten berechneter Zusammenhang nur zufälliger Natur ist, also das wahre C1 gleich Null ist; eine ,,hohe Signifikanz`` liegt vor, wenn $\alpha$ klein ist, dann ist ein Zufall unwahrscheinlich. Ferner kann berechnet werden, wie groß der Anteil der Varianz in der Variablen ,,Fehler tritt auf`` ist, der sich mit Hilfe des Modells erklären läßt. Dieser Wert wird als R2 bezeichnet; ist er 0, so hat das Modell überhaupt keine Erklärungskraft, ist er 1, so beschreibt das Modell einen funktionalen Zusammenhang, es ist also perfekt.

BBM unterschieden drei Teilsysteme ihrer Anwendung: GUI (graphische Benutzerschnittstelle), TUI (textuelle Benutzerschnittstelle) und DB (Datenbankoperationen). Ferner wurde bei Klassen, die auf Basis einer existierenden Klasse der Bibliothek entwickelt wurden, zwischen unverändert, leicht verändert (bis 25% Änderung) und stark verändert unterschieden.

Alle folgenden Maße werden auf jeweils eine Klasse angewendet.

1.7.1 Gewichtete Methoden pro Klasse (WMC)

,,Weighted Methods per Class``: WMC = $\sum_{Methods\:i} c_i$ wobei ci die Komplexität der Methode i ist, die aufgrund irgendeines beliebigen Komplexitätsmaßes berechnet werden kann. Sowohl bei CK als auch bei BBM wird hierfür immer die Konstante 1 eingesetzt.

Bedeutungen und Beobachtungen laut CK:

1.
Vorhersage des Aufwands zur Entwicklung und Wartung der Klasse.
2.
Hohe Zahl an Methoden bedeutet großen Einfluß auf Unterklassen (wegen Vererbung).
3.
Klassen mit vielen Methoden sind meist anwendungsspezifischer und deshalb schlechter wiederverwendbar.
Beobachtungen: CK fanden, daß die Anzahl der Klassen mit steigendem WMC in beiden Firmen exponentiell schnell abnimmt, trotz unterschiedlicher Anwendungsgebiete, Projektmannschaften und Programmiersprachen.

BBM fanden eine Signifikanz von $\alpha = 0.06$, was auf eine mäßige Brauchbarkeit von WMC zur Vorhersage von Fehlern hindeutet, 0.7% der Varianz des Fehlerauftretens können mittels WMC erklärt werden; hoher WMC bedeutet höhere Wahrscheinlichkeit eines Fehlers. Für bestimmte Klassenarten waren die Ergebnisse besser: Bei neuen und stark veränderten Klassen ist die Signifikanz 0.0003 und 2.4% der Varianz werden erklärt. Bei GUI- und TUI-Klassen ist die Signifikanz 0.001 und 4.7% der Varianz werden erklärt.

1.7.2 Tiefe im Vererbungsbaum (DIT)

,,Depth of Inheritance Tree``: DIT = Länge des längsten Pfades von der Klasse zur Wurzel ihres Vererbungsbaums. Bei Einfachvererbung gibt es nur einen Pfad, bei Klassen ohne Oberklasse ist das Ergebnis 0.

Bedeutungen laut CK:

1.
Je tiefer eine Klasse in der Hierarchie, desto schwieriger wird es, ihr Verhalten vorherzusagen, weil sie mehr und mehr Code von Oberklassen erbt.
2.
Tiefere Bäume haben höhere Entwurfskomplexität, weil mehr Methoden und Klassen involviert sind.
3.
Je tiefer eine Klasse in der Hierarchie ist, desto höher ist ihr Potential für die Wiederverwendung von Methoden.
Beobachtungen: CK fanden Mediane für DIT von 1 bzw. 3. Sie behaupten, daß die DIT-Verteilung es erlaubt zu entscheiden, ob ein Entwurf ,,kopflastig`` sei, also zu viele Klassen zu weit oben in der Vererbungshierarchie hat, oder ,,fußlastig``, also zu viele Klassen zu tief in der Hierarchie, wobei Kopflastigkeit auf zu schlechte Ausnutzung der Wiederverwendungsmöglichkeiten hindeute. CK vermuten, daß diese Möglichkeiten zugunsten leichterer Verständlichkeit des Entwurfs geopfert werden. Sie stufen beide betrachteten Klassensammlungen als kopflastig ein.

BBM fanden mit einer Signifikanz von $\alpha = 0.0000$, daß hohe DIT Fehler vorhersagt, DIT erklärt 6.5% der Varianz. Dieses Ergebnis bedeutet, daß zumindest im Hinblick auf Fehler, kopflastige Entwürfe klar besser sind -- jedenfalls im Experiment von BBM.

1.7.3 Zahl von Unterklassen (NOC)

,,Number of Children``: NOC = Zahl direkter Unterklassen der Klasse.

Bedeutungen laut CK:

1.
Je größer die Zahl der Unterklassen, umso höher die Wiederverwendung, da Vererbung eine Form der Wiederverwendung ist.
2.
Je größer die Zahl der Unterklassen, desto höher die Wahrscheinlichkeit von falscher Abstraktion in der Oberklasse und die Wahrscheinlichkeit, daß die Vererbung mißbraucht wurde.
3.
Je größer die Zahl der Unterklassen, desto mehr Einfluß hat die Klasse auf den Gesamtentwurf. Sie sollte deshalb z.B. sorgfältiger getestet werden.
Beobachtungen: CK fanden wiederum sehr ähnliche Verteilungen in beiden Firmen. Etwa 70% der Klassen hat gar keine Kinder. NOC kann benutzt werden, um zu prüfen, inwieweit ggf. die jeweilige vorgegebene Entwurfsphilosophie (entweder möglichst tiefe Vererbungshierarchien für starke Wiederverwendung oder möglichst flache für bessere Effizienz und leichtere Verständlichkeit) eingehalten wird.

BBM fanden mit Signifikanz von $\alpha = 0.0000$, daß Klassen mit hoher NOC eine geringere(!) Fehlerwahrscheinlichkeit aufweisen, wobei 14% der Varianz erklärt werden. Sie erklären das damit, daß die meisten Klassen höchstens eine Unterklasse haben und eine hohe Zahl von Unterklassen bei unverändert wiederverwendeten Klassen auftritt. Allerdings ist die Signifikanz für nur neue oder geändert wiederverwendete Klassen immer noch 0.0011, so daß diese Erklärung nicht recht überzeugt. Vielleicht ist der relevante Effekt der, daß eine Klasse, von der weitere Klassen abgeleitet werden, sorgfältiger entworfen und implementiert und besser verstanden wird. Inwieweit dieser Effekt auf andere Projekte und Teams zu übertragen ist, läßt sich nicht sagen.

1.7.4 Kopplung zwischen Objektklassen (CBO)

,,Coupling Between Object Classes``: CBO = Anzahl von anderen Klassen, aus denen Methoden dieser Klasse Methoden oder Instanzvariablen verwenden.

Bedeutungen laut CK:

1.
Hohe Kopplung vermindert die Möglichkeit zur Wiederverwendung der Klasse in einer anderen Anwendung.
2.
Hohe Kopplung vermindert die Modularität und Kapselung von Klassen und erhöht ihre Empfindlichkeit gegen Änderungen an anderen Stellen des Entwurfs.
3.
Das Kopplungsmaß erlaubt vorherzusagen, wie schwierig das Testen der Klasse wird bzw. wie sorgfältig dabei vorgegangen werden sollte.
Beobachtungen: CK fanden, daß der Median von CBO bei C++ gleich Null war, bei Smalltalk hingegen gleich 9 und zwar wohl deshalb, weil in Smalltalk auch elementare Datentypen Klassen sind, ebenso die Kontrollflußkonstrukte wie if, while und repeat. Die mittlere CBO wächst mit der Größe der Klassenmenge.

BBM fanden eine Signifikanz von $\alpha = 0.0000$ für hohe Fehlerwahrscheinlichkeit bei hoher CBO, welche im logistischen Regressionsmodell 6.8% der Varianz erklären kann.

1.7.5 Antwortmenge einer Klasse (RFC)

,,Response for a Class``: RFC = Gesamtanzahl verschiedener Methoden, die von irgendeiner Methode der Klasse direkt aufgerufen werden.

Bedeutungen laut CK:

1.
Große Antwortmengen machen das Testen und Debuggen schwieriger, weil mehr Code verstanden werden muß.
2.
Eine große Antwortmenge bedeutet eine hohe Komplexität der Klasse.
Beobachtungen: CK fanden, daß die Anzahl von Klassen wieder exponentiell mit steigendem RFC fällt und bei Smalltalk erheblich höher liegt als bei C++. Es gibt jeweils eine kleine Zahl von Klassen mit sehr hoher RFC; dies sind meist Schnittstellenklassen, die sich laut CK gut als strukturelle Treiber zum Systemtesten eignen. Auch RFC erlaubt eine Untersuchung des Entwurfs von Klassenhierarchien.

BBM fanden eine Signifikanz von $\alpha = 0.0000$ für hohe Fehlerwahrscheinlichkeit bei hoher RFC, die 6.5% der Varianz erklärt. Die Vorhersageeignung war am höchsten für die neuen oder stark geänderten Klassen (25% der Varianz erklärt) und für die UI-Klassen (36% der Varianz erklärt).

1.7.6 Mangel an Zusammenhang zwischen Methoden (LCOM)

,,Lack of Cohesion in Methods``: LCOM = max (|N| - |S|, 0), wobei N die Menge von Methodenpaaren ist, bei der die zwei Methoden eines Paares keine Instanzvariable gemeinsam benutzen (no sharing) und S die Menge von Methodenpaaren mit gemeinsamer Nutzung von mindestens einer Instanzvariablen (sharing). Eine solche gemeinsame Benutzung erzeugt einen Zusammenhang zwischen zwei Methoden. Das Maß gibt also an, wieviel mehr unzusammenhängende Paare von Methoden es gibt als zusammenhängende, wobei ein Überwiegen von zusammenhängenden abgeschnitten wird (also negative Werte nicht zugelassen sind, sondern auf Null abgebildet werden).

Bedeutungen laut CK:

1.
Zusammenhang ist wünschenswert, weil er Kapselung unterstützt.
2.
Mangel an Zusammenhang zeigt an, daß die Klasse wahrscheinlich in zwei Klassen aufgespalten werden sollte.
3.
Ein Maß für Verschiedenheit von Methoden hilft beim Entdecken von Entwurfsfehlern.
4.
Geringer Zusammenhang erhöht die Komplexität und die Wahrscheinlichkeit von Fehlern beim Entwicklungsprozeß.
Beobachtungen: CK fanden für ihre zwei Klassenmengen einen Median von LCOM von 0 bzw. 2. Das Maximum war bei den C++-Klassen 200, bei den Smalltalk-Klassen 17. LCOM eignet sich gut, um zu beurteilen, ob das Zusammenhangsprinzip ausreichend eingehalten wird.

BBM fanden für keine ihrer Teilmengen, daß LCOM signifikant die Vorhersage von Fehlern erlaubt. Sie führen das darauf zurück, daß das künstliche Abschneiden negativer Werte die meisten ihrer Klassen mit dem Wert 0 versieht und deshalb Klassen mit sehr unterschiedlich gutem Zusammenhang gleich bewertet werden. Diese künstliche Modifikation erscheint in diesem Licht also als glatter Entwurfsfehler bei der Definition des Maßes.

1.7.7 Diskussion

Es handelt sich bei den vorgelegten Maßen um insgesamt durchaus nützliche Grundlagen für Vorhersagesysteme, wobei die Nützlichkeit und Aussagekraft zwischen den einzelnen Maßen doch erheblich schwankt.

Bemerkenswert ist die unterschiedliche Sichtweise der beiden angeführten Arbeiten: CK benutzen den Satz von Maßen als Ideenlieferant für die Bewertung von Entwürfen. Zu jedem Maß gibt es mehrere Überlegungen zu möglichen Bedeutungen gewisser Meßwerte, wobei sich diese Überlegungen zum Teil sogar widersprechen. Die Betrachtung des Histogramms der Meßwertverteilung wird als Mittel zur qualitativen Beurteilung gewisser Entwurfseigenschaften von Klassenmengen angesehen. Der ganze Ansatz dokumentiert eine Einstellung der Art ,,wir haben da so einen Satz netter Maße, jetzt laßt uns doch mal schauen, was man damit vielleicht anfangen kann``. Zwar treffen CK mehrere Aussagen der Art ,,mit dem Maß XY läßt sich dieses oder jenes beurteilen``, aber nachgewiesen sind diese Behauptungen noch nicht, es handelt sich lediglich um Vermutungen.

Demgegenüber haben BBM ein klares Ziel: Sie wollen vorhersagen, welche Klassen voraussichtlich Fehler haben werden. Mit einer solchen Vorhersage kann man den Entwicklungsprozeß so steuern, daß kritische Klassen besonders sorgfältig implementiert und getestet werden, um die Qualität der Software insgesamt zu optimieren. Mit diesem klaren Ziel können BBM eine erheblich strukturiertere Vorgehensweise in der empirischen Untersuchung verwenden, die tatsächlich den Namen Validierung im oben eingeführten Sinne verdient. Sie haben eine Hypothese, die klar genug ist, um mit statistischen Methoden getestet werden zu können, nämlich daß ein Maß die Vorhersage von Fehlern besser erlaubt als eine optimale Zufallsentscheidung. Durch die Erklärung der Varianz kann die Nützlichkeit jedes Maßes zur Vorhersage bei Zutreffen der Hypothese auch quantitativ beschrieben werden.

Bei BBM ergibt sich als klare Aussage, daß RFC, DIT und eventuell auch NOC brauchbare Hinweisgeber auf fehleranfällige Klassen darstellen und das LCOM anders definiert werden sollte. Bei CK bleiben hingegen die Erkenntnisse vage und allgemein. Dies verdeutlicht, wie wichtig ein erkenntnisorientiertes Vorgehen bei der Validierung von Maßen ist. Optimal wäre es, den zielorientierten Ansatz von BBM mit den industriellen Daten von CK auszuführen. Solche Vorhaben scheitern leider meistens daran, daß im industriellen Kontext nicht alle benötigten Daten (hier: wo sind denn nun Fehler aufgetreten?) mit der nötigen Gleichförmigkeit gesammelt werden.


next up previous contents
Next: 1.8 Weitergehende Information Up: 1. Messen und Maße Previous: 1.6 Vorhersage und Validation
Lutz Prechelt
1999-04-13