Ein Ansatz zur Messung der Kapselung in Java-Systemen · 1Einleitung Das De nieren von...

117

Transcript of Ein Ansatz zur Messung der Kapselung in Java-Systemen · 1Einleitung Das De nieren von...

Universität HamburgFakultät für Mathematik, Informatik und

NaturwissenschaftenDepartment Informatik

Arbeitsbereich Softwaretechnik

Diplomarbeitim Fach Informatik

Ein Ansatz zur Messung der Kapselungin Java-Systemen

von

Christian ZollerMatrikelnr.: 5601774

Erstbetreuer: Dr. Axel SchmolitzkyZweitbetreuerin: Dr. Carola Lilienthal

Hamburg, November 2010

Inhaltsverzeichnis

Inhaltsverzeichnis

1 Einleitung 11.1 Gegenstand der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . 11.2 Aufbau der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

2 Kapselung in Java 32.1 Modularisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2.1.1 Das Modulkonzept . . . . . . . . . . . . . . . . . . . . . . . . 32.1.2 Modulkonzept der Objektorientierung . . . . . . . . . . . . . . 4

2.2 Zugri�skontrolle in Java . . . . . . . . . . . . . . . . . . . . . . . . . 52.2.1 Begri�e . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.2.2 Zugri�smodi�katoren . . . . . . . . . . . . . . . . . . . . . . . 5

2.3 Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.3.1 Typen-Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . 72.3.2 Paket-Schnittstellen . . . . . . . . . . . . . . . . . . . . . . . . 72.3.3 Keine Schnittstellen auf höherer Ebene . . . . . . . . . . . . . 8

2.4 Programmiersprachliche Regeln . . . . . . . . . . . . . . . . . . . . . 82.4.1 Überschreibende Methoden . . . . . . . . . . . . . . . . . . . 82.4.2 Verdeckende Methoden . . . . . . . . . . . . . . . . . . . . . . 102.4.3 Felder und Membertypen . . . . . . . . . . . . . . . . . . . . . 102.4.4 Interface-Member . . . . . . . . . . . . . . . . . . . . . . . . . 102.4.5 Main-Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . 112.4.6 Lokale und anonyme Klassen . . . . . . . . . . . . . . . . . . 11

3 Zugri�smodi�katoren aus softwaretechnischer Sicht 123.1 Leitlinien für die Wahl des Zugri�smodi�kators . . . . . . . . . . . . 12

3.1.1 Felder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123.1.2 Methoden, Konstruktoren und Membertypen . . . . . . . . . . 143.1.3 Top-Level-Typen . . . . . . . . . . . . . . . . . . . . . . . . . 15

3.2 Sonderfälle . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153.2.1 Genauere Bedeutung von protected . . . . . . . . . . . . . 153.2.2 Paketgrenzen auf Vererbungspfaden . . . . . . . . . . . . . . . 163.2.3 Marriage of convenience . . . . . . . . . . . . . . . . . . . . . 17

3.3 Minimaler Zugri�smodi�kator . . . . . . . . . . . . . . . . . . . . . . 183.4 Beobachtungen aus der Praxis . . . . . . . . . . . . . . . . . . . . . . 18

3.4.1 Zu groÿzügige Zugri�smodi�katoren . . . . . . . . . . . . . . . 183.4.2 default ist nicht der Standard . . . . . . . . . . . . . . . . . . 19

3.5 Zugri�smodi�katoren in der Programmierausbildung . . . . . . . . . . 213.6 Bestehende Werkzeuge zur Unterstützung des Umgangs mit Zugri�s-

modi�katoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

III

Inhaltsverzeichnis

3.6.1 PMD und FindBugs . . . . . . . . . . . . . . . . . . . . . . . 223.6.2 AccessModi�erModi�er . . . . . . . . . . . . . . . . . . . . . . 22

4 Softwaremetriken 234.1 Grundlagen der Messtheorie . . . . . . . . . . . . . . . . . . . . . . . 234.2 Validierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244.3 Einsatz von Softwaremetriken . . . . . . . . . . . . . . . . . . . . . . 25

4.3.1 Klassi�zierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 254.3.2 Die Auswahl von Metriken . . . . . . . . . . . . . . . . . . . . 274.3.3 Messwerkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . 27

4.4 Softwarequalität . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284.5 Beispiele von Softwaremetriken . . . . . . . . . . . . . . . . . . . . . 28

4.5.1 Lines of Code (LOC) . . . . . . . . . . . . . . . . . . . . . . . 304.5.2 Zyklomatische Komplexität . . . . . . . . . . . . . . . . . . . 304.5.3 Objektorientierte Softwaremetriken . . . . . . . . . . . . . . . 30

4.6 Metriken zur Kapselung . . . . . . . . . . . . . . . . . . . . . . . . . 31

5 Zwei neue Java-Metriken 325.1 De�nitionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32

5.1.1 IGAT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 325.1.2 IGAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34

5.2 Bestimmung der minimalen Zugri�smodi�katoren . . . . . . . . . . . 365.2.1 Benutzung von Typen . . . . . . . . . . . . . . . . . . . . . . 365.2.2 Benutzung von Methoden . . . . . . . . . . . . . . . . . . . . 385.2.3 Importdeklarationen . . . . . . . . . . . . . . . . . . . . . . . 39

5.3 Berechnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405.4 Validierung und Einordnung . . . . . . . . . . . . . . . . . . . . . . . 40

5.4.1 Skalentyp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415.4.2 Validierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . 415.4.3 Klassi�zierung . . . . . . . . . . . . . . . . . . . . . . . . . . . 44

5.5 Einsatzmöglichkeiten . . . . . . . . . . . . . . . . . . . . . . . . . . . 445.5.1 Qualitätsmodelle . . . . . . . . . . . . . . . . . . . . . . . . . 445.5.2 Refactoring . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45

5.6 Grenzen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 465.6.1 Benutzungen auÿerhalb des eigenen Projekts . . . . . . . . . . 465.6.2 Metaprogrammierung . . . . . . . . . . . . . . . . . . . . . . . 465.6.3 Bereits ausgenutzte Groÿzügigkeit . . . . . . . . . . . . . . . . 47

6 Umsetzung 496.1 Plattform . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496.2 Benutzungskonzept . . . . . . . . . . . . . . . . . . . . . . . . . . . . 496.3 Verwendetes Framework . . . . . . . . . . . . . . . . . . . . . . . . . 51

IV

Inhaltsverzeichnis

6.4 Algorithmus . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 536.5 Besonderheiten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

6.5.1 Interface-Methoden . . . . . . . . . . . . . . . . . . . . . . . . 556.5.2 Methodenaufruf ohne Punktnotation . . . . . . . . . . . . . . 556.5.3 Impliziter Konstruktoraufruf . . . . . . . . . . . . . . . . . . . 556.5.4 Statischer Import . . . . . . . . . . . . . . . . . . . . . . . . . 56

6.6 Beschränkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 566.6.1 Java Server Pages . . . . . . . . . . . . . . . . . . . . . . . . . 566.6.2 Re�ection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

7 Erprobung 597.1 Fallstudie A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

7.1.1 Ein�uss von Testklassen . . . . . . . . . . . . . . . . . . . . . 607.1.2 Verteilung der Zugri�smodi�katoren . . . . . . . . . . . . . . . 607.1.3 Falsch positive Ergebnisse . . . . . . . . . . . . . . . . . . . . 62

7.2 Fallstudie B . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 637.2.1 Falsch positive Ergebnisse . . . . . . . . . . . . . . . . . . . . 647.2.2 Verteilung der Zugri�smodi�katoren . . . . . . . . . . . . . . . 64

7.3 Schlussfolgerungen aus den Fallstudien A und B . . . . . . . . . . . . 667.4 Fallstudie C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

7.4.1 Auswahl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 667.4.2 Vorgehen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 687.4.3 Ergebnisse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 697.4.4 Verteilung der Zugri�smodi�katoren . . . . . . . . . . . . . . . 71

7.5 Alternative Berechnung der Metriken . . . . . . . . . . . . . . . . . . 737.6 Analysegeschwindigkeit . . . . . . . . . . . . . . . . . . . . . . . . . . 74

8 Fazit 778.1 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 778.2 Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78

A Zugri�smodi�kator-Regeln ausgewählter Quelltextanalyse-Werkzeuge 80A.1 PMD . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80

A.1.1 Code Size Rules . . . . . . . . . . . . . . . . . . . . . . . . . . 80A.1.2 Controversial Rules . . . . . . . . . . . . . . . . . . . . . . . . 80A.1.3 Design Rules . . . . . . . . . . . . . . . . . . . . . . . . . . . 80A.1.4 Finalizer Rules . . . . . . . . . . . . . . . . . . . . . . . . . . 81A.1.5 Unused Code Rules . . . . . . . . . . . . . . . . . . . . . . . . 81

A.2 FindBugs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81A.2.1 Correctness . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81A.2.2 Malicious code vulnerability . . . . . . . . . . . . . . . . . . . 81

V

Inhaltsverzeichnis

A.2.3 Performance . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82A.2.4 Dodgy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82

B Benutztbeziehungen in Java 83B.1 Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83

B.1.1 Explizite Benutzungen . . . . . . . . . . . . . . . . . . . . . . 83B.1.2 Implizite Benutzungen . . . . . . . . . . . . . . . . . . . . . . 89

B.2 Methoden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91

C Das AccessAnalysis-Plug-In 97C.1 Systemvoraussetzungen . . . . . . . . . . . . . . . . . . . . . . . . . . 97C.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97

C.2.1 Eclipse 3.4 (Ganymede) . . . . . . . . . . . . . . . . . . . . . 97C.2.2 Eclipse 3.5 (Galileo) und 3.6 (Helios) . . . . . . . . . . . . . . 97

C.3 Benutzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100

D Alternative Metrikde�nitionen 102D.1 IGAT2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102D.2 IGAM2 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102

E Inhalt der CD-Beilage 103

Abkürzungen 104

Literatur 106

VI

1 Einleitung

Das De�nieren von Schnittstellen und die Kapselung von Implementationsdetails sindzentrale Bestandteile eines jeden Softwareentwurfs. Eine saubere und klare Trennungder einzelnen Bausteine eines Softwaresystems verbessert deren Verständlichkeit, Än-derbarkeit und Wiederverwendbarkeit und leistet somit einen wichtigen Beitrag zurQualität der Software.Moderne objektorientierte Programmiersprachen bieten Möglichkeiten den Zugri�auf einzelne Elemente zu beschränken, um so festzulegen, ob diese zur Schnittstelleihrer jeweiligen Programmeinheit gehören sollen oder nicht. In Java � wie auch in vie-len anderen objektorientierten Sprachen � geschieht dies über Zugri�smodi�katoren.Dies sind Schlüsselwörter, mit denen sich bei der Deklaration eines Elements, wiez.B. einer Klasse oder einer Methode, dessen Zugreifbarkeit festlegen lässt. So lassensich sowohl die Schnittstellen einzelner Klassen als auch die von ganzen Paketen de-�nieren. Ein angemessener Umgang mit diesen Zugri�smodi�katoren ist notwendig,um eine gute Kapselung zu erreichen. Erfahrungen aus der Praxis zeigen jedoch, dassdie gebotenen Möglichkeiten oft nicht voll ausgeschöpft werden. Insbesondere scheintdie Kapselung nur intern verwendeter Typen innerhalb von Paketen selten umgesetztzu werden.Softwaremetriken sind ein Weg die Qualität von Software automatisiert und objektivzu bewerten. Es bietet sich daher an, auch den Umgang mit Zugri�smodi�katoreneiner solchen Bewertung zugänglich zu machen.

1.1 Gegenstand der Arbeit

In dieser Arbeit werden zwei Softwaremetriken entwickelt, Inappropriate Gene-rosity with Accessibility of Types (IGAT) und Inappropriate Generositywith Accessibility of Methods (IGAM), mit denen sich der Umgang mit Zu-gri�smodi�katoren in Java messen lässt. Darüber hinaus wird das von mir entwickel-te Werkzeug AccessAnalysis, ein Plug-In für die Entwicklungsumgebung Eclipse,beschrieben, mit dem sich diese Metriken berechnen lassen. Schlieÿlich wird dieserAnsatz an realen Softwareprojekten erprobt, um zu untersuchen, wie in der Praxismit Zugri�smodi�katoren umgegangen wird.

1.2 Aufbau der Arbeit

Das nachfolgende Kapitel 2 beginnt mit einer Einführung in die Konzepte Modula-risierung, Kapselung und Schnittstelle. Anschlieÿend wird das Prinzip der Zugri�s-modi�katoren und ihrer Verwendung dargestellt und diskutiert. Auf Basis der Java-

1

1 Einleitung

Sprachde�nition werden die Regeln aufgeführt, die bei der Verwendung von Zugri�s-modi�katoren zu beachten sind.In Kapitel 3 wird der Umgang mit Zugri�smodi�katoren aus softwaretechnischerSicht untersucht. Es werden Leitlinien vorgeschlagen und Sonderfälle diskutiert, diebei der Wahl des richtigen Zugri�smodi�kators über die allgemeinen Sprachregelnhinaus zu beachten sind. Zudem wird ein Blick in Lehre und Praxis geworfen, um diedort vor�ndbaren Prinzipien mit den hier aufgestellten zu vergleichen.In Kapitel 4 werden die theoretischen Grundlagen auf dem Gebiet der Softwareme-triken dargestellt. Es wird eine Zusammenfassung der messtheoretischen Grundlagengegeben und beschrieben, welche Anforderungen Softwaremetriken erfüllen müssen.Es wird aufgeführt, wo und wie Softwaremetriken eingesetzt werden. Zudem wirdauf den Begri� der Softwarequalität eingegangen und es werden Methoden beschrie-ben, die Qualität von Software über Metriken zu bewerten. Schlieÿlich werden einigeBeispiele für Softwaremetriken aufgeführt und untersucht, welche Ansätze, Aspekteder Kapselung über Metriken zu quanti�zieren, sich in der Literatur bereits �ndenlassen.Die Metriken IGAT und IGAM werden schlieÿlich in Kapitel 5 de�niert. Darauf-hin folgt die Betrachtung eines allgemeinen Verfahrens zu ihrer Berechnung und eineEinordnung in die vorausgegangenen Ausführungen über Softwaremetriken. Anschlie-ÿend werden Einsatzmöglichkeiten und Grenzen der Metriken diskutiert.In Kapitel 6 wird das Werkzeug AccessAnalysis vorgestellt. Die verwendete Platt-form und das Benutzungskonzept werden umrissen. Auÿerdem werden Aspekte derImplementation beleuchtet.Eine Aufarbeitung der Erprobung von Werkzeug und Metriken folgt in Kapitel 7.Hier werden drei Fallstudien beschrieben, in denen das Werkzeug eingesetzt wurde.Durchführung und Ergebnisse werden ausführlich diskutiert. Neben der Frage, wieder Umgang mit Zugri�smodi�katoren in der Praxis ganz allgemein ist, steht hierauch die Überprüfung der These, dass Typen in Java nur selten innerhalb ihres Pa-kets gekapselt werden, im Mittelpunkt.Die Arbeit endet in Kapitel 8 schlieÿlich mit einer Zusammenfassung und einemAusblick.

2

2 Kapselung in Java

Die Prinzipien der Modularisierung und Kapselung gehören zu den Grundbaustei-nen des objektorientierten Programmierparadigmas. Diese Arbeit beginnt mit einerEinführung in diese Konzepte und einer Darstellung ihrer Umsetzung in Java. DieZugri�smodi�katoren nehmen darin eine entscheidende Rolle ein. Ihre Bedeutung so-wie die Regeln, die die Java-Sprachde�nition [JLS05] für ihre Verwendung vorgibt,werden untersucht.

2.1 Modularisierung

2.1.1 Das Modulkonzept

Unter Modularisierung versteht man die Aufteilung des Quelltextes einer Softwarein mehrere in sich geschlossene Einheiten (Module), die über Schnittstellen mitein-ander kommunizieren und Details über ihre Implementation voreinander verbergen.Ein Modul im klassischen Sinne besteht aus einer Sammlung von Datenstrukturenund Operationen, von denen einige explizit exportiert werden, um sie anderen Modu-len zu Verfügung zu stellen. Zusammen mit den von anderen Modulen importiertenElementen bilden diese die Schnittstelle eines Moduls [Pom06, S. 569].Mit den Mitteln der jeweiligen Programmiersprache wird sichergestellt, dass alle nichtexportierten Elementen vor anderen Modulen verborgen bleiben, d.h. dass auf Datennicht zugegri�en werden kann und Operationen nicht aufgerufen werden können. Die-ses Verbergen von Implementationsdetails nennt man Kapselung (Encapsulation). Jemehr Elemente eines Moduls verborgen sind und je kleiner somit die Schnittstelleist, desto höher ist die Kapselung [Sny86].Die Forderung nach gröÿtmöglicher Kapselung lässt sich durch zwei Regeln zusam-menfassen, die Meyer in [Mey97, S. 47f] formuliert:

�Few Interfaces Rule:

Every module should communicate with as few others as possible.�

�Small Interfaces Rule:

If two modules communicate, they should exchange as little informationas possible.�

Diese Regeln liegen auch dem Geheimnisprinzip (Information hiding) zu Grunde, dasParnas [Par72] als Leitlinie der Modularisierung geprägt hat. Danach sollen Moduleeinzelne Entwurfentscheidungen kapseln. Die Schnittstellen sollen so gestaltet sein,dass sie von einer konkreten Implementation abstrahieren, damit die Verwendungeines Moduls ohne Kenntnis über deren inneren Aufbau möglich ist.

3

2 Kapselung in Java

Eine hohe Kapselung verbessert zum einen die Wiederverwendbarkeit von Software,da unabhängige, klar abgegrenzte Module sich leichter in andere Systeme einbindenlassen, und zum anderen die Änderbarkeit: Jedes Modul kann ersetzt werden durchein anderes, das durch die gleiche Schnittstelle beschrieben ist, auch wenn dieses einevöllig andere Implementation enthält.Ein weiterer Vorteil ist die Verbesserung der Verständlichkeit von Software. Einewesentliche Eigenschaft gröÿerer Softwaresysteme ist ihre Komplexität. Softwareent-wicklerinnen und -entwickler verbringen einen groÿen Teil ihrer Arbeit damit, Quell-text zu verstehen, Programmabläufe nachzuvollziehen und Strukturen innerhalb einerSoftware zu erfassen. Die Abstraktion von Implementationsdetails ist eine Möglich-keit die Komplexität zu verringern. Je weniger Informationen nötig sind, um dieeinzelnen Module einer Software zu verwenden, umso leichter ist ihr Zusammenspielzu verstehen.

2.1.2 Modulkonzept der Objektorientierung

Die objektorientierte Programmierung vereinigt das Konzept des Moduls mit dem desDatentyps. Eine Klasse ist ein Modul, denn sie enthält Datenfelder und die daraufarbeitenden Operationen. Diese sind durch eine Schnittstelle beschrieben und durcheine Implementation realisiert. Gleichzeitig ist eine Klasse als abstrakte Beschreibungdynamischer Objekte ein Datentyp [Mey97, S. 170].Objektorientierte Programmiersprachen unterstützen Kapselung in der Regel durchMechanismen der Zugri�skontrolle. Bei der Deklaration von Elementen wie Klassen,Methoden oder Variablen kann die Menge der Klassen festgelegt werden, aus denenauf das deklarierte Element zugegri�en werden darf. Diese Menge ist eine statischeEigenschaft des Elements, d.h. es kann zur Übersetzungszeit festgestellt werden, obder Zugri� auf dieses Element durch eine bestimmte Klasse erlaubt ist oder nicht.Eine hohe Kapselung bedeutet hier, dass die Menge der Klassen, die auf ein Elementzugreifen dürfen, möglichst klein ist. So lässt sich die Menge der Abhängigkeiteninnerhalb eines Softwaresystems begrenzen. Die Zugri�skontrolle dient vornehmlichdiesem softwaretechnischen Zweck und in der Regel nicht der Softwaresicherheit. Sogibt es in vielen Sprachen Möglichkeiten, diese Mechanismen zu umgehen1. Diesesollten jedoch nur in Ausnahmefällen eingesetzt werden.Die Klasse ist in der Objektorientierung die zentrale Entwurfseinheit. Doch dasKonzept des Moduls �ndet sich auch auf höherer Ebene wieder, wenn Klassen zuzusammenhängenden Einheiten gruppiert werden [Szy92]. Einige objektorientierteProgrammiersprachen, wie z.B. Java, unterstützen auch für solche Klassenpakete dieDe�nition von Schnittstellen und die Kapselung interner Klassen.

1 z.B. über Re�ection in Java oder Zeigermanipulation in C++

4

2.2 Zugri�skontrolle in Java

2.2 Zugri�skontrolle in Java

2.2.1 Begri�e

Da es für die Sprachelemente von Java besonders im Deutschen keine einheitlicheTerminologie gibt, nenne ich an dieser Stelle die Begri�e, die ich in meiner Arbeitverwende. Für das Verständnis meiner Ausführungen setze ich grundlegende Kennt-nisse in Java voraus, daher verzichte ich auf genaue De�nitionen. Die angegebenenParagraphen verweisen auf die aktuelle Ausgabe der Java-Sprachde�nition [JLS05].

Java-Quelltext wird in Paketen (Packages) [� 7] organisiert. Pakete enthalten Über-setzungseinheiten (Compilation units) [� 7.3]. Übersetzungseinheiten enthalten wie-derum die Deklarationen von Klassen (Classes) [� 8] und/oder Interfaces [� 9].

Klassen und Interfaces sind beides Typen. Enums [� 8.9] sind besondere Klassen; An-notationstypen (Annotation types) [� 9.6] sind besondere Interfaces. Primitive Da-tentypen (Primitive types) [� 4.2] spielen in dieser Arbeit keine Rolle.

Die Felder (Fields) [� 8.3],Methoden (Methods) [� 8.4] undMembertypen (Member ty-pes) [� 8.5] eines Typs heiÿenMember. Konstruktoren (Constructors) [� 8.8] gelten imKontext dieser Arbeit ebenfalls als Member. Typen, die nicht innerhalb eines anderenTyps geschachtelt sind, heiÿen Top-Level-Typen oder entsprechend Top-Level-Klassebzw. Top-Level-Interface.

Sowohl Typen als auch Member von Typen nenne ich Elemente.

Ein Typ, der in seinem Quelltext ein Element benutzt, heiÿt Klient dieses Ele-ments.

2.2.2 Zugri�smodi�katoren

Wie viele andere objektorientierte Programmiersprachen realisiert Java die Zugri�s-kontrolle mit Hilfe von Zugri�smodi�katoren (Access modi�er). Zugri�smodi�katorensind Schlüsselworte, die der Deklaration von Elementen vorangestellt werden. Dabeisteht jeder der Zugri�modi�katoren für eine bestimmte Menge von Klienten, ausdenen der Zugri� auf das deklarierte Element erlaubt wird. In Java gibt es drei Zu-gri�smodi�katoren: private, protected und public [JLS05, � 6.6].Das Nichtvorhandensein eines Zugri�smodi�kators hat eine eigene Bedeutung undwird als default oder auch package-private bezeichnet. Ich werde in dieser Arbeit aus-schlieÿlich die Bezeichnung default verwenden. Zur sprachlichen Vereinfachung wirddefault im Folgenden ebenfalls als Zugri�smodi�kator bezeichnet.Top-Level-Typen können nur default oder public deklariert werden, dagegen kön-nen Member jeden der vier Zugri�smodi�katoren erhalten.

5

2 Kapselung in Java

Die Bedeutung der einzelnen Zugri�smodi�katoren:

• private: Nur innerhalb der Top-Level-Klasse, zu der das Member gehört, darfauf dieses zugegri�en werden.

• default: Nur Klienten desselben Pakets haben Zugri�.

• protected: Nur Klienten desselben Pakets und Unterklassen der Klasse, zudem das Member gehört, haben Zugri�.

• public: Alle Klienten haben Zugri�.

Hieraus ergibt sich eine Hierarchie der Zugri�smodi�katoren. In der Reihenfolgeprivate, default, protected, public wird die Menge der Klienten gröÿer, dieZugri� auf ein Element mit dem jeweiligen Zugri�smodi�kator haben. Dabei ist dieMenge der zugri�sberechtigten Klienten einer Zugri�sstufe jeweils in der der nächstenZugri�sstufe enthalten, siehe Abb. 1.'

&

$

%

#

"

!

��

�private default protected public

Abbildung 1: Die Hierarchie der Mengen von Klienten, die auf Elemente mit dem jeweiligenZugri�smodi�kator Zugri� haben.

Auf Basis dieser Hierarchie wird im Folgenden häu�g von groÿzügigeren und stren-geren Zugri�smodi�katoren die Rede sein.

De�nition 1:Ein Zugri�smodi�kator A ist groÿzügiger als ein Zugri�smodi�kator B, wenn die Mengeder Klienten, die auf ein Element mit dem Zugri�smodi�kator A zugreifen dürfen, potenzi-ell gröÿer ist als die Menge der Klienten, die auf ein Element mit dem Zugri�smodi�katorB zugreifen dürfen.

Ein Zugri�smodi�kator B ist genau dann strenger als ein Zugri�smodi�kator A, wenn Agroÿzügiger ist als B.

In der Reihenfolge private, default, protected, public werden die Zugri�smo-di�katoren somit groÿzügiger und in der umgekehrten Reihenfolge strenger.

6

2.3 Schnittstellen

2.3 Schnittstellen

In Java lassen sich sowohl für Typen als auch für Pakete Schnittstellen de�nieren.

2.3.1 Typen-Schnittstellen

Die Schnittstelle eines Typs bilden die durch Klienten zugreifbaren Member. Da beiKlassen jedoch für verschiedene Klienten unterschiedliche Mengen von Membern zu-greifbar sind, ist die Schnittstelle nicht eindeutig. Vielmehr hat eine Klasse verschie-dene Schnittstellen. Je nachdem, an welchem Klienten eine Programmierin oder einProgrammierer gerade arbeitet, ist eine andere Schnittstelle der verwendeten Klassefür sie bzw. ihn relevant:

1. Schnittstelle für Klienten auÿerhalb des eigenen Pakets, die keine Unterklassensind: Alle als public deklarierten Member.

2. Schnittstelle für Unterklassen auÿerhalb des eigenen Pakets: Alle alsprotected und public deklarierten Member.

3. Schnittstelle für Klienten des gleichen Pakets: Alle als default, protected undpublic deklarierten Member.

Member, die als private deklariert sind, gehören zu keiner Schnittstelle, da sienicht der Kommunikation mit anderen Typen dienen. Sie dienen ausschlieÿlich derImplementation ihrer Klasse.

Für Interfaces gilt diese Unterscheidung der Schnittstellen nicht. Da hier alle Memberimmer public sind, sind sie für alle Klienten gleichermaÿen zugreifbar.

2.3.2 Paket-Schnittstellen

Die Schnittstelle eines Pakets bilden die durch Klienten anderer Pakete zugreifbarenTypen und deren zugreifbare Member. Dazu gehören public deklarierte Top-Level-Typen sowie deren public deklarierte Member. Auÿerdem zählt man die Klassen-Member mit protected-Zugri� zur Paketschnittstelle.Alle restlichen Elemente gehören zur Implementation des Pakets.

7

2 Kapselung in Java

2.3.3 Keine Schnittstellen auf höherer Ebene

Leider gibt es in Java keine Möglichkeit mit Sprachmitteln Schnittstellen oberhalbder Paketebene zu bilden. Auch die zur Strukturierung der Namensräume üblicheSchachtelung von Paketen hat keine Relevanz für die Zugri�skontrolle. So kann eineKlasse aus einem Paket �anwendung.beispiel� einen Typ aus �anwendung.beispiel.unterpaket� nur dann verwenden, wenn dieser public deklariert ist.Das bedeutet aber, dass dieser Typ auch sämtlichen anderen Klassen und Interfaceszur Verfügung steht.Subsysteme, die aus einer geordneten Sammlung von Paketen bestehen, lassen sichalso nur durch Konventionen voneinander trennen (vgl. [Lil08, S. 118f]). Man istgezwungen, sich zwischen einer guten logischen Strukturierung seines Quelltextesmit kleineren Paketen oder einer hohen Kapselung zu entscheiden.Es gibt Bemühungen dieses Problem in einer kommenden Java-Version zu beheben.Hauptziel ist dabei, vor allem die Entwicklungswerkzeuge des Java Development Kits(JDK) besser modularisieren zu können [Rei08] [Jig10]. Da aber die vorgeschlagenenMechanismen (u.a. ein neuer Zugri�smodi�kator module), wenn überhaupt, erstin der Zukunft zur Verfügung stehen, spielen Sie für die weiteren Betrachtungen indieser Arbeit keine Rolle.

2.4 Programmiersprachliche Regeln

Die Verwendung der Zugri�smodi�katoren, mit denen die Zugri�skontrolle in Javarealisiert wird, unterliegt den von der Sprache de�nierten Regeln.Wie bereits erwähnt, können grundsätzlich Top-Level-Klassen und -Interfaces alsdefault oder public deklariert werden und Member als private, default,protected oder public. Bei Membern gibt es allerdings einige Einschränkun-gen.

2.4.1 Überschreibende Methoden

Eine Methode, die eine Methode eines Obertyps überschreibt oder implementiert(Overriding), muss einen Zugri�smodi�kator haben, der mindestens so groÿzügig istwie der der überschriebenen Methode [JLS05, � 8.4.8.3].

8

2.4 Programmiersprachliche Regeln

Beispiel

class A {public int foo() {

return 42;}

}

class B extends A {int foo() {

return 23;}

}

Dieser Quelltext würde zu dem Übersetzungsfehler: �Cannot reduce the visibilityof the inherited method from A� führen, da die Klasse B hier die public-Methode foo() aus A überschreibt, dieser mit default aber einen strengerenZugri�smodi�kator zuweist.

Um eine Methode zu überschreiben, muss diese für die rede�nierende Klasse aller-dings ebenfalls zugreifbar sein. Ist dies nicht der Fall, ist es erlaubt eine andereMethode mit gleichlautender Signatur, aber niedrigerem Zugri�smodi�kator zu de�-nieren.

Beispiel

package p1;

public class A {int foo() {

return 42;}

}

package p2;

import p1.A;

class B extends A {private int foo() {

return 23;}

...}

Die Klassen A und B be�nden sich in unterschiedlichen Paketen. Da der Zugri�auf A.foo() default, also nur innerhalb des eigenen Pakets erlaubt ist, kann Bnicht auf diese Methode zugreifen und somit auch nicht überschreiben. Daherdarf B.foo() private deklariert sein.

9

2 Kapselung in Java

2.4.2 Verdeckende Methoden

Methoden, die mit dem Schlüsselwort static eingeleitet werden, nennt man sta-tische Methoden oder Klassenmethoden (Class methods). Nicht-statische Methodenheiÿen Exemplarmethoden (Instance methods) [JLS05, � 8.4.3.2].Bei statischen Methoden spricht man anders als bei nicht-statischen Methoden beimRede�nieren nicht von Überschreiben, sondern von Verdecken (Hiding) [JLS05, �8.4.8.2].Da Klassenmethoden nicht dynamisch gebunden werden, kommt es nicht wie beiExemplarmethoden zu polymorphen Aufrufen. Dennoch müssen Klassen auch allestatischen Operationen ihrer Oberklasse anbieten. Beim Verdecken gilt daher diegleiche Regel wie beim Überschreiben: Der Zugri�smodi�kator einer verdeckendenMethode muss mindestens dem der verdeckten Methode entsprechen.

2.4.3 Felder und Membertypen

Bei Feldern und Membertypen können die Zugri�smodi�katoren beliebig variiert wer-den.

Beispiel

class A {public int number = 42;

public class Inner {...

}}

class B extends A {private int number = 23;

class Inner {...

}}

Zwar verdeckt die Klasse B das Feld number und die Memberklasse Inner undweist diesen strengere Zugri�smodi�katoren zu als die Oberklasse A. Anders alsbei Methoden ist dies bei Feldern und Memberklassen aber unproblematisch.

2.4.4 Interface-Member

Sämtliche Member, die in Interfaces deklariert werden, sind implizit public. Esist nicht erlaubt, Member von Interfaces mit einem anderen Zugri�smodi�kator als

10

2.4 Programmiersprachliche Regeln

public zu versehen. Man kann den Zugri�smodi�kator zwar weglassen, aber auchdann ist das Member public.Zusammen mit der Regel, dass der Zugri� durch überschreibende Methoden nichteingeschränkt werden darf, bedeutet dies, dass Methoden, die eine Klasse deklariert,um ein Interface zu implementieren, immer public sein müssen.

Beispiel

interface I {int foo();

}

class A implements I {public int foo() {

return 42;}

}

Da die in I de�nierte Methode foo() wie alle Interface-Methoden implizitpublic ist, muss auch die implementierende Methode in A public sein.

2.4.5 Main-Methoden

Eine Main-Methode, die dazu dienen soll, ein Java-Programm zu starten, musspublic sein. Die Top-Level-Klasse, zu der die Main-Methode gehört, darf sowohlpublic als auch default sein.

2.4.6 Lokale und anonyme Klassen

Lokale und anonyme Klassen [JLS05, � 14.3, � 15.9.5] sind nur innerhalb des Blockssichtbar, in dem sie de�niert werden. Eine Zugri�skontrolle ist somit nicht nötig. Daihnen daher auch kein Zugri�smodi�kator zugewiesen werden kann, spielen sie fürdiese Arbeit keine Rolle.

11

3 Zugri�smodi�katoren aus softwaretechnischer Sicht

3 Zugri�smodi�katoren aus softwaretechnischer

Sicht

Neben den Regeln, die die Programmiersprache vorgibt, gibt es auch softwaretechni-sche Aspekte, die bei der Wahl des richtigen Zugri�smodi�kators eine Rolle spielen.So wäre es beispielweise ohne Weiteres möglich, sämtliche Top-Level-Typen und al-le Member public zu deklarieren. Übersetzungsfehler würden so nicht auftreten.Doch sollte es, wie oben dargestellt, Ziel eines softwaretechnisch sauberen Entwurfssein, die Schnittstellen der einzelnen Module � in Java also die Schnittstellen derTypen und Pakete � so klein wie möglich zu halten. Da die Schnittstellen durchdie Zugri�smodi�katoren bestimmt werden, sollten diese also so streng wie möglichgewählt werden.

In [Blo08, S. 67�] beschreibt Joshua Bloch diesen Zusammenhang zwischen der Ver-wendung von Zugri�smodi�katoren, dem Geheimnisprinzip und gutem Softwareent-wurf unter der Überschrift �Item 13: Minimize the accessibility of classes and mem-bers�. Das mit Abstand wichtigste Merkmal eines guten Moduldesigns ist für ihn derGrad, wie sehr interne Daten und andere Implementationsdetails vor anderen Mo-dulen verborgen werden. Der angemessene Gebrauch von Zugri�smodi�katoren seihierfür entscheidend. Bloch fasst zusammen:

�The rule of thumb is simple: make each class or member as in-

accessible as possible. In other words, use the lowest possible accesslevel consistent with the proper functioning of the software that you arewriting.� [Blo08, S. 68]

3.1 Leitlinien für die Wahl des Zugri�smodi�kators

Auf der von Bloch formulierten Regel bauen auch die softwaretechnischen Leitlinienfür den Umgang mit Zugri�smodi�katoren auf, die ich in diesem Abschnitt aufstelle.Ziel ist dabei die Minimierung von Schnittstellen.

3.1.1 Felder

Für Felder gilt eine breit akzeptierte und einfache Regel: Sie sollten stets privateund der Zugri� auf sie durch sondierende und verändernde Methoden gekapselt sein.Dies hat verschiedene Gründe: Zum einen kann eine Klasse so sicherstellen, dass ihrZustand stets konsistent ist. Verändernde Methoden können vor Setzen eines Fel-des prüfen, ob der neue Wert gültig ist. Ist ein Feld direkt für Klienten zugreifbar,

12

3.1 Leitlinien für die Wahl des Zugri�smodi�kators

können diese dem Feld jederzeit jeden beliebigen Wert des jeweiligen Datentyps zu-weisen und so unter Umständen einen inkonsistenten Zustand herbeiführen. Klassenmit ö�entlich veränderbaren Feldern sind daher auch nicht threadsicher 2, was beinebenläu�gen Programmen eine Rolle spielt.Zum anderen ist die Entscheidung, dass ein bestimmter Wert in einem Feld gespei-chert wird, anstatt ihn beispielsweise bei Bedarf zu berechnen, ein Implementati-onsdetail, das gegebenfalls Veränderungen unterliegt. Ist erst einmal ein Klient vonder Existenz eines Feldes abhängig, kann dieses nicht mehr ohne Weiteres entferntwerden.Zudem kann die Tatsache, dass Felder durch erbende Klassen nicht überschrieben,sondern nur verdeckt werden, zu möglicherweise unerwarteten E�ekten führen.

Beispiel

class A {final int number = 42;

}

class B extends A {final int number = 23;

}

class NumberPrinter {static void printNumber(A a) {

System.out.println(a.number);}

}

class Start {public static void main(String[] args) {

B b = new B();NumberPrinter.printNumber(b);

}}

Dieser Quelltext führt bei Ausführung von Start nicht etwa zu der Ausgabe�23�, wie man vielleicht vermuten könnte, sondern zu �42�.Die Klasse B, eine Unterklasse von A, redeklariert das Feld number. Die Klas-se NumberPrinter bietet eine Methode printNumber() an, die den Wertvon number eines übergebenen A-Objekts ausgibt. Diese Methode wird vonder Klasse Start benutzt, um den number-Wert eines B-Objekts auszugeben.Doch da Felder nicht dynamisch gebunden werden, entscheidet beim Zugri�auf diese immer der statische Typ des Ausdrucks, an dem der Zugri� vor-genommen wird, darüber, auf welches Feld zugegri�en wird. Die MethodeprintNumber() gibt daher immer den in A und niemals den in einem Unter-typ de�nierten Wert von number aus.

2 �Threadsicher� bedeutet, dass mehrere Klienten, die nebenläu�g auf ein Element zugreifen, sichdabei nicht gegenseitig behindern.

13

3 Zugri�smodi�katoren aus softwaretechnischer Sicht

Eine Ausnahme von der Regel, dass alle Felder private sein sollten, bilden höchs-tens Klassenkonstanten, d.h. Felder, die als static und final deklariert sind. Daderen Wert ohnehin fest codiert und unveränderlich ist, besteht hier keine Gefahr,wenn auf sie aus dem gesamten Quelltext zugegri�en werden kann. Dies gilt abernur, wenn der Datentyp einer solchen Konstante ein primitiver Datentyp oder dereines unveränderlichen Objekts ist, da der Zustand sonst auch wieder durch Klientenverändert werden kann.

Um es aus softwaretechnischer Sicht zusammenzufassen: Felder sollten immerprivate sein, es sei denn sie sind unveränderlich.Da diese Regel so einfach ist und Verstöÿe dagegen recht leicht zu erkennen sind,werde ich die Zugreifbarkeit von Feldern im Folgenden nicht weiter betrachten.

3.1.2 Methoden, Konstruktoren und Membertypen

Wie in Kapitel 2.4 beschrieben, müssen Methoden und Membertypen, die in Interfa-ces de�niert werden, immer public sein. Methoden, die in Klassen de�niert werden,müssen, wenn sie eine geerbte Methode überschreiben oder verdecken, mindestens denZugri�smodi�kator der überschriebenen bzw. verdeckten Methode haben. Soll eineMethode als Main-Methode dienen, muss diese ebenfalls public sein. Ansonstensollte man sich an folgenden Regeln orientieren:

• Wird eine Methode/ein Konstruktor/ein geschachtelter Typ innerhalb des um-schlieÿenden Top-Level-Typs benötigt und sonst gar nicht, soll diese(r) stetsprivate sein.

• Wird eine Methode/ein Konstruktor/ein geschachtelter Typ auÿerhalb des um-schlieÿenden Top-Level-Typs, aber innerhalb des eigenen Pakets und nicht au-ÿerhalb des eigenen Pakets benötigt, soll diese(r) stets default sein.

• Wird eine Methode/ein Konstruktor/ein geschachtelter Typ auÿerhalb des eige-nen Pakets, dort aber auschlieÿlich von Unterklassen der deklarierenden Klassebenötigt, soll diese(r) protected sein.

• Nur wenn eine Methode/ein Konstruktor/ein geschachtelter Typ von einemKlienten auÿerhalb des eigenen Pakets, der keine Unterklasse der deklarierendenKlasse ist, benötigt wird, soll diese(r) public sein.

Darüber hinaus werden in Kapitel 3.2 einige Sonderfälle beschrieben, die speziell beiMethoden zu beachten sind.

14

3.2 Sonderfälle

3.1.3 Top-Level-Typen

Ein Top-Level-Typ soll genau dann public sein, wenn er auÿerhalb des eigenenPakets benötigt wird. In allen anderen Fällen soll dieser default sein.

3.2 Sonderfälle

Java enthält neben den unter Kapitel 2.4 aufgeführten grundsätzlichen Sprachregelnfür die Verwendung von Zugri�smodi�katoren noch einige speziellere, die es nicht im-mer zulassen, sich an die Vorgaben aus dem vorangegangenen Abschnitt zu halten.

3.2.1 Genauere Bedeutung von protected

Wird eine Methode von einer Unterklasse der deklarierenden Klasse auÿerhalb desPakets der deklarierenden Klasse benötigt, reicht der protected-Modi�kator nuraus, wenn diese Methode statisch ist oder an einem Ausdruck vom Typ der aufru-fenden Klasse oder einer ihrer Unterklassen aufgerufen wird.

Beispiel

package p;

public class A {protected int foo() {

return 42;}

}

Die Klasse A deklariert eine protected-Methode foo(), welche von einerKlasse B wie folgt benutzt werden soll:

import p.A;

class B extends A {int bar() {

B b = new B();C c = new C();

return this.foo() + b.foo() + c.foo() + create().foo();}

private static B create() {return new C();

}}

class C extends B { ... }

15

3 Zugri�smodi�katoren aus softwaretechnischer Sicht

foo() wird innerhalb von B.bar() viermal aufgerufen, einmal an this, ein-mal an einer Variable vom Typ B, einmal an einer Variable vom Typ C, einerUnterklasse von B, und einmal am Rückgabewert der Methode create(),ebenfalls vom Typ B. Alle Aufrufe von foo() sind erlaubt, da sie innerhalbvon B jeweils an einem Ausdruck vom eigenen Typ bzw. von einem Untertypdes eigenen vorgenommen werden.

Hingegen sind die folgenden Aufrufe von foo() nicht erlaubt:

import p.A;

class B extends A {int bar() {

A aa = new A();A ab = new B();

return aa.foo() + ab.foo() + create().foo();}

private static A create() {return new C();

}}

class C extends B { ... }

Hier wird foo() innerhalb von B.bar() an drei Ausdrücken aufgerufen, diejeweils vom statischen Typ A sind, also weder vom eigenen Typ noch von ei-nem Untertyp des eigenen. Soll die Methode foo() auf diese Weise verwendetwerden können, muss sie public deklariert werden.

3.2.2 Paketgrenzen auf Vererbungspfaden

Soll eine Methode an eine Unterklasse vererbt werden, die sich im selben Paket be-�ndet wie die deklarierende Klasse, so reicht der default-Modi�kator nur aus, wennsich alle Klassen auf dem Vererbungspfad ebenfalls im selben Paket be�nden.

BeispielDie Klasse A enthält eine Methode foo(); C ist eine indirekte Unterklassevon A. In Abb. 2(a) ist foo() default (�) deklariert und alle Klassen auf demVererbungspfad liegen im gleichen Paket. C erbt daher foo(). In Abb. 2(b)liegen A und C zwar auch im selben Paket, jedoch be�ndet sich die Klasse B,welche auf dem Vererbungspfad zwischen A und C liegt, in einem anderen Paket.C erbt foo() daher nicht. Damit C in so einer Situation foo() erben kann,muss foo() wie in Abb. 2(c) protected (#) deklariert sein.

16

3.2 Sonderfälle

p1

A

~foo(): int

B

C

(a)

p1

A

~foo(): int

C

p2

B

(b)

p1

A

#foo(): int

C

p2

B

(c)

Abbildung 2: Paketgrenzen auf Vererbungspfaden.

3.2.3 Marriage of convenience

Manchmal beerbt eine Klasse eine andere, um mit den geerbten Methoden ein Inter-face zu implementieren. Meyer vergleicht dieses Muster in [Mey97, S. 530] mit derHochzeit zwischen einer Adligen und einem Mann aus reichem bürgerlichem Hause.Die Braut bringt ihren Namen mit in diese Verbindung, der Bräutigam die �nanziel-len Mittel. Das Kind der Eheleute bzw. die erbende Klasse erhält somit beides, denNamen bzw. den Typ des Interfaces und die Mittel, also die Implementation der Me-thoden. Meyer nennt dieses Muster daher �Marriage of convenience�, also Zweckehe.In Java ist dies nur möglich, wenn die für die Implementation des Interfaces benö-tigten Methoden public sind, auch wenn die deklarierende Oberklasse selbst nichtdas Interface implementiert.

BeispielWäre A.foo() in Abb. 3 nicht public deklariert, würde ein Übersetzungs-fehler auftreten, da B foo() braucht, um I zu implementieren

A

foo : void

<<interface>>I

foo : void

B

Abbildung 3: Das Muster �Marriage of convenience�.

17

3 Zugri�smodi�katoren aus softwaretechnischer Sicht

3.3 Minimaler Zugri�smodi�kator

Wendet man die beschriebenen Regeln an, ergibt sich für jeden Typ und jede Me-thode ein maximal notwendiger Zugri�smodi�kator, der ein übersetzbares Programmgewährleistet, in dem alle Klienten Zugri� auf die Typen und Methoden haben, diesie wirklich benötigen. Innerhalb eines gegebenen Programmcodes lässt sich für jedenTyp und jede Methode dieser minimale Zugri�smodi�kator ermitteln, wenn man dietatsächliche Verwendung des Typs oder der Methode zugrunde legt.Um im Sinne einer hohen Kapselung die Schnittstellen der Typen und Pakete in-nerhalb eines Java-Programms zu minimieren, sollten alle Typen und Methoden mitdem minimalen Zugri�smodi�kator versehen werden, sofern keine anderen Gründedagegen sprechen.

De�nition 2:Für einen Typ bzw. eine Methode innerhalb des Quelltextes P eines gegebenen Java-Programms heiÿt der strengste3 Zugri�smodi�kator, der die Übersetzbarkeit und korrekteFunktion des Programms gewährleistet, der minimale Zugri�smodi�kator dieses Typsbzw. dieser Methode in Bezug auf P .

Ein einem Typ bzw. einer Methode zugewiesener Zugri�smodikator, der groÿzügiger istals der minimale Zugri�smodi�kator dieses Typs bzw. dieser Methode, wird hier zu groÿ-zügiger Zugri�smodi�kator genannt.

3.4 Beobachtungen aus der Praxis

3.4.1 Zu groÿzügige Zugri�smodi�katoren

In realen Softwareprojekten gibt es etliche Gründe, weshalb für einen Typ oder eineMethode nicht immer der minimale Zugri�smodi�kator gewählt wird. Ein nahelie-gender Grund, weshalb ein Element während der Entwicklung einer Software einenzu groÿzügigen Zugri�smodikator hat, ist beispielsweise, dass ein Klient, der diesesElement mit dem gewählten Zugri�smodi�kator benötigt, erst noch geschrieben wer-den muss.Gerade wenn ein Projekt nicht als eigenständige Anwendung, sondern als Biblio-thek oder Framework, das von anderen Projekten verwendet werden soll, entwickeltwird, werden die Schnittstellen sicher Elemente enthalten, die innerhalb des Pro-jekts selbst gar nicht benutzt werden. Ebenso spielen bei der Entwicklung eines starkkomponentenbasierten Systems, in dem die einzelnen Komponenten in anderen Pro-jekten wiederverwendet werden sollen, beim Entwurf der Schnittstellen sicher nichtnur Minimierungsaspekte eine Rolle.

3 vgl. De�nition 1, Kapitel 2.2.2

18

3.4 Beobachtungen aus der Praxis

Man kann aber davon ausgehen, dass sich in jedem Java-Projekt etliche Typen undMethoden be�nden, die unnötig Teil einer Schnittstelle sind, also einen zu groÿzügi-gen Zugri�smodi�kator haben. In einigen Fällen geschieht dies ganz bewusst. So gibtes neben der hier vertretenen Strategie, immer den minimalen Zugri�smodi�kator zuwählen, um die Schnittstellen möglichst klein zu halten, auch andere.Beispielsweise argumentiert Feathers in [Fea08], dass breite Schnittstellen die Erwei-terung einer Software erleichtern, da Funktionalität, die irgendwann doch benötigtwird, nicht erst freigegeben werden muss. Sofern die Invarianten einer Klasse odereines Pakets nicht gefährdet sind, sollten ihre Methoden und Typen möglichst weitzugänglich gemacht werden.Hierbei lässt er jedoch auÿer acht, dass breite Schnittstellen die Komplexität einerSoftware erhöhen; zum einen da die Entwicklerinnen und Entwickler mit mehr Infor-mationen belastet werden und zum anderen da durch gröÿere Schnittstellen komple-xere Abhängigkeitsstrukturen entstehen. Abhängkeiten, die einmal bestehen, lassensich nur mit Mühe wieder au�ösen. Änderungen an den betro�enen Elementen sindso schwieriger durchzuführen. Dies gilt insbesondere, wenn Module nicht nur pro-jektintern eingesetzt, sondern beispielweise im Internet verö�entlicht werden. Hierkönnen Schnittstellen in späteren Versionen kaum noch verändert werden, da vieleandere Softwareprojekte von diesen abhängig sein können [Fow02].

Desweiteren ist davon auszugehen, dass zu groÿzügige Zugri�smodi�katoren oft auchunbewusst eingesetzt werden. So ist manch einer Entwicklerin oder einem Entwicklermöglicherweise die richtige Bedeutung der einzelnen Modi�katoren gar nicht bekannt.Andere wollen oder können sich die Zeit nicht nehmen, sich immer ausreichend Ge-danken über die Verwendung ihrer Typen oder Methoden zu machen.Auch kann es vorkommen, dass Zugri�smodi�katoren nicht angepasst werden, wennBenutztbeziehungen beispielsweise nach Refactorings wegfallen. Besonders in agilenEntwicklungsprojekten, in denen der Quelltext vielen Veränderungen unterliegt, kanndas der Fall sein (vgl. [BGS08]).

3.4.2 default ist nicht der Standard

Während die Praxis, mit der Unterscheidung zwischen public- und private-Methoden die Schnittstelle einer Klasse zu bestimmen, weit verbreitet ist, �ndetder default-Modi�kator bzw. das Nichtsetzen eines Zugri�smodi�kators wahrschein-lich am wenigsten Anwendung. Besonders bei Top-Level-Typen scheint nicht default,sondern vielmehr public der Standard zu sein, selbst wenn gar kein Bedarf besteht,den betre�enden Typ anderen Paketen zur Verfügung zu stellen.

So bietet die Java-Entwicklungsumgebung (IDE) Eclipse4 einen Assistenten zum Er-

4 http://eclipse.org, getestet in der Version 3.5.2 unter Linux

19

3 Zugri�smodi�katoren aus softwaretechnischer Sicht

Abbildung 4: Der Eclipse-Dialog zum Erstellen einer neuen Java-Klasse. Als Zugri�smodi�katorist standardmäÿig public ausgewählt.

stellen einer neuen Top-Level-Klasse (Abb. 4). In diesem lässt sich der Zugri�smodi-�kator der neuen Klasse per Radio-Buttons auswählen. Die Standardeinstellung isthier immer public.In der NetBeans IDE 5 beginnen neu erstellte Top-Level-Klassen ebenfalls immermit public. Hier bietet der Assistent zum Erstellen einer neuen Klasse gar nichtdie Möglichkeit, den Zugri�smodi�kator einzustellen. Möchte man die neue Klassedefault deklarieren, muss man das public per Hand löschen. Allerdings lässt sich dieverwendete Vorlage (Template) so anpassen, dass Klassen ohne das public erzeugtwerden. Ebenso verhält es sich in IntelliJ IDEA6.In dem weit verbreiteten Quelltextanalyse-Werkzeug PMD7 gibt es sogar eine Regel,die davor warnt, die default-Zugreifbarkeit zu verwenden8. Eine Begründung wirdhierfür nicht angegeben [PMD09]. Es ist durchaus möglich, dass diese Regel in vielenProjekten unre�ektiert befolgt wird.

Auch in der Java-Fachliteratur erfreut sich der public-Modi�kator für Top-Level-Typen groÿer Beliebtheit. Beispielsweise beginnen in �E�ective Java� [Blo08] die

5 http://netbeans.org, getestet in der Version 6.8 unter Linux6 http://www.jetbrains.com/idea, getestet in der Version 9.0.2 unter Linux7 http://pmd.sourceforge.net8 �DefaultPackage: Use explicit scoping instead of the default package private level.� [PMD09]

20

3.5 Zugri�smodi�katoren in der Programmierausbildung

meisten Beispiele unnötigerweise mit �public class { ...�, obwohl Bloch � wieoben zitiert � im gleichen Buch unter �Item 13� dazu au�ordert, immer den minima-len Zugri�smodi�kator zu verwenden.In dem Programmierhandbuch �Java in a nutshell� von Flanagan [Fla05] oder dem�Programmer's Guide to Java Certi�cation� von Mughal und Rasmussen [MR03]kommt ebenfalls kaum eine Klassen- oder Methodendeklaration ohne ein einleitendespublic aus. Viele weitere Beispiele lieÿen sich au�ühren � darunter auch einige derim folgenden Abschnitt genannten Lehrbücher (z.B. [BK09]).

3.5 Zugri�smodi�katoren in der Programmierausbildung

Kommen in Java-Kursen oder -Lehrbüchern Zugri�smodi�katoren zum ersten Malzur Sprache, dann oft im Zusammenhang der Unterscheidung zwischen den beidenExtrema private und public. Meist wird hierbei erwähnt, dass Felder in derRegel private sein sollten. Für Methoden gilt die übliche Lehre, dass sie publicsein müssten, sollen sie von anderen Klassen benutzt werden können. Der default-Zugri�, der hierfür eigentlich ausreichen würde, solange Pakete noch nicht verwendetwerden, wird hingegen oft erst erwähnt, sobald diese eingeführt wurden (vgl. z.B.[SZ�08], [BK09], [RSSW10]).Dieses Vorgehen ist sinnvoll, da sich durch die explizite Angabe von private undpublic der Unterschied zwischen der Schnittstelle und der Implementation einerKlasse besonders deutlich veranschaulichen lässt. Gerade als Vorbereitung auf dieEinführung von Interfaces kommt man nicht umhin, den public-Modi�kator fürMethoden auch ohne die Benutzung von Paketen einzuführen9.

Schiedermeier geht in [Sch10] allerdings einen anderen Weg. Zwar taucht auch in die-sem Lehrbuch wie in vielen anderen der erste Zugri�smodi�kator bereits im erstenCodebeispiel, einem Beispielprogramm mit main-Methode, auf, doch bis zur Einfüh-rung von Paketen beschränkt sich die Verwendung von public ausschlieÿlich undohne nähere Erläuterung auf solche Fälle. Die Konzepte Schnittstelle und Kapselungerläutert er nur mit dem private-Modi�kator. Interfaces folgen bei ihm allerdingsauch erst später, wenn Pakete und public bereits bekannt sind.

Einige Lehrbücher führen auch einfach alle Zugri�smodi�katoren auf einmal ein (vgl.z.B. [HMHG07], [Ull09]).

9 vgl. Kapitel 2.4.4

21

3 Zugri�smodi�katoren aus softwaretechnischer Sicht

3.6 Bestehende Werkzeuge zur Unterstützung des Umgangs

mit Zugri�smodi�katoren

Für den Umgang mit Zugri�smodi�katoren stehen Softwareentwicklerinnen und-entwicklern im begrenzten Maÿe Werkzeuge zur Verfügung. Quelltextanalyse-Werkzeuge wie PMD oder Findbugs10 bieten einige einfache Regeln, die Zugri�smo-di�katoren zum Gegenstand haben. Ein umfangreichere Analyse ermöglicht dagegenbeispielweise der AccessModi�erModi�er 11.

3.6.1 PMD und FindBugs

Die etablierten Quelltextanalyse-Werkzeuge PMD und Findbugs beinhalten aus-schlieÿlich einfache Regeln, die sich im Kontext einer einzelnen Übersetzungseinheitüberprüfen lassen. Neben der erwähnten Regel, den default-Zugri�smodi�kator nichtzu verwenden, kann PMD beispielsweise eine Warnung ausgeben, wenn eine Klassezu viele public-Methoden enthält, und emp�ehlt, diese möglicherweise aufzuteilen.FindBugs warnt, wenn Felder groÿzügigeren Zugri� als default bieten.Beide Werzeuge erkennen auÿerdem, wenn private-Methoden oder -Felder inner-halb einer Klasse nie verwendet werden, und empfehlen diese zu löschen � eine Funk-tion, die Eclipse ebenfalls anbietet.In Anhang A sind alle zugri�sbezogenen PMD- und Findbugs-Regeln aufgeführt.

3.6.2 AccessModi�erModi�er

Das Eclipse-Plug-In AccessModi�erModi�er, das Groÿkinsky in seiner Masterarbeit[Gro07] entwickelt und beschrieben hat, kann Java-Quelltext analysieren und mini-male Zugri�smodi�katoren ermitteln.Es hilft der Entwicklerin oder dem Entwickler, die Methoden einer Klasse oder ei-nes ganzen Projekts auf die minimale Zugreifbarkeit einzustellen. Auÿerdem bietetes die Möglichkeit, Warnungen von Eclipse anzeigen zu lassen, wenn eine Metho-de einen zu groÿzügigen Zugri�smodi�kator hat. Die Zugreifbarkeit von Typen wirdnicht analysiert.

10 http://�ndbugs.sourceforge.net11 http://www.fernuni-hagen.de/ps/prjs/AMM2

22

4 Softwaremetriken

In nahezu allen Bereichen des Lebens ist Messen eine unverzichtbare Tätigkeit. Täg-lich sind wir wie selbstverständlich mit Messgröÿen wie Gewicht, Preis, Entfernung,Zeit und vielen weiteren konfrontiert. Besonders in der Wissenschaft nimmt das Erhe-ben und Messen von Daten einen besonderen Stellenwert ein. Seit den späten 1960erJahren [Zus97, S. 5] beschäftigt sich auch die Softwaretechnik damit, wie man mitHilfe von Maÿen und Messungen die eigenen Produkte und Prozesse verstehen, steu-ern und verbessern kann. Auch wenn sich die entstandenen Methoden bis heute nichtvollständig etabliert haben [OH08], sind im Laufe der Jahrzehnte etliche Softwarema-ÿe, meist � wie auch im Folgenden � Softwaremetriken genannt, entwickelt worden.Jede dieser Metriken de�niert ein mathematisches Modell, das eine Eigenschaft einesSoftwareprodukts oder -prozesess auf einen numerischen Wert abbildet. Die Grund-lage, solche Modelle zu untersuchen, bildet die Messtheorie.

4.1 Grundlagen der Messtheorie

Ein Maÿ im Sinne der Messtheorie ist die Abbildung eines empirischen Relationen-systems (ERS) auf ein formales Relationensystem (FRS) (vgl. z.B. [FP97, S. 24�]).Eine empirische Relation ist beispielsweise: �Karl ist gröÿer als Friedrich�. DurchMessen der Körpergröÿen von Karl und Friedrich in Zentimetern, z.B. 182 cm und175 cm, bildet man diese empirische Relation auf die formale Relation �182 ¡ 178�ab. Ein ERS besteht aus Entitäten, die in der Realität direkt oder auch indirekterfahrbar sind, und einer oder mehreren Relationen zwischen diesen Entitäten. EinFRS besteht aus Zahlen und Symbolen sowie den Relationen zwischen diesen. Fürein gültiges Maÿ muss die Repräsentationsbedingung erfüllt sein, d.h. zum einen musses für jedes Element aus dem ERS ein entsprechendes im FRS geben, zum anderenmuss es auch für jede Relation eine Entsprechung geben, so dass bei der Abbildungdie Relationen erhalten bleiben. Das Tripel aus ERS, FRS und einem gültigen Maÿnennt man Skala.Mit Hilfe von Maÿen möchte man durch Operationen auf den Daten im FRS Er-kenntnisse über die Eigenschaften der Objekte im ERS gewinnen. Jedoch sind nichtalle Operationen bei jeder Skala sinnvoll. Man unterscheidet daher verschiedene Ska-lentypen. Tabelle 1 enthält eine Au�istung einiger wichtiger Skalentypen mit ihrenEigenschaften, den jeweils erlaubten Operationen und einem Beispiel.

Neben Maÿen, die direkt am zu messenden Objekt ermittelt werden, gibt es solche,die aus anderen Maÿen berechnet werden, z.B. die Geschwindigkeit als Quotient vonLänge und Zeit. Solche Maÿe werden indirekte [FP97, S. 40] oder abgeleitete Maÿe(Derived measurements) [Zus97, S. 95] genannt. Die erlaubten Operationen auf den

23

4 Softwaremetriken

Skalentyp Charakterisierung Operationen Beispiel

Nominalskala Klassi�zierungohne Ordnung

�,� Themenbereichein der Bibliothek

Ordinalskala Klassi�zierungmit Ordnung

�,�, ,¡ Schulnoten

Intervallskala Ordnung miteinheitlichenAbständen

�,�, ,¡,�,� Temperatur(Celsius)

Verhältnisskala EinheitlicheAbstände undNullpunkt

�,�, ,¡,�,�, �, { Temperatur(Kelvin)

Absolutskala Abzählung �,�, ,¡,�,�, �, { AnzahlQuelltextzeilen

Tabelle 1: Skalentypen (vgl. u.a. [FP97, S. 45�], [Zus97, S. 130�]).

Werten indirekter Maÿe sind abhängig von den Skalentypen der zugrundeliegendendirekten Maÿe.

4.2 Validierung

Damit sichergestellt ist, dass ein Maÿ eine gültige Repräsentation einer Eigenschaftdarstellt und zuverlässige Messwerte liefert, muss dieses validiert werden. Hierbeiunterscheidet man zwischen interner und externer Validierung. Mit der internenValidierung wird gezeigt, dass ein Maÿ konform zur Messtheorie ist. Die externeValidierung ist die Überprüfung, ob das Maÿ hilfreich ist, die zugrundeliegendenFragestellungen zu beantworten.Während die externe Validierung aus statistischen Untersuchungen besteht, wird dieinterne Validierung mittels theoretischer Überlegungen durchgeführt. Dazu sind zweiSchritte notwendig:

1. Überprüfen des Skalentyps

2. Prüfen der Repräsentationsbedingung

Für den zweiten Schritt wird ausgehend von einem intuitiven Verständnis über das,was das Maÿ messen soll, ein individueller Anforderungskatalog erstellt. Dabei trittjedoch die Schwierigkeit auf, einen hinreichend vollständigen und korrekten Satz vonForderungen zu �nden. Ein Ansatz besteht darin, ausgehend vom zugrundeliegenden

24

4.3 Einsatz von Softwaremetriken

Modell Operationen zu identi�zieren, die auf den Untersuchungsgegenstand anwend-bar sind. Das Verhalten des Maÿes unter Anwendung der Operationen muss denintuitiven Vorstellungen über die Veränderung der Messwerte entsprechen [BR04, S.22].

BeispielDas Maÿ �Kontostand� beschreibe den Geldbetrag, der auf einem Bankkonto zurVerfügung steht, und berechne sich aus der Summe der Beträge aller Einlagenabzüglich der Summe der Beträge aller Auszahlungen. Mögliche Operationenwären in diesem Fall �Einzahlen� und �Auszahlen�. Nun wäre zu überprüfen,wie sich z.B. eine Einzahlung auf die einzelnen Terme auswirkt und was das fürden Kontostand bedeutet. Da eine Einzahlung nach intuitiver Vorstellung zueiner Erhöhung des Kontostandes führt, sollte dieser E�ekt auch mathematischnachweisbar sein.

4.3 Einsatz von Softwaremetriken

Maÿe bzw. Metriken werden in der Softwarenentwicklung in vielen Bereichen einge-setzt. Sie können sowohl Entwicklerinnen und Entwicklern als auch dem Managementnützliche Daten liefern. Fenton und P�eeger nennen u.a. folgende Einsatzgebiete[FP97, S. 14f]:

• Kosten- und Aufwandsschätzungen

• Produktivitätsmessungen

• Qualitätsmodelle

• Zuverlässigkeitsmodelle

• Leistungsbewertung

• Struktur- und Komplexitätsmodelle

• Evaluation von Methoden und Werkzeugen

4.3.1 Klassi�zierung

Neben den Skalentypen und der Unterscheidung zwischen direkten und indirektenMaÿen gibt es etliche weitere Schemata, nach denen Softwaremetriken klassi�ziertwerden [Zus97, S. 17]. Fenton und P�eeger unterscheiden beispielsweise zwischenProzess-, Produkt- und Ressourcenmetriken sowie zwischen internen und externen

25

4 Softwaremetriken

Eigenschaften, die gemessen werden. Interne Eigenschaften sind solche, die ausschlieÿ-lich den Prozess, das Produkt oder eine Ressource selbst betre�en, z.B. ist die Längedes Quelltextes eine interne Produkteigenschaft. Externe Eigenschaften beziehen dieUmgebung mit ein. Ein Beispiel für eine externe Prozesseigenschaft wäre die Ren-tabilität einer bestimmten Aktivität. Externe Eigenschaften sind oft schwieriger zumessen als interne. Häu�g werden externe Eigenschaften daher aus internen abge-leitet, z.B. lieÿe sich die Rentabilität von Code-Reviews als gefundene Fehler proZeiteinheit de�nieren [FP97, S. 77].

Im Bereich der internen Produktmetriken teilen Bennicke und Rust [BR04, S. 40�] diebetrachteten Eigenschaften eines Softwaresystems nach Granularitätsebenen ein:

• Systemebene

• Architekturebene (Subsystem/Paket/Datei)

• Entwurfsebene (Modul)

• Verhaltensebene (Prozedur/Funktion/Methode)

• Datenebene (Variable)

Darüber hinaus unterscheiden sie zwischen Intra- und Intermetriken, je nachdemob die gemessene Eigenschaft ein einzelnes betrachtetes Element beschreibt oder dieBeziehungen zwischen den Elementen.Auf Java-Systeme übertragen ergibt sich daraus die in Abb. 5 aufgestellte Hierarchie.Darin ist allerdings die Architekturebene in die zwei Ebenen �Subsystem� und �Paket�aufgeteilt, wobei die Subsystemebene optional ist, da sie nicht explizit durch dieProgrammiersprache de�niert ist.

Subsysteminter intra

Gesamtsystem

Paketinter intra

Klasse/Interfaceinter intra

Methodeinter intra

Variableinter intra

Abbildung 5: Granularitätsebenen in Java-Systemen.

26

4.3 Einsatz von Softwaremetriken

4.3.2 Die Auswahl von Metriken

Zu einem erfolgreichen Einsatz von Softwaremetriken gehört die Auswahl der richti-gen Metriken. Diese zu tre�en, ist nicht in jedem Fall einfach. Ein populärer Ansatzist das Goal-Question-Metric-Paradigma (GQM) von Basili et al. [BW84], [BR88].Dabei wird zunächst das Ziel bestimmt, das erreicht werden soll. Ausgehend vomZiel werden Fragen formuliert, die beantwortet werden müssen, um das Ziel zu errei-chen. Schlieÿlich werden Metriken abgeleitet, die bei der Beantwortung der Fragenhelfen.

BeispielEin Ziel könnte �Bewertung der E�ektivität von Quelltextkonventionen� sein.Abb. 6 zeigt, wie daraus abgeleitete Fragen und Metriken aussehen könnten.

ZIEL: Bewertung der E�ektivität von Quelltextkonventionen (QTK)

ssggggggggggggg

�� ++WWWWWWWWWWWWW

FRAGEN: Wer verwendet Wie ist die Wie ist die

Quelltext- Produktivität Qualität des

konventionen?

ssggggggggggggg

��

der Entwickler?

ssggggggggggggg

�� ++WWWWWWWWWWWWW Quelltextes?

ssggggggggggggg

++WWWWWWWWWWWWW

METRIKEN: Anteil der Erfahrung Quelltextumfang Aufwand Fehler ...

Entwickler, die der Entwickler (Quelltextzeilen,

- QTK benutzen - mit QTK Function Points

- Sprache benutzen - mit Sprache usw.)

- mit IDE, usw.

Abbildung 6: Beispiel eines GQM-Modells (übersetzt aus [FP97, S. 85]).

Bei der Zusammenstellung eines geeigneten Satzes von Metriken nach dem GQM-Prinzip kann es notwendig sein, die strikte Aufteilung in drei Verfeinerungsebenenzu erweitern. Hierzu kann man Ziele zunächst in Unterziele aufgliedern und Fragenin Unterfragen [Sim01, S. 15].

4.3.3 Messwerkzeuge

Ein groÿer Vorteil der Softwarevermessung ist, dass sich viele Daten automatisierterfassen lassen. Besonders zu Metriken, die Gröÿe und Struktur von Softwareproduk-ten zum Gegenstand haben, gibt es eine Vielzahl sowohl kommerzieller als auch freiverfügbarer Messwerkzeuge. Die meisten berechnen mehrere Metriken auf einmal.Eine Beschreibung einer Auswahl von Messwerkzeugen �ndet sich z.B. in [Sch06, S.52�].

27

4 Softwaremetriken

4.4 Softwarequalität

Ein wesentliches Einsatzgebiet von Softwaremetriken ist die Bewertung der Qualitäteiner Software. Jedoch ist Qualität eine sehr subjektive Eigenschaft und lässt sichnicht direkt messen. Daher de�niert man Qualität auf Basis anderer Produktmerk-male, die näher an einer objektiven Bewertbarkeit liegen. Entsprechend DIN 55350ist Softwarequalität

�...die Gesamtheit der Eigenschaften und -merkmale, die Software in Ver-wendung und (Weiter-)Entwicklung aufweist, um die an sie gestellten An-forderungen zu erfüllen.� [ZR06, S. 802]

Diese Eigenschaften setzt man zu Qualitätsmodellen zusammen, in denen man durchweitere Verfeinerung schlieÿlich zu Untereigenschaften kommt, die sich mit Hilfe vonSoftwaremetriken quanti�zieren lassen. So soll schlieÿlich ein relativ objektives Ge-samtbild der Qualität einer Software entstehen.

Ein Weg zur Erstellung solcher Qualitätsmodelle ist das GQM-Paradigma, das imvorangegangenen Abschnitt vorgestellt wurde. Einer ähnlichen Vorgehensweise ent-spricht das Factor-Criteria-Metrics-Framework von McCall [CM78]. Auch hier wirdder Qualitätsbegri� in einer Top-Down-Verfeinerung zerlegt; zunächst in einzelneFaktoren, diese wiederum in Kriterien und schlieÿlich in Metriken, um die einzelnenKriterien zu messen.Auf diese und ähnliche Weisen wurden bereits Ansätze zu allgemeingültigen Quali-tätsmodellen entwickelt. Ein Beispiel ist das standardisierte ISO-9136-Modell [Int01],das in Abb. 7 zu sehen ist. Qualität wird hier in die Faktoren Funktionalität, Zuver-lässigkeit, Benutzbarkeit, E�zienz, Wartbarkeit und Übertragbarkeit zerlegt, für diewiederum einzelne Kriterien angegeben sind. In der Praxis bilden solche allgemeinenModelle meist jedoch nicht vollständig die konkreten Anforderungen an ein Software-produkt ab. Daher können sie in der Regel nur als Grundlage für die Erstellung einesindividuellen Qualitätsmodells dienen [SSL01, S. 5�].Auch mit dem Herunterbrechen des Qualitätsbegri�s auf die Ebene von Metrikenbleibt zur Bewertung der Qualität eines Softwareprodukts die Notwendigkeit dermenschlichen Beurteilung bestehen.

4.5 Beispiele von Softwaremetriken

In der Literatur �ndet sich eine Vielzahl von Softwaremetriken. Die meisten hiervonvermessen einen Aspekt der Gröÿe oder Struktur einer Softwareeinheit, fallen also inden Bereich der Produktmetriken. Besonders mit Aufkommen der objektorientiertenSoftwareentwicklung wurden viele Metriken vorgeschlagen, die die besonderen Struk-turen objektorientierter Systeme zum Gegenstand haben. Man kann daher zwischen

28

4.5 Beispiele von Softwaremetriken

Quality

Portability

Portability Compliance

Replaceability

Co-Existence

Installability

Adaptability

Maintainability

Maintainability Compliance

Testability

Stability

Changeability

Analyzability

E�ciency

E�ciency Compliance

Resource Utilisation

Time Behaviour

Usability

Usability Compliance

Attractiveness

Operability

Learnability

Understandability

Reliability

Reliability Compliance

Recoverability

Fault Tolerance

Maturity

Functionality

Functionality Compliance

Security

Interoperability

Accuracy

Suitability

Abbildung 7: Qualitätsmodell nach ISO 9126 [Int01].

objektorientierten und klassischen Metriken unterscheiden.Die klassischen Softwaremetriken sind meist älter und beziehen sich auf prozeduraleProgramme. Die wohl bekanntesten Vertreter sind Lines of Code und die zykloma-tische Komplexität von McCabe [McC76], welche im Folgenden vorgestellt werden.Weitere Vertreter sind beispielsweise die Function-Points-Berechnung [Alb79, u.a.],das COCOMO-Modell von Boehm [Boe81] [BCH�95], die Informations�uss-Metrikenvon Henry und Kafura [HK81] oder die sehr umstrittene12 Software-Science-Methodevon Halstead [Hal77]. Viele dieser klassischen Metriken können auch im objektorien-tierten Kontext eingesetzt werden, während objektorientierte Metriken in der Regelnur dort anwendbar sind.

12vgl. z.B. [FP97, S. 249]

29

4 Softwaremetriken

4.5.1 Lines of Code (LOC)

Eine verbreitete und einfache Methode, die Gröÿe einer Software zu bestimmen, istdas Zählen der Quelltextzeilen. Die Ergebnisse hängen dabei allerdings stark vonder Zählweise ab. Häu�g macht es Sinn, z.B. Leerzeilen und Kommentare nicht mit-zuzählen. Diese Variante wird auch als Non-Commented Lines of Codes (NCLOC)bezeichnet, wobei allerdings auch andere Begri�e verwendet werden [FP97, S. 247].Die Anzahl der Quelltextzeilen ist in der Regel kein vergleichbares Kriterium für dieGröÿe von Software, da sie stark von Programmiersprache und -stil abhängt.

4.5.2 Zyklomatische Komplexität

Auf Basis der Graphentheorie de�nierte McCabe 1976 die zyklomatische Komplexität(v):

vpGq � π � 1

wobei G der Kontroll�ussgraph eines Programms oder Programmteils ist und π dieAnzahl der Entscheidungsknoten innerhalb von G, also prizipiell die Anzahl der if-und Schleifenkonstrukte innerhalb des Programmteils. Nach McCabe ist die zyklo-matische Komplexität ein Maÿ für die generelle Komplexität eines Programms undsomit ein Faktor für die Wart- und Testbarkeit sowie die Fehleranfälligkeit. KeinProgrammteil sollte einen v-Wert höher als 10 haben [McC76].DeMarco kritisiert, dass eine zu hohe zyklomatische Komplexität letztlich nur einHinweis darauf sei, dass ein Modul zu lang ist und aufgeteilt werden sollte. Somit seisie eher ein Längen- und weniger ein Komplexitätsmaÿ. Da man die Länge eines Mo-duls aber viel einfacher bestimmen könne, sei die zyklomatische Komplexität somitrelativ bedeutungslos [DeM97, S. 22].

4.5.3 Objektorientierte Softwaremetriken

Mitte der 1990er Jahre wurden einige Metrikkataloge entwickelt, um die besonderenEigenschaften objektorientierter Systeme messbar zu machen. Die wichtigsten sindder von Chidamber und Kemerer [CK94], die Metrics for Object Oriented Design(MOOD) von Abreu [AC94] und der Katalog von Robert Martin [Mar94]. Die in die-sen Arbeiten de�nierten Metriken beziehen sich häu�g auf Aspekte wie Kopplung undKohäsion, Vererbungshierarchien oder die Gröÿe von Klassen und Methoden. Dochauch die Kapselung spielt teilweise eine Rolle. Hierauf wird im nächsten Abschnittnäher eingegangen.

30

4.6 Metriken zur Kapselung

4.6 Metriken zur Kapselung

In dieser Arbeit wird ein Ansatz vorgestellt, die Kapselung innerhalb eines Java-Systems zu bewerten. Im Mittelpunkt steht dabei der Umgang der Entwicklerinnenund Entwickler mit Zugri�smodi�katoren. Hierzu lässt sich in der Literatur bisherkeine vergleichbare Arbeit �nden. Jedoch gibt es bereits Metriken zu anderen Aspek-ten der Kapselung.

Der MOOD-Katalog von Abreu [AC94] beinhaltet unter anderem die Metriken Me-thod Hiding Factor (MHF) und Attribute Hiding Factor (AHF). Diese geben jeweilsden Anteil der nicht-ö�entlichen Methoden bzw. Felder an deren Gesamtzahl inner-halb einer oder aller Klassen eines Systems an. Da Felder ohnehin nicht ö�entlichsein sollten13, sollte der AHF-Wert idealerweise immer 1 betragen.Cao und Zhu [CZ08] erweitern diese Metriken, indem sie die Anzahl der Klassen, dieauf eine Methode oder Feld Zugri� haben, mit einrechnen und daraus den Information-Hiding Factor (IHFC) einer Klasse ableiten.Ein ähnliches Prinzip verfolgen Saini und Aggarwal [SA07], die jedoch von einemKapselungsbegri� ausgehen, der sich nur auf die Nicht-Zugreifbarkeit von Daten be-zieht. Aus der Anzahl der Klienten, die auf die Felder einer Klassen zugreifen können,berechnen sie deren Data Visibility (DV). Diese bildet wiederum zusammen mit derebenfalls dort de�nierten Kohäsionsmetrik Class Unity (CU) eine Formel für einenEncapsulation Factor (EF).Alle diese Ansätze haben gemeinsam, dass sie allein die Klasse als Abstraktionseinheitsehen. Die Kapselung von Klassen innerhalb von Paketen wird gar nicht betrachtet.

Noch aus der prozeduralen Welt stammt die Metrik von Rising und Calliss [RC94].Rising und Calliss beziehen sich auf das Geheimnisprinzips nach Parnas [Par72], wo-nach ein Modul genau eine Entwurfsentscheidung kapseln soll und diese hinter einerminimalen Schnittstelle zu verbergen sei. Ihre Metrik Information Hiding (IH) ergibtsich aus der Summe der ö�entlichen Variablen eines Moduls und dem Term �2�p0|1q�,wobei der Faktor �(0|1)� 0 ist, wenn das Modul genau eine Entwurfsentscheidung kap-selt, oder anderenfalls 1. Da sich letztere Frage kaum automatisiert beantworten lässt,handelt es sich hierbei um ein Beispiel für eine subjektive Metrik, also einer Metrik,die auf menschlicher Einschätzung beruht.

13 vgl. Kapitel 3.1.1

31

5 Zwei neue Java-Metriken

5 Zwei neue Java-Metriken

Um die adäquate Verwendung von Zugri�smodi�katoren messbar und somit einerQualitätskontrolle zugänglich zu machen, führe ich nun zwei neue Metriken ein, diedie Zugri�smodi�katoren von Typen und Methoden zum Gegenstand haben:

• Die Metrik Inappropriate Generosity with Accessibility of Types (IGAT) be-schreibt den Anteil derTypen innerhalb des Quelltextes eines Java-Programms,die mit einem zu groÿzügigen Zugri�smodi�kator14 versehen sind.

• Die Metrik Inappropriate Generosity with Accessibility of Methods (IGAM)beschreibt den Anteil der Methoden innerhalb des Quelltextes eines Java-Programms, die mit einem zu groÿzügigen Zugri�smodi�kator versehen sind.

5.1 De�nitionen

5.1.1 IGAT

De�nition 3:Die Metrik Inappropriate Generosity with Accessibility of Types (IGAT) sei fol-gendermaÿen de�niert:

IGAT pU, P q � |T�pU,P q||T pUq|

wobei

• P der Quelltext aller Übersetzungseinheiten eines Java-Programms ist,

• U mit U � P eine Quelltext-Teilmenge aus P (z.B. der gesamte Quelltext, einPaket oder eine Typdeklaration)

• T pUq die Menge aller in U deklarierten Typen und |T pUq| deren Anzahl,

• T �pU, P q mit T �pU, P q � T pUq die Menge aller in U deklarierten Typen, derenZugri�smodi�kator jeweils groÿzügiger ist als der minimale Zugri�smodi�kator inBezug auf P , und |T �pU, P q| deren Anzahl.

Gleichbedeutend mit IGAT pU, P q ist �der IGAT(-Wert) von U (in Bezug auf P )�, wo-bei �in Bezug auf P � dann weggelassen wird, wenn eindeutig ist, auf welcher Basis dieminimalen Zugri�smodi�katoren ermittelt wurden.

14 vgl. De�nition 2, Kapitel 3.3

32

5.1 De�nitionen

Die Metrik IGAT beschreibt den Anteil der Typen innerhalb einer echten oder unech-ten Teilmenge des Quelltextes eines Java-Programms, die mit einem zu groÿzügigenZugri�smodi�kator versehen sind. Sie lässt sich somit sowohl für ein komplettes Java-Programm, als auch für einzelne Pakete und Typen berechnen � allerdings immer mitBezug auf den Quelltext des gesamten Programms, da auf dieser Basis die minimalenZugri�smodi�katoren ermittelt werden.

Beispiel 1Angenommen wir haben ein Java-Programm �Malkasten� vorliegen. Durch eineAnalyse des gesamten Malkasten-Quelltextes haben wir festgestellt, dass darin24 Klassen und Interfaces enthalten sind, von denen 18 mit dem minimalenund sechs mit einem zu groÿzügigen Zugri�smodi�kator versehen sind. DerIGAT des gesamten Malkasten-Projekts bzw. IGAT pMalkasten,Malkastenqist also 6

24� 0, 25.

Von den sechs Typen, deren Zugri�smodi�kator zu groÿzügig ist,be�nden sich vier in dem Paket malkasten.formen, das insge-samt acht Typen enthält. Der IGAT von malkasten.formen bzw.IGAT pmalkasten.formen,Malkastenq beträgt daher 4

8� 0, 5.

Einer der Typen, deren Zugri�smodi�kator zu groÿzügig ist, ist die Klassemalkasten.formen.Kreis. Der einzige in der Klassendeklaration vonKreis enthaltene Typ ist trivialerweise Kreis selbst. Der IGAT von Kreisbzw. IGAT pKreis,Malkastenq beträgt somit 1

1� 1.

Beispiel 2Die Gra�ken in Abb. 8 zeigen drei mal schematisch das gleiche Java-Projekt.Dieses ist in drei Pakete mit insgesamt neun Typdeklarationen aufgeteilt. Diegrau hinterlegten Typen sind diejenigen, deren tatsächlicher Zugri�smodi�ka-tor groÿzügiger ist als ihr minimaler. Grundlage für deren Bestimmung sinddie Benutztbeziehungen (Pfeile) innerhalb des Gesamtprojekts P . Je nachdemfür welche Untermenge Ui von P der IGAT berechnet werden soll, ergibt sichdie Gesamtzahl der Typen |T pUiq| und die Anzahl der Typen mit zu groÿzügi-gem Zugri�smodi�kator |T �pUi, P q|. Der Bereich P , aus dem die Benutztbezie-hungen für die Bestimmung der minimalen Zugri�smodi�katoren herangezogenwerden, ist aber immer der gleiche.

Da die Anzahl der Typen, die mit einem zu groÿzügigen Zugri�smodi�kator versehensind, zwangsläu�g kleiner oder gleich der Gesamtzahl der Typen in der gleichenQuelltextmenge ist, ergibt sich für IGAT immer ein Wert zwischen 0 und 1, wobeiim Sinne der vorangegangen Ausführungen 0 das �bessere� und 1 das �schlechtere�Ende der Skala darstellt.

33

5 Zwei neue Java-Metriken

Projekt

Paket

Typ

U1

PProjekt

Paket

Typ

U2

PProjekt

Paket

P

Typ

U3

|T pU1q| � 9 |T pU2q| � 2 |T pU3q| � 1|T �pU1, P q| � 5 |T �pU2, P q| � 1 |T �pU3, P q| � 1

IGAT pU1, P q �59

IGAT pU2, P q �12

IGAT pU3, P q �11

Abbildung 8: Beispiel für die Berechnung der IGAT-Metrik. Pfeile: Benutztbeziehungen; grauhinterlegt: Typen mit zu groÿzügigem Zugri�smodi�kator.

Berechnet man den IGAT eines einzelnen Typs, sollen die zugrundeliegenden Men-gen T und T � aus nicht mehr als dem Typ selbst bestehen. Die Zugri�smodi�katorenetwaiger innerer Klassen oder Interfaces spielen für die Berechnung des IGAT desumschlieÿenden Typs somit keine Rolle. Der IGAT eines einzelnen Typs beträgt alsoimmer 0, wenn er selbst mit dem minimalen Zugri�smodi�kator deklariert ist, oderanderenfalls 1.Für die Berechnung des IGAT für Pakete oder das Gesamtprojekt werden alle Typenbis auf anonyme und lokale Klassen berücksichtigt, also auch sämtliche Memberty-pen.

5.1.2 IGAM

De�nition 4:Die Metrik Inappropriate Generosity with Accessibility of Methods (IGAM) seifolgendermaÿen de�niert:

IGAMpV, P q � |M�pV,P q||MpV q|

wobei

• P auch hier der Quelltext aller Übersetzungseinheiten eines Java-Programms ist,

34

5.1 De�nitionen

• V mit V � P eine Quelltext-Teilmenge aus P (z.B. der gesamte Quelltext, einPaket, eine Typ- oder Methodendeklaration)

• MpV q die Menge aller in V deklarierten Methoden und |MpV q| deren Anzahl,

• M�pV, P q mitM�pV, P q �MpV q die Menge aller in V deklarierten Methoden, de-ren Zugri�smodi�kator jeweils groÿzügiger ist als der minimale Zugri�smodi�katorin Bezug auf P , und |M�pV, P q| deren Anzahl.

Gleichbedeutend mit IGAMpV, P q ist �der IGAM(-Wert) von V (in Bezug auf P )�, wobeiauch hier �in Bezug auf P � dann weggelassen wird, wenn eindeutig ist, auf welcher Basisdie minimalen Zugri�smodi�katoren ermittelt wurden.

BeispielDie Klasse Kreis aus dem Malkasten-Projekt enthält insgesamt zehn Me-thoden. Die Analyse ergab, dass nur eine dieser zehn Methoden einenzu groÿzügigen Zugri�smodi�kator hat, legt man ihre Verwendung im ge-samten Malkasten-Projekt zu Grunde. Für den IGAM von Kreis bzw.IGAMpKreis,Malkastenq ergibt sich daher 1

10� 0, 1.

Die Methode, deren Zugri�smodi�kator nicht minimal ist, ist drehen().Die einzige in der Methodendeklaration von drehen() enthaltene Metho-de ist trivialerweise drehen() selbst. Der IGAM von drehen() bzw.IGAMpdrehenpq,Malkastenq beträgt somit 1

1� 1.

Die Metrik IGAM beschreibt den Anteil der Methoden innerhalb einer echten oderunechten Teilmenge des Quelltextes eines Java-Programms, die mit einem zu groÿzü-gigen Zugri�smodi�kator versehen sind. Sie lässt sich somit sowohl für ein komplet-tes Java-Programm als auch für einzelne Pakete, Typen und Methoden berechnen� analog zu der IGAT-Metrik immer mit Bezug auf den Quelltext des gesamtenProgramms, auf dessen Basis die minimalen Zugri�smodi�katoren ermittelt werden.Der Wert liegt auch hier immer zwischen 0 und 1, wobei 0 das �bessere� und 1 das�schlechtere� Ende der Skala darstellt.

Prinzipiell kann eine einzelne Methode andere Methoden enthalten, wenn in ihr lokaleoder anonyme Klassen deklariert sind. Ob deren Methoden mit einem zu groÿzügigenZugri�smodi�kator deklariert sind oder nicht, spielt für den IGAM der umschlieÿen-den Methode aber keine Rolle. Lokale und anonyme Klassen sind ohnehin nur imKontext des umschlieÿenden Blocks sichtbar15, daher sind die Zugreifbarkeiten ih-rer Methoden irrelevant. Bei der Berechnung des IGAM einer Methode bestehen dieMengen M und M� also immer höchstens aus der Methode selbst. Der Wert beträgt0, wenn sie mit dem minimalen Zugri�smodi�kator versehen ist, anderenfalls 1.Für die Berechnung des IGAM eines Typs sollen ebenso nur die eigenen Methoden

15 vgl. Kapitel 2.4.6

35

5 Zwei neue Java-Metriken

und nicht die Methoden etwaiger innerer Typen berücksichtigt werden. Für die Be-rechnung des IGAM für Pakete und das Gesamtprojekt werden alle Methoden bisauf solche in anonymen oder lokalen Klassen berücksichtigt. Konstruktoren werdenim Sinne der Metrik wie Methoden behandelt und gehen ebenfalls in die IGAM-Berechnung ein.

Diese und die im vorangegangenen Abschnitt aufgestellten Konventionen dienen da-zu, den Interpretationsspielraum bei der Berechnung der Metriken weitestgehendeinzuschränken. Dadurch soll vermieden werden, dass ggf. verschiedene Implementa-tionen zu unterschiedlichen Ergebnissen führen, was bei anderen Metriken durchausder Fall ist [LLL08].

5.2 Bestimmung der minimalen Zugri�smodi�katoren

Der erste und aufwendigste Schritt zur Berechnung von IGAT und IGAM besteht dar-in, durch eine statische Analyse des Quelltextes die minimalen Zugri�smodi�katorensämtlicher Typen und Methoden der betrachteten Quelltextmenge zu bestimmen.Um den minimalen Zugri�smodi�kator eines Elements zu bestimmen, müssen alleBenutzungen dieses Elements innerhalb des Quelltextes des Gesamtprojekts ermit-telt werden. Der niedrigste Zugri�smodi�kator, der dann diesem Element zugewie-sen werden muss, um sämtliche ermittelten Benutzungen zu gewährleisten und alleSprachregeln16 einzuhalten, ist der minimale Zugri�smodi�kator.Elemente, die überhaupt nicht benutzt werden, sollen dementsprechend markiert wer-den. Hierfür führe ich den Pseudozugri�smodi�kator not used ein, der im Sinne derDe�nition 117 strenger sei als alle anderen.Die in Java möglichen Benutztbeziehungen für Typen und Methoden sind im AnhangB aufgeführt.

5.2.1 Benutzung von Typen

Die minimalen Zugri�smodi�katoren von Typen sind durch eine statische Analyserecht einfach zu bestimmen. Zwar gibt es für Typen � wie in Anhang B zu sehen �sehr viel mehr Ausprägungen der Benutzung als für Methoden, doch sind diese zumeinen in der Regel sehr einfach zu erkennen und zum anderen ergibt sich der minimaleZugri�smodi�kator direkt aus dem Verhältnis der Klienten zu dem benutzten Typ.Die Benutztbeziehungen für Typen lassen sich grob in zwei Gruppen aufteilen: ex-plizite und implizite Benutzungen. Explizite Benutzungen sind solche, bei denen der

16 vgl. Kapitel 2.4 und 3.217 vgl. Kapitel 2.2.2

36

5.2 Bestimmung der minimalen Zugri�smodi�katoren

benutzte Typ namentlich im Quelltext auftaucht, z.B. sieht man bei Deklaration ei-ner Variablen in der Form �U u;� sofort, dass hier der Typ U benutzt wird.Bei impliziten Benutzungen taucht der benutzte Typ nicht direkt im Quelltext auf,sondern ergibt sich durch Auswertung eines Ausdrucks. Greift man beispielsweise aufden Rückgabewert einer Methode zu, wie z.B. in �a = X.foo().bar;�, wird derRückgabetyp dieser Methode, hier also der von X.foo() benutzt. Dieser Typ lässtsich meist recht leicht ermitteln, da er bei der Deklaration der Methode, hier im TypX oder einer der Obertypen von X, genannt wird.In einem Fall ist hierbei eine weitere Regel zu beachten: Es kann vorkommen, dassein Interface eine Methode mehrfach, aber mit verschiedenen Rückgabetypen, erbt.Da in solchen Situationen die möglichen Rückgabetypen jedoch in einer Vererbungs-beziehung stehen müssen, gilt die Regel, dass der benutzte Typ derjenige ist, der inder Vererbungshierarchie weiter unter steht [JLS05, � 9.4.1].

BeispielDas Interface X aus Abb. 9 erbt die Methode foo() sowohl von seinem Oberin-terface X1 als auch von X2. foo() ist jeweils mit unterschiedlichen Rückgabe-typen de�niert: in X1 mit U und in X2 mit V. Diese Konstellation ist möglich,da die Rückgabetypen selbst in einer Vererbungsbeziehung stehen. V ist einUntertyp von U. Wird foo() nun an einem Ausdruck vom Typ X aufgerufen,und der Rückgabewert von foo() benutzt, ist der benutzte Typ derjenige, derin der Vererbungshierarchie weiter unten steht, also V.

U

V

<<interface>>

X1

foo : U

<<interface>>

X2

foo : V

<<interface>>X

Abbildung 9: Beispiel für eine mehrfach geerbte Methode mit nicht einheitlichem Rückgabetyp.

Der Zugri�smodi�kator, der für eine einzelne Benutzung notwendig ist, ergibt sichaus dem Verhältnis zwischen Klient und benutztem Typ. Handelt es sich bei dem be-nutzten Typ um einen Top-Level-Typ, ist der notwendige Zugri�smodi�kator default,wenn beide Typen zum selben Paket gehören, oder public, wenn sie zu unter-schiedlichen Paketen gehören. Ist der benutzte Typ ein Membertyp, kommen nochprivate und protected in Frage. Der minimale Zugri�smodi�kator des Typsist schlieÿlich der groÿzügigste notwendige Zugri�smodi�kator aller seiner Benutzun-gen.

37

5 Zwei neue Java-Metriken

5.2.2 Benutzung von Methoden

Etwas komplizierter ist die Analyse der Methoden. Hier gibt es zwar weniger Formender Benutzung, siehe Anhang B, doch lässt sich der minimale Zugri�smodi�katoraus diesen nicht so einfach bestimmen wie bei Typen. Hier spielen sämtliche Regelnzu Überschreibungshierarchien, Interfaces und Main-Methoden sowie die Spezialfälleeine Rolle18.Auÿerdem ergibt sich der notwendige Zugri�smodi�kator einer einzelnen Benutzungnicht nur aus dem Verhälnis zwischen Klient und benutzter Methode, sondern zumeinen aus dem Verhältnis zwischen Klient und dem Typ, in dem die Methode dekla-riert wurde, und zum anderen aus dem Verhältnis zwischen Klient und dem Typ desAusdrucks, an dem die Methode aufgerufen wird.

Beispiel

class A {void foo() {

...}

void bar(A a, U u) {a.foo();u.foo();

}}

class U extends A {}

Die Klasse A enthält eine Methode foo(), die in der ebenfalls in A dekla-rierten Methode bar() zweimal aufgerufen wird. Sowohl der deklarierende alsauch der benutzende Typ von foo() ist somit A. Für die erste Benutzung vonfoo() wäre private der notwendige Zugri�smodi�kator, da hier der Typdes Ausdrucks, an dem foo() aufgerufen wird, also a, ebenfalls A ist. Für diezweite Benutzung wäre allerdings ein groÿzügigerer Zugri�smodi�kator notwen-dig19, da der Typ des Ausdrucks u nicht A ist, sondern U, eine Unterklasse vonA.

Um beim Aufruf einer Operation die jeweils benutzte Methode zu bestimmen, ermit-telt man zunächst den Ausdruck, an dem die Operation aufgerufen wird. Im Fall von�u.foo();� im oben aufgeführten Beispiel ist dies also U. Nun sucht man von U ausentlang des Vererbungspfades die von unten gesehen erste Deklaration der Methode.Dies ist dann die benutzte Methode.

18 vgl. Kapitel 2.4 und 3.219 default oder protected, je nachdem ob U und A im selben Paket liegen, was in diesem Beispiel

o�enbar der Fall ist, da anderenfalls A und U selbst public sein müssten.

38

5.2 Bestimmung der minimalen Zugri�smodi�katoren

Handelt es sich beim Typ des Ausdrucks um ein Interface, ist die benutzte Metho-de nicht unbedingt eindeutig zu bestimmen, wenn diese in Oberinterfaces mehrfachdeklariert wurde. Da Methoden, die in Interfaces deklariert werden, aber ohnehinimmer public sein müssen, spielen hier einzelne Benutzungen keine Rolle.

Der minimale Zugri�smodi�kator einer Methode, die weder eine Main-Methode ist,noch in einem Interface deklariert wird oder eine Methode aus einem Interface imple-mentiert, ergibt sich schlieÿlich aus dem höchsten notwendigen Zugri�smodi�katoraller ihrer Benutzungen und ggf. aus dem minimalen Zugri�smodi�kator der Metho-de, die überschrieben wird.

5.2.3 Importdeklarationen

Einen Grenzfall für die Benutzung von Typen stellen Importdeklarationen (Importdeclarations) [JLS05, � 7.5] dar. Einerseits ist das bloÿe Importieren eines Typs nochkeine tatsächliche Benutzung, andererseits würde das Importieren eines nicht zu-greifbaren Typs zu einem Übersetzungsfehler führen. Nach der De�nition, dass mini-male Zugri�smodi�katoren immer die Übersetzbarkeit eines Programms gewährleis-ten müssen, müssten Import-Deklarationen also bei ihrer Bestimmung berücksichtigtwerden.Allerdings stellt der Import weiterhin nicht benutzter Typen über�üssigen Code dar,der ohnehin entfernt werden sollte. Nicht umsonst gibt beispielweise Eclipse an sol-chen Stellen die Warnung �import XY is never used � aus. Berücksichtigt man Im-portdeklaration beim Minimieren von Zugri�smodi�katoren nicht, lassen sich Über-setzungsfehler, die durch über�üssige Imports entstehen, einfach beseitigen, indemman die über�üssigen Deklarationen entfernt.Hinzu kommt, dass man mit Hilfe des Wildcard-Symbols * auch sämtliche Typen ei-nes Pakets importieren kann, z.B. �import example.*�. Daraus ergibt sich nochnicht, welcher Typ des Pakets tatsächlich benutzt wird. Importdeklarationen sollenbei der Bestimmung der minimalen Zugri�smodi�katoren also nicht berücksichtigtwerden.

Bei statischen Imports [JLS05, � 7.5.3, 7.5.4] bezieht sich das Wildcard-Symbol hin-gegen nicht auf Typen, sondern auf die Member eines konkreten Typs. So werdenmit �import static example.U.*� alle Member von example.U statisch im-portiert. Hier ist der Typ somit eindeutig festgelegt. Bei statischen Imports soll derjeweilige Typ also immer direkt als benutzt gelten, eine so importierte Methode al-lerdings erst, wenn sie tatsächlich benutzt wird. Dieses Vorgehen ist auch für dieImplementation zweckmäÿiger20.

20 vgl. Kapitel 6.5.4

39

5 Zwei neue Java-Metriken

5.3 Berechnung

Hat man auf Basis des gesamten Quelltextes des zu analysierenden Softwareprojektsfür sämtliche Typen und Methoden des zu betrachtenden Codeausschnitts den jeweilsminimalen Zugri�smodi�kator ermittelt, sind die letzten Schritte zur Berechnung vonIGAT und IGAM vergleichsweise einfach.Für die Berechnung von IGAT vergleicht man die ermittelten minimalen Zugri�s-modi�katoren mit den tatsächlichen Zugri�smodi�katoren der Typen, also den Zu-gri�smodi�katoren, die den Typen im Quelltext jeweils zugewiesen sind. Die Anzahlderjenigen Typen, bei denen der tatsächliche Zugri�smodi�kator groÿzügiger ist alsder minimale, teilt man nun durch die Anzahl aller Typen des betrachteten Codeaus-schnitts und erhält den IGAT dieses Codeausschnitts auf Basis des Gesamtprojekts.Analog verfährt man mit den Methoden zur Berechnung von IGAM.

Wie in den De�nitionen der Metriken festgelegt, ergeben sich die Werte von IGATund IGAM nur daraus, ob die tatsächlichen Zugri�smodi�katoren der Typen undMethoden groÿzügiger sind als die minimalen. Der Grad der etwaigen Abweichungenbeein�usst die Metriken nicht. Wäre dies gewünscht, müsste man eine geeignete Skala�nden, um die Abweichungen zu bewerten. Da es hierfür beliebig viele Möglichkeitengibt, würde durch solch eine Festlegung die Transparenz der Metriken leiden.Man könnte beispielsweise auf Basis der Reihenfolge not used, private, default,protected, public jeden Abweichungsschritt mit einem Punkt bewerten, z.B.private statt not used mit 1, public statt default mit 2 oder public statt notused mit 4 usw. In diesem Fall könnte man u.a. fragen: Ist einmal public stattnot used genauso schlimm wie viermal default statt private? Ist protected stattprivate wirklich genauso schlimm wie public statt default?Derartige Fragen lieÿen sich nur schwer allgemeingültig beantworten. Hingegen ist dieeinfache Aussage, dass der Zugri�smodi�kator eines Elements groÿzügiger ist als not-wendig, eindeutig. Es erscheint daher sinnvoll, auf eine Bewertung der Abweichungenzu verzichten.

5.4 Validierung und Einordnung

In Kapitel 4 wurde der Stand der Wissenschaft auf dem Gebiet der Softwaremetrikenumrissen. Nachfolgend werden die dort gelegten Grundlagen nun auf die MetrikenIGAT und IGAM angewendet. Die Bestimmung des Skalentyps und die Validierungwerden dabei exemplarisch für die Metrik IGAT durchgeführt, lassen sich aber ebensoauf IGAM übertragen.

40

5.4 Validierung und Einordnung

5.4.1 Skalentyp

Die Metrik IGAT ist ein indirektes Maÿ, das sich als Quotient aus den direkten Ma-ÿen �Anzahl der Typen mit zu groÿzügigem Zugri�smodi�kator� und �Anzahl derTypen insgesamt�, in De�nition 3 mit |T �| bzw. |T | bezeichnet, berechnet. Diesedirekten Maÿe ergeben sich aus dem bloÿen Abzählen der jeweiligen Typdeklaratio-nen, bilden also eine Absolutskala. Da Absolutskalen die Division erlauben21, ist dievorgenommene Ableitung des indirekten Maÿes IGAT möglich.

Die Division mit der Gesamtzahl der Typen dient der Normierung der Metrik, umeinen Vergleich unterschiedlich groÿer (Teil-)Systeme zu ermöglichen. Die sich dar-aus ergebene Prozentskala, eine eingeschränkte Verhältnisskala mit den Grenzen 0und 1 bzw. 0 % und 100 %, hat allerdings auch Nachteile. So sind die Operationen�,�, � und { in vielen Fällen nicht sinnvoll anzuwenden. Beispielsweise lässt sich derIGAT-Wert eines Gesamtsystems nicht aus den Einzelergebnissen seiner Teilsystemeberechnen. Hierzu sind immer die Werte der beiden direkten Maÿe notwendig.

BeispielTabelle 2 zeigt die Werte der Teilmetriken für ein Java-Programm P0, beste-hend aus drei unterschiedlich groÿen Paketen p1, p2 und p3. Berechnet manden Durchschnitt der IGAT-Werte der einzelnen Pakete und den IGAT desGesamtprogramms, ergeben sich mit 0,58 und 0,42 abweichende Ergebnisse.

U |T �pU, P0q| |T pUq| IGAT pU, P0q

p1 3 12 0,25p2 2 4 0,50p3 3 3 1,00

Σ 1,75∅ 0,58

P0 8 19 0,42

Tabelle 2: Beispiel für die Abweichung zwischen IGAT-Gesamtergebnis und Paket-Durchschnitt.

5.4.2 Validierung

Die Validierung einer Metrik besteht aus zwei Teilen: der internen und der externenValidierung22.

21 vgl. Tabelle 1, Kapitel 4.122 vgl. Kapitel 4.2

41

5 Zwei neue Java-Metriken

Die externe Validierung besteht aus der empirischen Untersuchung, ob die Metrik imjeweiligen Einsatzkontext mit vertretbarem Aufwand zu erheben ist und nützlicheErgebnisse liefert. Dies kann an dieser Stelle nicht vollständig durchgeführt werden.Einen ersten Ansatz enthalten die nachfolgenden Kapitel. Darin wird die Implemen-tation (Kapitel 6) und Erprobung (Kapitel 7) eines Messwerkzeuges beschrieben.Die interne Validierung besteht aus der Überprüfung des Skalentyps, was im vor-angegangenen Abschnitt bereits geschehen ist, und dem Prüfen der Repräsentati-onsbedingung. Zur Überprüfung der Repräsentationsbedingung sind Operationen zuidenti�zieren, die auf dem Untersuchungsgegenstand ausgeführt werden können, unddas Verhalten der Metrik mit den intuitiven Vorstellungen über die Veränderung derMesswerte zu vergleichen.

Der Untersuchungsgegenstand der Metrik IGAT sind der Quelltext P des zugrunde-liegenden Java-Programms und die Teilmenge U des Quelltextes, für die die Metrikberechnet werden soll.Als grundlegende Operationen, die die Metrik beein�ussen, können folgende identi�-ziert werden:

• Hinzufügen einer Typdeklaration zu U

• Entfernen einer Typdeklaration aus U

• Hinzufügen einer Benutztbeziehung zu einem Typ aus U zu P

• Entfernen einer Benutztbeziehung zu einem Typ aus U aus P

• Ersetzen des Zugri�smodi�kators eines Typs aus U durch einen groÿzügigeren

• Ersetzen des Zugri�smodi�kators eines Typs aus U durch einen strengeren

Unter der Annahme, dass diese Operationen unter Berücksichtigung der Sprachre-geln durchgeführt werden und nicht zu Übersetzungsfehlern führen, werden nun ihreAuswirkungen untersucht. Die Symbole U und P stehen jeweils für die entsprechen-den Quelltextmengen vor Durchführung der Operation, die Symbole U 1 und P 1 fürdie Mengen nach der Operation.

Hinzufügen einer Typdeklaration zu U : Wird ein neuer Typ hinzugefügt, wirddieser zunächst noch nicht benutzt. Der IGAT-Wert sollte also steigen, da ein garnicht verwendeter Typ hinzugefügt wird � es sei denn alle Zugri�smodi�katoren sindzu groÿzügig.

IGAT pU 1, P 1q � |T�pU 1,P 1q||T pU 1q|

� |T�pU,P q|�1|T pUq|�1

¥ |T�pU,P q||T pUq|

� IGAT pU, P q

42

5.4 Validierung und Einordnung

Da sich durch das Hinzufügen des nicht verwendeten Typs sowohl die Anzahl |T �| derTypen mit zu groÿzügigem Zugri�smodi�kator als auch die Anzahl |T | aller Typenum jeweils 1 erhöht, wächst deren Quotient � es sei denn Zähler und Nenner hattenund haben denselben Wert. In diesem Fall bleibt das Ergebnis 1. Die Metrik verhältsich also korrekt.

Entfernen einer Typdeklaration aus U : Wird ein Typ entfernt, wurde dieserzuvor nicht benutzt. Der IGAT-Wert sollte also sinken, da ein nicht verwendeter Typentfernt wird � es sei denn alle Zugri�smodi�katoren sind zu groÿzügig.

IGAT pU 1, P 1q � |T�pU 1,P 1q||T pU 1q|

� |T�pU,P q|�1|T pUq|�1

¤ |T�pU,P q||T pUq|

� IGAT pU, P q

Hinzufügen einer Benutzbeziehung zu einem Typ aus U zu P : Wird einTyp, der zuvor einen zu groÿzügigen Zugri�smodi�kator hatte, nun innerhalb von Pso benutzt, dass der minimale Zugri�smodi�kator dem tatsächlichen entspricht, dannsollte der IGAT-Wert sinken.

IGAT pU 1, P 1q � |T�pU 1,P 1q||T pU 1q|

� |T�pU,P q|�1|T pUq|

  |T�pU,P q||T pUq|

� IGAT pU, P q

Entfernen einer Benutzbeziehung zu einem Typ aus U aus P : Wird einTyp, bei dem der tatsächliche Zugri�smodi�kator zuvor dem minimalen entsprach,innerhalb von P nur noch so benutzt, dass ein strengerer Zugri�smodi�kator aus-reicht, sollte der IGAT-Wert steigen.

IGAT pU 1, P 1q � |T�pU 1,P 1q||T pU 1q|

� |T�pU,P q|�1|T pUq|

¡ |T�pU,P q||T pUq|

� IGAT pU, P q

Ersetzen des Zugri�smodi�kators eines Typs aus U durch einen groÿzügi-geren: Erhält ein Typ, dessen tatsächlicher Zugri�smodi�kator seinem minimalenentspricht, einen groÿzügigeren, sollte der IGAT-Wert steigen.

IGAT pU 1, P 1q � |T�pU 1,P 1q||T pU 1q|

� |T�pU,P q|�1|T pUq|

¡ |T�pU,P q||T pUq|

� IGAT pU, P q

43

5 Zwei neue Java-Metriken

Ersetzen des Zugri�smodi�kators eines Typs aus U durch einen strenge-ren: Erhält ein Typ mit einem zu groÿzügigem Zugri�smodi�kator einen strengeren,der nun seinem minimalen entspricht, sollte der IGAT-Wert sinken.

IGAT pU 1, P 1q � |T�pU 1,P 1q||T pU 1q|

� |T�pU,P q|�1|T pUq|

  |T�pU,P q||T pUq|

� IGAT pU, P q

In allen aufgeführten Fällen verhält sich die Metrik entsprechend den intuitiven Vor-stellungen. Somit kann davon ausgegangen werden, dass die Repräsentationsbedin-gung erfüllt ist.

5.4.3 Klassi�zierung

Die Metriken IGAT und IGAM sind im Sinne Fenton und P�eegers interne Produkt-metriken, da sie einen Aspekt der inneren Struktur einer Software beschreiben.

Nach dem Schema von Bennicke und Rust beschreibt die Metrik IGAM die Elementeder Verhaltensebene, da sie die Zugreifbarkeit von Methoden zum Gegenstand hat.Die Metrik IGAT ist wiederum auf der Entwurfsebene einzuordnen. Wie dargestelltlassen sich beide Metriken aber ebenso auf höheren Ebenen berechnen.Da die Benutzungsbeziehungen zwischen den Elementen einen entscheidenden Ein-�uss auf die Metriken haben, kann man sie im Sinne Bennicke und Rusts auch alsInter-Metriken bezeichnen23.

5.5 Einsatzmöglichkeiten

5.5.1 Qualitätsmodelle

Im Rahmen individueller Qualitätsmodelle können IGAT und IGAM eingesetzt wer-den, um den angemessenen Umgang der Entwicklerinnen und Entwickler mit Zu-gri�smodi�katoren, die Kapselung und die Minimalität von Schnittstellen zu bewer-ten. Gute IGAT- und IGAM-Werte können Ein�uss auf die Verständlichkeit einerSoftware haben, da an die tatsächliche Benutzung angepasste Zugreifbarkeiten dieBenutzungsebenen explizit machen. Sie erleichtern die Änderbarkeit, da strengereZugreifbarkeiten die Menge der Abhängigkeiten begrenzen können. Negative Auswir-kungen können sie haben auf die Testbarkeit und Erweiterbarkeit, wenn auf vorhan-dende Funktionalität nicht zugegri�en werden darf.Ob diese Zusammenhänge im jeweiligen Einsatzkontext tatsächlich zu beobachten

23 vgl. Kapitel 4.3.1

44

5.5 Einsatzmöglichkeiten

sind, wäre im Rahmen der externen Validierung nachzuweisen. Dies geht allerdingsüber den Rahmen dieser Arbeit hinaus.

5.5.2 Refactoring

Refactoring ist das zentrale Verfahren, um die innere Qualität von Software zu erhö-hen. Beim Refactoring ändert man die Struktur eines Quelltextes in kleinen, klar be-schriebenen Schritten, um ihn so verständlicher und leichter änderbar zu machen. Da-bei wird die Funktionalität der Software ausdrücklich unverändert gelassen [Fow99].Stellt man beispielsweise fest, dass eine Klasse unnötigerweise zur Schnittstelle einesPakets gehört, bestünde die entsprechende Refactoring-Maÿnahme aus dem Entfer-nen des public-Modi�kators dieser Klasse.Es ist jedoch nicht immer ohne Weiteres erkennbar, an welchen Stellen ein Quelltextein Refactoring nötig hat. Metriken können helfen, diese Stellen aus�ndig zu machen[SSL01].

Berechnet man die Metriken IGAT und IGAM nicht nur für ein gesamtes Software-projekt, sondern auch für einzelne Pakete und Klassen, können schnell die Bereichegefunden werden, an denen eine Überprüfung der Schnittstellen am dringendsten ist.Hat ein Entwickler darüber hinaus Zugri� auf die bei der Berechnung ermitteltenminimalen Zugri�smodi�katoren, kann er sich bei der Überarbeitung an diesen ori-entieren.Es wäre sogar möglich, anhand der ermittelten minimalen Zugri�smodi�katoren al-le Schnittstellen innerhalb einer Software vollständig automatisch auf das Minimumeinzuschränken24, doch wäre dies nicht empfehlenswert. Es kann � wie bereits darge-stellt25 � Gründe geben, weshalb der minimale Zugri�smodi�kator nicht unbedingtder gewünschte ist. Am Ende sollte daher immer eine Entwicklerin oder eine Entwick-ler entscheiden, welchen Zugri�smodi�kator ein Element erhält. IGAT und IGAMkönnen dabei unterstützen.

Eine regelmäÿige Berechnung von IGAT und IGAM für ein gesamtes Softwarepro-jekt könnte zudem anzeigen, wann eine gesonderte Überprüfung der Schnittstellenangebracht ist.

24 Soll so eine automatische Einschränkung aller Schnittstellen tatsächlich erfolgen, ist zu beachten,dass hierzu ggf. mehrere Durchläufe erforderlich sind. Durch das Entfernen von mit not usedmarkierten Typen und Methoden fallen Benutztbeziehungen weg, wodurch sich wiederum dieminimalen Zugri�smodi�katoren anderer Typen und Methoden verändern können.

25 vgl. Kapitel 3.4.1

45

5 Zwei neue Java-Metriken

5.6 Grenzen

Die Bestimmung der minimalen Zugri�smodi�katoren und die Berechnung der Metri-ken beruht auf der genauesten Beachtung der Java-Sprachde�nition [JLS05]. Nebenden allgemeinen Regeln sind auch alle Spezialfälle, seien sie auch noch so ungewöhn-lich oder softwaretechnisch unvernünftig, zu berücksichtigen. Das grundsätzliche Ver-fahren wurde hier dargestellt, eine entsprechende Umsetzung ist im nachfolgendenKapitel 6 beschrieben. Jedoch verfügt der Ansatz über einige theoretische Grenzen,die beim Einsatz der Metriken zu beachten sind.

5.6.1 Benutzungen auÿerhalb des eigenen Projekts

Die geschilderte Vorgehensweise zur Bestimmung der minimalen Zugri�smodi�kato-ren und der darauf aufbauenden Berechnung von IGAT und IGAM kann nur Be-nutzungen von Typen und Methoden innerhalb der Quelltextbasis berücksichtigen,die für die Analyse zur Verfügung steht. Ist beispielsweise eine public deklarierteKlasse als Teil einer API für die Verwendung in anderer Software vorgesehen undwird im analysierten Projekt selbst nicht verwendet, wird diese Klasse das Ergebnisfür IGAT ungewollt verschlechtern.

5.6.2 Metaprogrammierung

Die strenge Typisierung von Java macht es in der Regel möglich, durch statischeAnalyse die Stellen im Quelltext zu �nden, an denen ein Typ oder eine Methodebenutzt wird. Dies stöÿt allerdings an seine Grenzen, wenn Metaprogrammierungz.B. mit Hilfe der Java Re�ection API eingesetzt wird.Die Java Re�ection API ermöglicht es u.a., Typen oder Methoden zu benutzen, indemihr deren Namen in Form von Strings übergeben werden (vgl. [AGH05, S. 397�]). Dadiese Strings aber auf beliebige Weise erzeugt oder übergeben werden können, lässtsich erst zur Laufzeit ermitteln, welche Typen und Methoden gemeint sind. Wie beianderen Metriken und Methoden, die auf einer statischen Analyse des Quelltextesberuhen, können diese Re�ection-basierten Abhängigkeiten bei der Berechnung vonIGAT und IGAM in der Regel nicht berücksichtigt werden.

46

5.6 Grenzen

Beispiel

class A {Object foo(String n) throws ClassNotFoundException,

InstantiationException, IllegalAccessException {Class c = Class.forName(n);return c.newInstance();

}}

Hier wird ein Exemplar einer Klasse erzeugt, deren Namen über den Parametern übergeben wird. Dies geschieht, indem durch den Aufruf der statischen Me-thode Class.forName(String className) zunächst ein entsprechendesObjekt von java.lang.Class erzeugt wird. Mit dem Class-Objekt kannman nun durch Aufruf von newInstance() wiederum ein Exemplar der je-weiligen Klasse erzeugen. Dies funktioniert hier allerdings nur, wenn A auf dieseKlasse zugreifen darf, anderenfalls wird eine IllegalAccessException ge-worfen.

5.6.3 Bereits ausgenutzte Groÿzügigkeit

Die Metriken IGAT und IGAM sagen nur etwas über die Minimalität der Schnitt-stellen aus, wenn man davon ausgeht, dass die tatsächlichen Benutzungsbeziehungeninnerhalb des Quelltextes diese Minimalität de�nieren. Im Code können aber bereitsunnötige Benutztbeziehungen enthalten sein. Eine mangelhafte Kapselung, die aufdiese Weise ausgenutzt wird, verschlechtert nicht die Werte von IGAT und IGAM.

BeispielIm Folgenden ist eine einfache Implementation eines Stacks aufgeführt; mit denklassischen Operationen push zum Ablegen eines Objekts auf dem Stack, popzum Holen und Entfernen des obersten Objekts, peek zum Holen des oberstenObjekts ohne es zu entfernen und empty zum Abfragen, ob der Stack leer ist.

Diese Stack-Implementation basiert auf einer Verkettung von Exemplaren derinneren Klasse Element. Jeder Stack hält über das Feld top eine Referenzauf sein oberstes Element. Dieses Element hält wiederum eine Referenz aufdas eigentlich abgelegte Object und das nächste Element im Stack usw.Die Felder sind wie üblich private deklariert und der Zugri� auf sie überGetter und Setter gekapselt, die intern benutzt werden.Unglücklicherweise sind die Getter und Setter sowie die innere Klasse Elementpublic deklariert. Dies könnte z.B. zur Folge haben, dass ein Klient, derein Objekt auf dem Stack ablegen möchte, anstatt die dafür vorgesehene Me-thode push() zu benutzen, selbst ein Exemplar von Element erzeugt und

47

5 Zwei neue Java-Metriken

setTopElement() aufruft, weil beispielsweise der Entwickler die Schnitt-stellenbeschreibung von Stack nicht zu Ende gelesen hat.Wäre dies der Fall, wäre hier eine mangelhafte Kapselung gegeben, die von denMetriken IGAT und IGAM nicht berücksichtigt würde, da durch die unnötigeBenutzung von setTopElement() und Element deren minimaler Zugri�s-modi�kator fälschlicherweise höher ist.

public class Stack {

private Element top = null;

public Element getTopElement() { return top; }

public void setTopElement(Element e) { top = e; }

public class Element {private Object o;private Element next;

public Element(Object o, Element next) {this.o = o;this.next = next;

}

public Object getObject() { return o; }

public Element getNextElement() { return next; }}

public boolean empty() {return getTopElement() == null;

}

public void push(Object o) {setTopElement(new Element(o, getTopElement()));

}

public Object peek() {if (empty()) {

return null;}return getTopElement().getObject();

}

public Object pop() {Object o = peek();if (! empty()) {

setTopElement(getTopElement().getNextElement());

}return o;

}}

48

6 Umsetzung

Um die hier vorgestellten Konzepte umzusetzen, habe ich das Werkzeug AccessAna-lysis entwickelt, das Java-Quelltext analysieren, minimale Zugri�smodi�katoren be-stimmen und die Metriken IGAT und IGAM berechnen kann. AccessAnalysis ist einPlug-In für die Entwicklungsumgebung Eclipse26.

6.1 Plattform

Als Basis für die Entwicklung von AccessAnalysis habe ich die Entwicklungsum-gebung Eclipse gewählt, da diese zum einen frei verfügbar und zum anderen weitverbreitet ist. Einige der für diese Arbeit analysierten Softwareprojekte27 werden oh-nehin in Eclipse entwickelt, so dass sie für das Werkzeug leicht zugänglich waren.Auÿerdem bietet Eclipse bereits eine umfassende Infrastruktur, die man für eigeneErweiterungen verwenden kann.

Eclipse ist nicht nur eine Java-Entwicklungsumgebung, sondern auch eine allgemei-ne Plattform für komponentenbasierte Anwendungen. Seit der Version 3.0 basiertdie Eclipse-Laufzeitumgebung auf Equinox 28, einer eigenen Implementation des OS-Gi -Standards29. Darauf aufbauend bildet ein Paket grundlegender OSGi-Bundles, inEclipse Plug-Ins genannt, die Eclipse Rich Client Platform (RCP). Diese Basis kanndurch eigene Plug-Ins zu jeder Art von Desktop-Anwendungen ausgebaut werden.Ein Sammlung solcher Plug-Ins sind die Eclipse Java Development Tools (JDT), dieEclipse zu dem machen, für das es in erster Linie bekannt ist: eine Java-Entwicklungs-umgebung. Das AccessAnalysis-Plug-In erweitert wiederum die JDT. Abb. 10 zeigtden grundsätzlichen Aufbau dieser Architektur. Inzwischen ist Eclipse in der Version3.6 erschienen. Bei der Entwicklung von AccessAnalysis habe ich aber noch Eclipse3.5 eingesetzt. Wie die Eclipse-Plattform und die meisten Plug-Ins ist auch Access-Analysis vollständig in Java implementiert.

6.2 Benutzungskonzept

Das Plug-In AccessAnalysis ermöglicht es, in Eclipse ein oder mehrere Java-Projekteauszuwählen und auf deren Basis die minimalen Zugri�smodi�katoren aller enthal-tenen Typen und Methoden zu bestimmen. Daraus resultierend werden dann die

26 http://eclipse.org27 vgl. Kapitel 728 http://eclipse.org/equinox29 http://www.osgi.org

49

6 Umsetzung

�� ��AccessAnalysis�� ��.�� ��.�� ��.�� ��Eclipse JDT�� ��.�� ��.�� ��.�� ��.

�� ��.�� ��.�� ��Eclipse RCP�� ��.�� ��.�� ��.�� ��Equinox OSGi Framework�� ��Java Runtime Environment

Abbildung 10: Architektur der Eclipse-Plattform mit AccessAnalysis-Plug-In.

Abbildung 11: Screenshot der AccessAnalysis-View mit den Ergebnissen einer Beispielanalyse.

Ebene IGAT IGAM Minimal Access Actual Access

Projekte 0..1 0..1 - -

ë Pakete 0..1 0..1 - -

ë Typen 0; 1 0..1 not used; private; default;protected; public

private; default;protected; public

ë Methoden - 0; 1 not used; private; default;protected; public

private; default;protected; public

Tabelle 3: Die Ebenen der Ergebnisausgabe von AccessAnalysis mit den Wertemengen der je-weiligen Spalten.

50

6.3 Verwendetes Framework

Metriken für jedes der ausgewählten Projekte sowie alle darin enthalten Pakete, Ty-pen und Methoden berechnet.Die Präsentation der Ergebnisse erfolgt in der AccessAnalysis-View 30 in einer baumar-tigen Tabelle. Die oberste Ebene des Baumes bilden die ausgewählten Projekte, dar-unter folgen die Pakete der jeweiligen Projekte, dann die Typen und schlieÿlich dieMethoden.Die Ergebnistabelle (Abb. 11) besteht aus fünf Spalten: Die erste enthält den Na-men der jeweiligen Einheit, dann folgen zwei Spalten für die Metriken IGAT undIGAM. Die letzten beiden Spalten enthalten die durch die Analyse ermittelten mi-nimalen und tatsächlichen Zugri�smodi�katoren (�Minimal Access� und �Actual Ac-cess�). Stimmen der minimale und der tatsächliche Zugri�smodi�kator eines Elementsnicht überein, wird dies besonders hervorgehoben.Nicht jede Spalte enthält auf allen Ebenen Werte. So können nur für Typen undMethoden Zugri�smodi�katoren angezeigt werden. Methoden haben wiederum kei-nen Wert für IGAT. Tabelle 3 zeigt die Wertemengen der Spalten auf den jeweiligenErgebnisebenen.Eine Installations- und Benutzungsanleitung für das AccessAnalysis-Plug-In �ndetsich in Anhang C.

6.3 Verwendetes Framework

Die Plug-Ins der Java Development Tools machen Eclipse zur Java-Entwicklungsum-gebung. Sie enthalten die für die Entwicklung von Java-Programmen nötigen Edito-ren, Werkzeuge, Compiler und Debug-Komponenten. Auÿerdem bieten die JDT einebreite API [JDT09], die Entwicklerinnen und Entwickler anderer Plug-Ins verwendenkönnen, um darüber Java-Quelltext auszulesen, zu verändern, erzeugen, kompilierenoder auszuführen.So enthält das Paket Java DOM/AST (org.eclipse.jdt.core.dom) eine Reihevon Interfaces und Klassen, mit denen die Dokumentstruktur eines Java-Programmsmodelliert wird. Zudem bietet es die Möglichkeit, vom Compiler einen abstraktenSyntaxbaum (AST) von einer Java-Übersetzungseinheit erzeugen zu lassen und die-sen systematisch zu verarbeiten.Ein AST ist eine kompakte Darstellung eines Quelltextes in einer Baumstruktur.Die Knoten des Baumes stellen die einzelnen Sprachkonstrukte dar, aus denen derQuelltext besteht. Unwichtige Details, wie Klammern, einleitende Schlüsselworte etc.werden dabei weggelassen. Abb. 12 zeigt ein Beispiel eines AST.

30 �Views� bezeichnen in Eclipse die Bereiche, aus denen sich die Benutzungsober�äche zusammen-setzt. Sie dienen der Navigation oder der Anzeige von Informationen. Einzelne Views könnenvom Benutzer ein- und ausgeblendet werden. Ein Plug-In kann eine oder mehrere Views zu Eclip-se hinzufügen. Das AccessAnalysis-Plug-In beinhaltet die AccessAnalysis-View, die automatischeingeblendet wird, wenn eine Analyse abgeschlossen wurde.

51

6 Umsetzung

class A {int foo(U u) {

return u.bar();}

}

CompilationUnit

class A { int foo( U u){ return u.bar(); } }

TypeDeclaration

class A { int foo( U u){ return u.bar(); } }

eeeeeeeeeeeeeeeeeeeeee

YYYYYYYYYYYYYYYYYYYYYY

SimpleName

A

MethodDeclaration

int foo(U u){ return u.bar(); }

dddddddddddddddddddddddddddddd

iiiiiiiiiiiiiiii

YYYYYYYYYYYYYYYYYYYYYY

PrimitiveType

int

SimpleName

foo

SingleVariableDeclaration

U u

rrrrrrrrr

LLLLLLLLL

Block

{ return u.bar(); }

SimpleType

U

SimpleName

u

ReturnStatement

return u.bar();

SimpleName

U

MethodInvocation

u.bar()

rrrrrrrrr

LLLLLLLLL

SimpleName

u

SimpleName

bar

Abbildung 12: Beispiel eines AST im Modell der Eclipse Java Development Tools. Der o.a. Quell-text wird nach und nach in einzelne programmiersprachliche Konstrukte zerlegt. Schlüsselwortewie class oder Klammern fallen bei der Zerlegung weg. Die Wurzel des AST bildet hier dievollständige Übersetzungseinheit.

52

6.4 Algorithmus

Die Verarbeitung eines AST ermöglicht das Java-DOM/AST-Framework über dasBesuchermuster (Visitor pattern) [GHJV95, S. 331�]. Als Plug-In-Entwickler er-weitert man die abstrakte Klasse org.eclipse.jdt.core.dom.ASTVisitor.In Methoden wie visit(TypeDeclaration node) odervisit(MethodInvocation node) kann für jedes einzelne Sprachkonstrukt an-gegeben werden, wie dieses zu verarbeiten ist. Dabei liefert das übergebene Knoten-objekt node die benötigten Informationen.Beispielsweise liefert der Knoten org.eclipse.jdt.core.dom.MethodInvocation, der für einen Methodenaufruf im Quelltext steht, ein Objekt,das die aufgerufene Methode repräsentiert. Dieses Objekt vom Typ org.eclipse.jdt.core.dom.IMethodBinding enthält wiederum Informationen über die de-klarierende Klasse, Rückgabe- und Parametertypen der Methode und vieles mehr.Um eine Übersetzungseinheit mit seinem eigenen ASTVisitor zu verarbeiten, lässtman zunächst von der Klasse org.eclipse.jdt.core.dom.ASTParser denAST dieser Übersetzungseinheit erzeugen. Man erhält eine Referenz auf den Wurzel-knoten des Baumes. Dieser ist in der Regel vom Typ org.eclipse.jdt.core.dom.CompilationUnit, repräsentiert also die gesamten Übersetzungseinheit. Die-sem Knotenobjekt übergibt man über die Methode accept(ASTVisitorvisitor) seinen eigenen ASTVisitor. Nun wird nach und nach der gesamte Baumin einer Tiefensuche durchlaufen. Dabei wird für jeden Knoten des Baumes am über-gebenen ASTVisitor-Objekt die entsprechende visit()-Methode aufgerufen.

6.4 Algorithmus

Für die Bestimmung der minimalen Zugri�smodi�katoren werden nacheinander dieASTs sämtlicher Übersetzungseinheiten der zu analysierenden Projekte durchsucht.Dabei werden drei Maps31 mit Daten befüllt:

AT: ordnet Typen Zugri�smodi�katoren zu.

AM: ordnet Methoden Zugri�smodi�katoren zu.

OM: ordnet überschreibenden Methoden überschriebene Methoden zu.

Beim Durchsuchen des AST werden nun an den einzelnen Knoten je nach Knotentypkeine, eine oder mehrere der folgenden vier Aktionen durchgeführt:

31 Eine �Map� ist eine dynamische Datenstruktur, in der Datensätze durch eindeutige Schlüssel ad-dressiert werden. Die Datentypen der Datensätze und Schlüssel lassen sich weitestgehend beliebigfestlegen. Das Java Collection Framework bietet hierfür das Interface java.util.Map<K,V>sowie verschiedene Implementationen, z.B. java.util.HashMap<K,V>.

53

6 Umsetzung

Typbenutzung: Enthält der Knoten die Benutzung eines Typs t, wird der für dieseBenutzung notwendige Zugri�smodi�kator at ermittelt. Die Zuordnung pt, atqwird in AT gespeichert, sofern t noch nicht in AT enthalten ist oder der bisherzugeordnete Zugri�smodi�kator strenger ist als at.

Methodenaufruf: Enthält der Knoten den Aufruf einer Methode (oder eines Kon-struktors) m, wird der für diese Benutzung notwendige Zugri�smodi�kator amermittelt. Die Zuordnung pm, amq wird in AM gespeichert, sofern m noch nichtin AM enthalten ist oder der bisher zugeordnete Zugri�smodi�kator strengerist als am.

Typdeklaration: Enthält der Knoten die Deklaration eines Top-Level- oder Mem-bertyps t, wird die initiale Zuordnung pt, not usedq in AT gespeichert, sofern tnoch nicht in AT enthalten ist.

Methodendeklaration: Enthält der Knoten die Deklaration einer Methode (odereines Konstruktors) m, wird entweder die Zuordnung pm,publicq oderpm, not usedq in AM gespeichert � pm,publicq, wenn die Methode in einemInterface deklariert wird, eine Interface-Methode implementiert oder es sich umeine Main-Methode handelt; pm, not usedq in allen anderen Fällen und sofernm noch nicht in AM enthalten ist.Wirdm in einer Klasse deklariert, wird entlang des Vererbungspfades nach einervon m überschriebenen Methode om gesucht. Ist so eine Methode vorhanden,wird die Zuordnung pm, omq in OM gespeichert.

Sind die ASTs aller Übersetzungseinheiten durchsucht, enthält AT für jeden Typ denminimalen Zugri�smodi�kator. Für Methoden ist der minimale Zugri�smodi�katorentweder der in AM zugeordnete oder der der in OM vermerkten überschriebenenMethode � je nachdem welcher groÿzügiger ist.

6.5 Besonderheiten

Der beschriebene Algorithmus entspricht der grundsätzlichen Vorgehensweise. Opti-mierungsaspekte oder die besonderen Eigenschaften der verwendeten Datenstrukturlassen die Implementation im Detail noch etwas anders aussehen. Beispielsweise wer-den benutzte Typen und Methoden nur dann in den Maps vermerkt, wenn sie selbstaus einem der analysierten Projekte stammen, da nur für diese die minimalen Zu-gri�smodi�katoren bestimmt werden sollen. Auch werden die gefundenen Typ- undMethodendeklarationen entsprechend der in Abb. 3 aufgeführten Hierarchie nebenbeiin einer gesonderten Datenstruktur gesammelt usw.Hinzu kommen die folgenden Fälle, die vom Grundalgorithmus nicht erfasst werdenkönnen. Einige ergänzenden Prüfungen sind daher notwendig.

54

6.5 Besonderheiten

6.5.1 Interface-Methoden

Das im vorangegangen Abschnitt beschriebene Verfahren erfasst nicht den in Kapitel3.2.3 beschriebenen Fall, in dem eine Klasse eine Interface-Methode implementiert,indem es diese von einer anderen Klasse erbt. Da die Klasse, die die entsprechendeMethode deklariert, sich nicht selbst auf dieses Interface beziehen muss, kann bei derVerarbeitung des Knotens dieser Methodendeklaration nicht festgestellt werden, dassdie Methode public sein muss.Daher muss zusätzlich für jede deklarierte Klasse überprüft werden, ob die imple-mentierten Interfaces oder deren Oberinterfaces Methoden enthalten, die die Klasseselbst nicht implementiert. Nach diesen wird dann entlang des Vererbungspfades inden Oberklassen der aktuellen Klasse gesucht, um ihnen entsprechend public zu-zuordnen.

6.5.2 Methodenaufruf ohne Punktnotation

Wie in Kapitel 5.2.2 dargelegt, ist der für die Benutzung einer Methode notwen-dige Zugri�smodi�kator nicht nur vom benutzenden und deklarierenden Typ ab-hängig, sondern auch vom Typ des Ausdrucks, an dem die Methode aufgerufenwird. In den meisten Fällen ist dieser recht einfach zu bestimmen. Die Knoten-klasse org.eclipse.jdt.core.dom.MethodInvocation, die den Aufruf ei-ner Methode repräsentiert, liefert über die Methode getExpression() ein org.eclipse.jdt.core.dom.Expression-Objekt, von demman wiederum den Typdes Ausdrucks erfragen kann.Leider funktioniert dies nur, wenn Methoden über die Punktnotation auch an einemrichtigen Ausdruck aufgerufen werden, wie in �foo.bar();�. Wird eine Metho-de wie in �bar();� hingegen freistehend aufgerufen, liefert MethodInvocation.getExpression() stets null. Hier sind dann weitere Prüfungen notwendig, dennder Typ des �Ausdrucks� könnte in diesem Fall die aufrufenden Klasse selbst, eineumschlieÿende Klasse oder ein statisch importierter Typ sein.

6.5.3 Impliziter Konstruktoraufruf

Es gibt zwei Situationen, in denen ein Konstruktor aufgerufen wird, ohne dass diesim Quelltext notiert ist. Dies ist zum einen der Fall, wenn eine direkte Unterklasseselbst keinen Konstruktor deklariert. Der dann vom Compiler erzeugte Standardkon-struktor (Default constructor) [JLS05, � 8.8.9] ruft immer super() auf, also denparameterlosen Konstruktor der Oberklasse.Der andere Fall ist gegeben, wenn eine direkte Unterklasse zwar einen Konstruktor

55

6 Umsetzung

deklariert, dessen Rumpf aber selbst keinen expliziten Konstruktoraufruf [JLS05, �8.8.7.1] enthält, also weder super(...) noch this(...). Auch hier wird implizitsuper() aufgerufen, und zwar vor Ausführung des eigentlichen Konstruktorcodes.Diese impliziten Aufrufe stellen eine Benutzung des Konstruktors durch die Unter-klasse dar und der Zugri�smodi�kator des Konstruktors muss diese Benutzung erlau-ben. Anderenfalls würde es in beiden Fällen zu einem Übersetzungsfehler kommen.Da diese Benutzung aber nicht im Quelltext notiert ist und der entsprechende ASTsomit keinen Knoten für das implizite super() enthält, sind auch hier gesondertePrüfungen notwendig, um diese Situationen zu erkennen. Daher wird jede Klassen-deklaration dahingehend überprüft, ob sie einen Konstruktor deklariert, und jedeKonstruktordeklaration, ob sie einen expliziten Konstruktoraufruf enthält. Ist einesvon beiden nicht der Fall, wird, sofern die direkte Oberklasse auch zum analysiertenProjekt gehört, in dieser nach dem parameterlosen Konstruktor gesucht, um dessenBenutzung zu vermerken.

6.5.4 Statischer Import

Die Benutzung einiger statisch importierter Elemente, wie beispielsweise Enum-Konstanten, erscheint im AST der benutzenden Klasse nur als Knoten vom Typorg.eclipse.jdt.core.dom.SimpleName. Diese Knotenklasse steht für jeg-liche Art von Bezeichner im Quelltext. Der Zugri� auf ein statisch importiertes Ele-ment ist somit nicht ohne Weiteres von einem beliebigen anderen Bezeichner zuunterscheiden. Möchte man den Zugri� auf so ein Element als Benutzung des dazu-gehörigen Typs vermerken, müsste man daher für jeden SimpleName-Knoten über-prüfen, ob es sich um so ein statisch importiertes Element handelt. Da SimpleNameder wahrscheinlich am häu�gsten auftretende Knotentyp innerhalb eines AST ist,wäre dieser Aufwand nicht angemessen. Daher ist es pragmatischer schon das stati-sche Importieren eines Elements als Benutzung des deklarierenden Typs anzusehen.Ein Beispiel hierzu zeigt Abb. 13.

6.6 Beschränkungen

6.6.1 Java Server Pages

In Java geschriebene Webanwendungen bestehen oft nicht nur aus herkömmlichemQuelltext in Form von Klassen- und Interfacedeklarationen, sondern zum Teil auchaus einer Kombination von HTML und Java, den Java Server Pages (JSP)32. Dochso umfangreich die Möglichkeiten der Eclipse JDT sind, um einfachen Java-Quelltext

32 http://java.sun.com/products/jsp

56

6.6 Beschränkungen

package example;

public enum U {FOO, BAR

}

import static example.U.FOO;

class A {Object foo() {

return FOO;}

}

CompilationUnit

import static example.U.FOO; class A { Object foo(){ return FOO; } }

XXXXXXXXXXXXXXXXXXXX

ffffffffffffffffffff

ImportDeclaration

import static example.U.FOO;

TypeDeclaration

class A { Object foo(){ return FOO; } }

nnnnnnnnnnn

PPPPPPPPPPP

Quali�edName

example.U.FOO

PPPPPPPPPPP

nnnnnnnnnnn

SimpleName

A

MethodDeclaration

Object foo(){ return FOO; }

nnnnnnnnnnn

PPPPPPPPPPP

Quali�edName

example.U

nnnnnnnnnnn

PPPPPPPPPPP

SimpleName

FOO

SimpleType

Object

SimpleName

foo

Block

{ return FOO; }

SimpleName

example

SimpleName

U

SimpleName

Object

ReturnStatement

return FOO;

SimpleName

FOO

Abbildung 13: AST einer Übersetzungseinheit, in der ein statisch importiertes Element benutztwird (untere Hälfte des angegebenen Quelltextes). Die Benutzung von U wird nicht erst beiZugri� auf FOO (unten rechts hervorgehoben), sondern bereits beim Import (oben links)vermerkt.

57

6 Umsetzung

zu analysieren, so beschränkt sind diese, wenn es um das Auslesen von JSP-Codegeht. Eine eigene Lösung für das Auslesen und Analysieren von in JSPs enthaltenemJava-Code zu entwickeln, hätte jedoch den Rahmen dieser Arbeit gesprengt. Access-Analysis kann daher bei der Bestimmung der minimalen Zugri�smodi�katoren keineBenutzungen von Typen und Methoden innerhalb von JSPs berücksichtigen.

Beispiel

<%@ page import="example.U" %><html><body>The answer is: <%= U.number() %></body></html>

Die Benutzung der Klasse example.U und der Methode number() im Quell-text dieser JSP wird bei der Bestimmung der minimalen Zugri�smodi�katorendurch AccessAnalysis nicht berücksichtigt.

6.6.2 Re�ection

Wie in Kapitel 5.6.2 erläutert, können mit Hilfe der Java Re�ection API benutzteTypen und Methoden generell nicht vollständig erfasst werden. Das AccessAnalysis-Plug-In verzichtet daher völlig auf die Analyse von Re�ection. Auch einfache Auf-rufe, in denen das benutzte Element namentlich aufgeführt ist, wie in �Class.forName("example.U")� werden nicht erfasst. Ebenso können Kon�gurations-dateien von Frameworks nicht untersucht werden.

58

7 Erprobung

Um die vorgestellten Metriken zu erproben, habe ich zunächst in zwei Fallstudien rea-le Softwareprojekte exemplarisch mit AccessAnalysis vermessen. Hierzu habe ich zweiSoftwareunternehmen besucht und zusammen mit jeweils einem Entwickler ein Kun-denprojekt analysiert. Später habe ich zusätzlich zwölf Open-Source-Anwendungenuntersucht.

7.1 Fallstudie A

Für die erste Fallstudie habe ich bei einem Softwareunternehmen ein aktuelles Auf-tragsprojekt eines Kunden aus der Telekommunikationsbranche untersucht. An demseit fünf Jahren laufenden, agilen Entwicklungsprojekt sind rund zwölf Entwickler be-teiligt. Das Einsatzgebiet der Anwendung wurde mir mit �Vertrieb von Access- undVoice-Produkten an mittelständische Unternehmen� umschrieben. Da dieser Versuchnoch in einem sehr frühen Stadium meiner Arbeit stattfand, waren die Ergebnissenoch nicht ganz fehlerfrei, lieferten aber einen ersten Eindruck für den Einsatz desAnalysewerkzeugs unter realen Bedingungen. Die Analyse habe ich gemeinsam miteinem der beteiligten Entwickler vor Ort an seinem Arbeitsplatzrechner durchgeführt.Bei Installation und Durchführung traten keine Probleme auf.Die gesamte Software ist in mehrere Subsysteme aufgeteilt, die jeweils ein eigenesEclipse-Projekt bilden. Für die Untersuchung haben wir vier zusammenhängendeProjekte ausgewählt und in einem Durchlauf analysiert. Bei solchen Multiprojekt-Analysen berücksichtigt AccessAnalysis die projektübergreifenden Benutzbeziehun-gen, liefert aber für jedes Teilprojekt einen eigenen IGAT- und IGAM-Wert.Die vier ausgewählten Projekte umfassen insgesamt 269 Pakete mit 3.804 Typen und31.890 Methoden. Darin sind allerdings auch sämtliche Testklassen für das JUnit-

gesamter Quelltext ohne Tests TestanteilTeilprojekt Pakete Typen Methoden Typen Methoden Typen

I 132 2.094 18.202 1.573 13.684 25,9 %II 76 832 7.315 532 4.881 36,1 %III 45 567 3.906 329 2.028 42,0 %IV 16 311 2.467 179 1.617 42,4 %

gesamt 269 3.804 31.890 2.613 22.210 31,3 %

Tabelle 4: Der Quelltextumfang der Fallstudie A mit und ohne Testcode.

59

7 Erprobung

Framework33 enthalten. Eine genauere Aufschlüsselung des Quelltextumfangs zeigtTabelle 4. Da die JUnit-Testklassen sich zwar in einem gesonderten Ordner, aberin der Regel im selben Paket wie die zu testenden Klassen be�nden, entspricht dieAnzahl der Pakete ohne Tests in etwa der mit Tests.Da das Unternehmen um Geheimhaltung gebeten hat, sind das Gesamtsystem unddie einzelnen Subsysteme nicht mit ihren eigentlichen Namen aufgeführt. Stattdessensind die Teilprojekte anhand der Anzahl der enthaltenen Typen vom gröÿten zumkleinsten römisch durchnummeriert.

7.1.1 Ein�uss von Testklassen

Ein wichtiges Ergebnis dieser ersten realen Messung war, dass der groÿe Anteil derTestklassen die Ergebnisse merkbar beein�usst. Testklassen und -methoden für dasJUnit-Test-Framework müssen public deklariert sein, auch wenn sie im eigenenQuelltext an keiner Stelle aufgerufen werden, sondern nur vom JUnit-Framework perRe�ection. Diese Klassen und Methoden beein�ussen das Ergebnis der Analyse, daihre Benutzung von AccessAnalysis nicht erfasst werden kann, und ihre Zugri�smo-di�katoren somit als zu groÿzügig erscheinen.Abb. 14 zeigt die Ergebnisse der einzelnen Teilprojekte und des Gesamtprojekts. DerVergleich der Ergebnisse mit und ohne Testklassen zeigt eine Gesamtabweichung desIGAT-Werts von 20 Prozentpunkten. Die höchste Di�erenz zeigt Teilprojekt IV mit40 Prozentpunkten. Wie Tabelle 4 zeigt, ist hier auch der Testanteil am höchsten.Beim IGAM ist die Gesamtabweichung mit insgesamt neun Prozentpunkten nichtganz so stark.

7.1.2 Verteilung der Zugri�smodi�katoren

Durch die Analyse trat deutlich die Vorherrschaft des public-Modi�kators hervor.Von den insgesamt 2.613 Typen (ohne Tests) sind 2.580 public deklariert. Nuracht Typen sind protected und 19 private. Dies verwundert nicht, da diesebeiden Modi�katoren lediglich bei Memberklassen erlaubt sind. Doch ausgerechnetder default-Modi�kator, der auch bei Top-Level-Typen erlaubt ist, spielt mit sechsDeklarationen die geringste Rolle.Bei solch einer konsequenten Verwendung eines einzigen Modi�kators werden dieErgebnisse der Metriken nicht durch eine unterschiedliche Verwendung der Zugri�s-modikatoren bestimmt, sondern nur durch den Grad der Benutzung der einzelnenElemente. So ist das gute IGAT-Ergebnis des Teilprojekts IV34 nicht darauf zurück-zuführen, dass hier mehr auf die Einschränkung der Zugreifbarkeit geachtet wurde,

33 http://junit.org34 vgl. Abb. 14(a)

60

7.1 Fallstudie A

IGAT (ohne Tests) IGAT (mit Tests)

Teilprojekt I Teilprojekt II Teilprojekt III Teilprojekt IV Gesamt0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,20

0,37

0,58

0,70

0,22

0,49

0,03

0,43

0,27

0,47

(a) IGAT

IGAM (ohne Tests) IGAM (mit Tests)

Teilprojekt I Teilprojekt II Teilprojekt III Teilprojekt IV Gesamt0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,420,49 0,52

0,61

0,33

0,47

0,15

0,43 0,42

0,51

(b) IGAM

Abbildung 14: Ergebnisse der Fallstudie A mit und ohne Tests. Den Werten aller Teilmengenliegt dieselbe Zugri�sanalyse auf Basis des gesamten Quelltextes zugrunde. Die Ergebnissedes Gesamtprojekts und der Teilprojekte ohne Tests wurden nachträglich aus den IGAT- undIGAM-Werte der einzelnen Typen und Methoden berechnet.

61

7 Erprobung

sondern darauf, dass fast alle Typen dieses Subsystems über Paketgrenzen hinwegverwendet werden. Dieses Teilprojekt enthält ausschlieÿlich Fachwert-Klassen ent-prechend dem Werkzeug-Material-Ansatz [Zü98, S. 316�]. Diese sind zum einen fürdie systenweite Verwendung bestimmt, zum anderen ist ihre Implementation rechteinfach, so dass wenige Hilfsklassen benötigt werden, die versteckt werden könnten.

Bei den Methoden ist das Bild ebenfalls sehr deutlich, wenn auch nicht ganz so ex-trem wie bei den Typen. Von insgesamt 22.210 Methoden sind 18.706 public, 1.838protected, lediglich 29 default und 1.641 private. Auch hier scheint der default-Modi�kator für die Entwickler keine Bedeutung zu haben. Dies wird auch an demüberraschend hohen protected-Anteil deutlich, der sogar den von private über-steigt. Der Grund hierfür liegt in der Teststrategie des Entwicklungsteams. Um Me-thoden für die JUnit-Testklassen innerhalb des eigenen Pakets zugreifbar zu machen,wird der Zugri� von private auf protected erhöht. Dass hierfür auch defaultausreicht, war den Entwicklern o�enbar bisher nicht klar. So ist laut Analyse für1.025 der 1.838 protected-Methoden default der minimale Zugri�smodi�kator.

7.1.3 Falsch positive Ergebnisse

Wie Abb. 14 zeigt, haben laut Analyse 27 % der untersuchten Typen und 42 % derMethoden einen zu groÿzügigen Zugri�smodi�kator. Am schlechtesten sind die Wer-te bei Teilprojekt II mit 58 % der Typen und 52 % der Methoden. Diese Zahlensind jedoch mit Vorsicht zu betrachten. Da es sich bei der untersuchten Anwendungum eine Webanwendung handelt, enthält diese neben normalen Java-Klassen und-Interfaces auch JSPs, die von AccessAnalysis nicht analysiert werden können35. Sosind viele Typen und Methoden für den Gebrauch in JSPs bestimmt. Diese Elementekönnen als falsch positive die Metriken verfälschen, wenn sie sonst gar nicht oder nureingeschränkt benutzt werden.Hinzu kommt, dass die Entwickler das Persistenz-Framework Hibernate36 einset-zen. Auch hierfür wurden etliche Klassen geschrieben, die durch das Frameworkper Re�ection aufgerufen werden. Diese Klassen werden zwar in den Hibernate-Kon�gurationsdateien benannt, doch werden auch diese bei der Analyse nicht be-rücksichtigt.Beispielsweise wurden von den insgesamt 22.210 Methoden 5.822 als not used er-kannt, also mehr als ein Viertel. Ob diese Methoden tatsächlich nicht benötigt wer-den, erscheint vor diesem Hintergrund aber fraglich und müsste gegebenfalls genaueruntersucht werden.

35 vgl. Kapitel 6.6.136 http://hibernate.org

62

7.2 Fallstudie B

7.2 Fallstudie B

Für die zweite Fallstudie besuchte ich ein weiteres Softwareunternehmen. Auch hieruntersuchte ich gemeinsam mit einem Entwickler ein aktuelles Kundenprojekt. DerAuftraggeber dieses Projekts ist eine Versicherungsgesellschaft. Die Anwendung dientder Erstellung und Verwaltung von Versicherungsverträgen über eine Webober�äche.Dieses ebenfalls agil durchgeführte Projekt läuft seit etwas mehr als anderthalb Jah-ren und beschäftigt drei bis vier Entwickler. Das entwickelte System ist deutlichkleiner als das der ersten Fallstudie, teilt sich aber in mehr Subsysteme auf. Tabelle5 zeigt, dass der Quelltextumfang sehr ungleichmäÿig auf die insgesamt zwölf Teil-projekte verteilt ist.Trotz des kleineren Projektumfangs war die Durchführung der Analyse hier etwasaufwendiger, da der Quelltext zunächst in eine aktuelle Eclipse-Version importiertwerden musste, weil das Team sonst mit einer anderen Entwicklungsumgebung ar-beitet. Nachdem der Import abgeschlossen und die Übersetzbarkeit hergestellt wur-de, wurden zunächst alle Testklassen entfernt, damit diese das Ergebnis nicht wie inFallstudie A beein�ussen. Da in der Teststrategie dieses Teams nicht vorgesehen ist,Zugreifbarkeiten nur für die Tests zu erhöhen, hatte diese komplette Entfernung derTests keinen Ein�uss auf die Ergebnisse des übrigen Quelltextes.

Teilprojekt Pakete Typen Methoden

I 16 105 1269II 6 40 279III 1 39 492IV 1 35 463V 5 32 289VI 4 29 784VII 2 21 78VIII 2 18 158IX 5 13 234X 1 12 42XI 1 9 55XII 1 2 0

gesamt 45 355 4143

Tabelle 5: Der Quelltextumfang der Fallstudie B ohne Testcode.

63

7 Erprobung

7.2.1 Falsch positive Ergebnisse

Aufrund der geringeren Gröÿe des Projekts war es diesmal möglich, mit dem betei-ligten Entwickler nahezu sämtliche Einzelergebnisse zu besprechen. Dabei konntenvereinzelt auch tatsächlich überhöhte Zugreifbarkeiten entdeckt werden, die der Ent-wickler in einer Refactoringliste notierte. Der gröÿte Anteil der �zu groÿzügigen�Zugri�smodi�katoren stellte sich aber auch hier als falsch positives Ergebnis heraus.Auch hier liegt die Ursache im umfangreichen Einsatz von Frameworks wie Spring37,EJB38 oder Hibernate sowie von JSPs.Deutlich wird diese Problematik beispielsweise an den Ergebnissen der TeilprojekteVII und VIII, siehe Abb. 15. Teilprojekt VII enthält ausschlieÿlich Typbeschreibun-gen in Form von Interfaces. Der IGAT-Wert ist hier besonders gut, da diese Interfa-cetypen gröÿtenteils in anderen Teilen der Software benutzt werden. Der IGAM-Wertsteht bei 0 %, da bei Interfaces die minimalen Zugri�smodi�katoren der Methoden im-mer public sind und somit den tatsächlichen entsprechen. Teilprojekt VIII enthältwiederum die Implementationen dieser Interfaces. Die Objekte dieser implementie-renden Klassen werden aber an keiner Stelle im Quelltext erzeugt, sondern von derDependency-Injection-Komponente des Spring-Frameworks. Daher erscheinen sämt-liche Typen dieses Teilprojekts sowie ihre Konstruktoren im Ergebnis der Analyse alsnot used; der IGAT-Wert steht somit bei 100 %. Der IGAM-Wert sieht deutlich besseraus, da die Methoden der Klassen die Methoden der Interfaces implementieren unddie minimalen Zugri�smodi�katoren dadurch auch hier überwiegend public sind.Nur ein paar von Spring benötigte Setter werden als not used erkannt.

7.2.2 Verteilung der Zugri�smodi�katoren

Der insgesamt starke Einsatz von Interfaces führt dazu, dass die Amplitude derSchwankungen bei der IGAM-Metrik nicht ganz so stark und das Gesamtniveauniedriger ist als beim IGAT, da durch die Verwendung von Interfaces der Einsatzvon public bei Methoden unvermeidlich ist. Dass public auch bei dieser Fallstu-die sowohl bei Methoden als auch bei Typen vorherrschend ist, zeigt die Betrach-tung der Modi�katorverteilung. 345 der 355 Typen sind public deklariert, keinerprotected, zwei default und sieben private. Von den 4.143 Methoden sind 3.742public, 137 protected, eine default und 263 private. Somit scheint auch beidiesem Entwicklungsteam der default-Modi�kator kaum eine Rolle zu spielen.

37 http://www.springsource.org38 http://java.sun.com/products/ejb/

64

7.2 Fallstudie B

I II III IV V VI VII VIII IX X XI XII Gesamt0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,49

0,75

0,08

0,14

0,53

0,41

0,10

1,00

0,46

0,14

0,22

0,00

0,42

(a) IGAT

I II III IV V VI VII VIII IX X XI XII Gesamt0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,45

0,05

0,22

0,30

0,14

0,33

0,00

0,23

0,400,36

0,11

0,00

0,31

(b) IGAM

Abbildung 15: Ergebnisse der Fallstudie B. Den Werten aller Teilmengen liegt dieselbe Zugri�s-analyse auf Basis des gesamten Quelltextes zugrunde.

65

7 Erprobung

7.3 Schlussfolgerungen aus den Fallstudien A und B

Die erste Fallstudie zeigte, dass auch gröÿere Projekte durch AccessAnalysis verar-beitet werden können.Der hohe Anteil an JUnit-Tests machte deutlich, dass diese Klassen bei der Berech-nung der Metriken auÿen vor bleiben müssen. Allerdings hängt es von der Teststra-tegie ab, ob die Benutzungen durch Testklassen berücksichtigt werden sollen. Ist esakzeptiert und erwünscht, dass die Zugreifbarkeit von Methoden erhöht wird, umsie durch Testklassen, die sich in der Regel im selben Paket be�nden, zugreifbar zumachen, sollten diese Test-Benutzungen bei der Bestimmung der minimalen Zugri�s-modi�katoren berücksichtigt werden. Ansonsten kann man sie wie in Fallstudie Bvon der Analyse ganz ausschlieÿen.Der Einsatz von JSPs und Frameworks, die Typen und Methoden per Re�ectionbenutzen, verfälschen stark die Metriken und mindern deren Aussagekraft und Nütz-lichkeit. So lassen sich die Ergebnisse verschiedener Quelltextmengen mit unterschied-lichem Anteil an auf diese Weise benutzten Typen und Methoden nur schwer mitein-ander vergleichen.Die Analyse zeigte aber auch die Dominanz des public-Modi�kators, nicht nurbei den tatsächlichen, sondern auch bei den minimalen Zugri�smodi�katoren. Dengröÿten Anteil der Typen und Methoden, bei denen tatsächlicher und minimaler Zu-gri�smodi�kator übereinstimmen, bilden diejenigen, bei denen beide public sind.So können teilweise recht gute IGAT- und IGAM-Werte entstehen, auch wenn sichdas Entwicklungsteam um die Einschränkung von Zugreifbarkeiten nur wenig be-müht. Der default-Modi�kator scheint kaum im Bewusstsein der Entwickler zu sein,was in Fallstudie A o�enbar auch durch ein mangelhaftes Wissen über die Bedeutungder Modi�katoren begründet ist.

7.4 Fallstudie C

Ergänzend zu den zwei Messungen bei Entwicklern vor Ort habe ich zwölf Open-Source-Systeme auf Java-Basis, deren Quelltext im Internet verfügbar ist, analysiert.Dabei habe ich die Erkenntnisse der ersten Fallstudien in die Auswahl der Systemeein�ieÿen lassen, um möglichst aussagekräftige Ergebnisse zu gewinnen.

7.4.1 Auswahl

Wichtigstes Kriterium bei der Auswahl der Systeme war die Vermeidung falsch po-sitiver Ergebnisse. Daher sollte es sich bei den ausgewählten Programmen um eigen-ständige Anwendungen und nicht um Bibliotheken oder Frameworks handeln. We-banwendungen, die JSPs enthalten, waren ausgeschlossen; ebenso Projekte, in denen

66

7.4 Fallstudie C

Re�ection eine groÿe Rolle spielt � sei es im eigenen Quelltext oder durch eingesetzteFrameworks.Auÿerdem sollte sich die Software bereits in einem fortgeschrittenen Entwicklungs-stadium be�nden, d.h. bereits in einer einsatzfähigen Version erschienen sein. Derverfügbare Quelltext sollte sich zudem ohne Veränderungen in Eclipse importierenlassen und nach Einbindung aller benötigter Bibliotheken frei von Übersetzungsfeh-lern sein.Die Suche nach geeigneten Projekten zeigte, dass es sehr schwierig ist, solche zu �n-den, die alle Kriterien vollständig erfüllen. Die folgenden zwölf ausgewählten Projektetun dies weitestgehend. Einige enthalten allerdings eine API für Erweiterungen, sodass Teile des Quelltextes Bibliothekscharakter haben. Andere implementieren Tasksfür das Build-Tool Apache Ant39, die von diesem per Re�ection aufgerufen werden.Der Anteil dieser Quelltextteile ist aber in allen Fällen so gering, dass die Menge anfalsch positiven Ergebnissen vernachlässigbar ist.

BlueJ Version 3.0.0 (http://bluej.org)Java-Entwicklungsumgebung für den Einsatz in der Lehre.

Cobertura Version 1.9.4.1 (http://cobertura.sourceforge.net)Quelltextanalyse-Werkzeug zur Messung der Testabdeckung von Java-Code.

DoctorJ Version 5.1.2 (http://www.incava.org/projects/java/doctorj)Quelltextanalyse-Werkzeug, das Java-Code mit den enthaltenen Javadoc-Kommentaren vergleicht.

FindBugs Version 1.3.9 (http://�ndbugs.sourceforge.net)Quelltextanalyse-Werkzeug zum Finden von Fehlern in Java-Code.

FreeCol Version 0.9.3 (http://www.freecol.org)Rundenbasiertes Strategiespiel.

FreeMind Version 0.8.1 (http://freemind.sourceforge.net)Illustrationsprogramm zum Erstellen von Mindmaps.

JabRef Version 2.6 (http://jabref.sourceforge.net)Verwaltungsprogramm für Literaturreferenzen.

JDepend Version 2.9 (http://www.clarkware.com/software/JDepend.html)Quelltextanalyse-Werkzeug zur Berechnung von Softwarequalitätsmetriken fürJava-Code.

jrDesktop Version 0.3.1.0 (http://jrdesktop.sourceforge.net)Fernwartungstool zum Darstellen und Steuern von Desktops auf anderen Com-putern.

39 http://ant.apache.org

67

7 Erprobung

PDFsam Version 2.2.0 (http://www.pdfsam.org)Werkzeug zum Aufteilen und Zusammenfügen von PDF-Dokumenten.

PMD Version 4.2.5 (http://pmd.sourceforge.net)Quelltextanalyse-Werkzeug zum Finden von Fehlern in Java-Code.

Sweet Home 3D Version 2.5 (http://www.sweethome3d.com)Illustrationsprogramm zum Planen von Innenraumeinrichtungen.

Die Gröÿen der Projekte reichen ohne Testklassen von 29 Typen bei JDepend biszu 1.319 Typen bei FindBugs. Tabelle 6 zeigt den Quelltextumfang aller Anwendun-gen.

Projekt Pakete Typen Methoden

BlueJ 42 766 6.232Cobertura 19 117 3.309DoctorJ 12 220 3.869FindBugs 53 1.319 9.422FreeCol 34 681 6.020FreeMind 29 790 5.991JabRef 41 794 4.428JDepend 4 29 329jrDesktop 11 75 908PDFsam 84 323 2.441PMD 47 648 4.778Sweet Home 3D 9 392 3.468

Tabelle 6: Der Quelltextumfang der Projekte der Fallstudie C, jeweils ohne Testcode.

7.4.2 Vorgehen

Die ausgewählten Projekte waren mir zum einen bereits vor dieser Arbeit bekannt,zum anderen habe ich auf Internet-Plattformen wie java-source.net odersourceforge.net nach geeigneten Anwendungen gesucht. Nach dem Herunterladen desjeweiligen Quelltextes habe ich diesen als neues Java-Projekt in Eclipse importiert.In einigen Fällen mussten noch weitere externe Bibliotheken eingebunden werden,um alle Abhängigkeiten aufzulösen. Enthielt der Quelltext danach noch Fehler, diedie Übersetzbarkeit verhinderten, habe ich das Projekt ausgeschlossen. Anderenfallshabe ich eine Testmessung vorgenommen, um au�ällige Pakete aufzuspüren, die dasErgebnis verfälschen könnten. So musste ich beispielsweise das Projekt Apache Antausschlieÿen, da sich herausstellte, dass hier der Quelltextanteil der Erweiterungs-API zu einem hohen Aufkommen falsch positiver Ergebnisse geführt hätte.

68

7.4 Fallstudie C

Nach der Zusammenstellung der oben genannten Projekte habe ich bei diesen sämtli-che JUnit-Testklassen entfernt. Diese waren in der Regel daran zu erkennen, dass siesich in Ordnern oder Paketen mit �test� im Namen befanden. Bei einigen Projekte wa-ren die Tests im verö�entlichten Quelltext bereits entfernt. Bei den Anwendungen,deren Funktion selbst die Analyse von Java-Quelltext beinhaltet, war häu�g auchBeispielcode in Ordnern wie �example�, �sample� oder �testcases� enthalten. DiesePakete habe ich ebenfalls entfernt.Schlieÿlich habe ich der Reihe nach für jedes Projekt noch einmal die Analyse durch-geführt.

7.4.3 Ergebnisse

Ein Blick auf die Ergebnisse in Abb. 16 zeigt, dass auch bei den vermessenen Open-Source-Projekten ein nicht unerheblicher Teil der Zugri�smodi�katoren zu groÿzügigist. Der Anteil der Methoden mit zu groÿzügigem Zugri�smodi�kator bewegt sichdabei relativ eng in einem Bereich von 25 bis 44 %. Nur das Projekt DoctorJ liegtmit einem IGAM-Wert von 71 % deutlich auÿerhalb dieses Bereichs. Die IGAT-Wertezeigen eine deutlich stärkere Schwankung und insgesamt höhere Werte. Das au�äl-ligste Ergebnis hat hier PDFsam, bei dem nur 16 % der Typen einen zu groÿzügigenZugri�smodi�kator haben.

PDFsam schneidet auch bei den Methoden vergleichsweise gut ab. Betrachtet mandas Projekt jedoch näher, zeigt sich, dass diese guten Ergebnisse ihre Ursache wenigerin einer hohen Kapselung haben, als vielmehr im hohen Anteil von public unterden minimalen Zugri�smodi�katoren. Aufgrund einer sehr ausgeprägten Aufteilungdes Quelltextes in Pakete40 gibt es im PDFsam-Code kaum Möglichkeiten, Zugreif-barkeiten einzuschränken, somit auch wenig Gelegenheiten, Zugri�smodi�katoren zugroÿzügig anzugeben. So ist hier der Anteil von public an den tatsächlichen Zu-gri�smodi�katoren mit 96 % bei den Typen und 88 % bei den Methoden sogar höherals der bei den Typen und Methoden aller Projekte41. Allerdings übersteigt dieserauch bei den minimalen Zugri�smodi�katoren mit 81 % bei den Typen und 64 % beiden Methoden deutlich den Durchschnitt42.

Anders sieht es bei JDepend aus. 27 der insgesamt 29 Typen teilen sich hier auf nurzwei Pakete auf. Entsprechend hoch ist der Anteil der Typen und Methoden, die nurpaketintern verwendet werden. Der public-Anteil bei den minimalen Zugri�smo-di�katoren ist daher mit 28 % (Typen) und 19 % (Methoden) sehr niedrig. Da dertatsächliche Einsatz von public aber deutlich höher ist, fallen hier die IGAT- undIGAM-Werte entsprechend schlecht aus.

40 Mit durchschnittlich 3,85 enthaltenen Typen hat PDFsam die kleinsten Pakete aller Projekte.41 vgl. Abb. 17(a) und 17(g)42 vgl. Abb. 17(b) und 17(h)

69

7 Erprobung

Blue

J (4

2)Co

bert

ura

(19)

Doct

orJ

(12)

FindB

ugs

(53)

Free

Col (

34)

Free

Min

d (2

9)Ja

bRef

(41

)JD

epen

d (4

)jrD

eskt

op (

11)

PDFs

am (

84)

PMD

(47)

Swee

t Ho

me

3D (

9)

0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,39

0,52

0,28

0,51

0,320,35

0,59 0,59

0,25

0,16

0,46

0,21

(a) IGAT

Blue

J (4

2)Co

bert

ura

(19)

Doct

orJ

(12)

FindB

ugs

(53)

Free

Col (

34)

Free

Min

d (2

9)Ja

bRef

(41

)JD

epen

d (4

)jrD

eskt

op (

11)

PDFs

am (

84)

PMD

(47)

Swee

t Ho

me

3D (

9)

0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,370,31

0,71

0,380,35

0,25

0,44 0,430,40

0,260,31 0,30

(b) IGAM

Abbildung 16: Ergebnisse der Fallstudie C. In Klammern ist jeweils die Anzahl der Paketeangegeben.

70

7.4 Fallstudie C

Das zweitbeste IGAT-Ergebnis hat Sweet Home 3D. Schaut man hier nach den Ur-sachen, stellt man fest, dass die Entwicklerinnen und Entwickler hier ungewöhnlichhäu�g Membertypen einsetzen. Deren Anzahl übersteigt mit 223 sogar die der Top-Level-Typen (169). Wie Abb. 17(e) zeigt, scheint in allen Projekten der Einsatz vonstrengeren Zugri�smodi�katoren als public bei Membertypen höher zu sein alsbei Top-Level-Typen oder Methoden. So sind auch bei Sweet Home 3D 148 Typenprivate deklariert, was sich positiv auf den IGAT-Wert niederschlägt.

DoctorJ fällt nicht nur durch einen ungewöhnlich hohen IGAM-Wert, sondern auchdurch ein dagegen vergleichsweise gutes IGAT-Ergebnis auf. Betrachtet man das Pro-jekt genauer, zeigt sich, dass auch bei DoctorJ der gute IGAT-Wert nicht durch einehohe Einschränkung von Zugreifbarkeiten entsteht. So sind mit 215 von 220 fast alleTypen public, jedoch entspricht dies bei 156 auch dem minimalen Zugri�smodi�-kator.Bei den Methoden hingegen zeigt sich, dass hier o�enbar etliche vorhanden sind, diegar nicht benutzt werden. So ist bei mehr als der Hälfte der Methoden, nämlich bei2.147 von insgesamt 3.869 der minimale Zugri�smodi�kator not used. Sieht man sichden Quelltext von DoctorJ an, sieht es so aus, als sei hier der Code externer Bi-bliotheken per Copy & Paste eingefügt worden, anstatt eine kompilierte Version zuverlinken. Von diesen fremden Typen wird jedoch nur ein Bruchteil der angebotenenOperationen benötigt. Hinzu kommt, dass im eigenen Quelltext sämtliche Metho-den entweder public oder protected sind. Auf default und private wird hiergänzlich verzichtet.

7.4.4 Verteilung der Zugri�smodi�katoren

Abb. 17 zeigt deutlich, dass auch bei den hier untersuchten Open-Source-Projektenpublic der mit Abstand am häu�gsten verwendete Zugri�smodi�kator ist. Bei denTop-Level-Typen kommt er fast ausschlieÿlich zum Einsatz. Bei den Membertypenund Methoden ist private durchaus gebräuchlich, allerdings viel seltener als es lautder Ermittlung der minimalen Zugri�smodi�katoren sein könnte.Der default-Modi�kator wird auch hier sowohl bei Top-Level-Typen als auch Metho-den äuÿerst selten verwendet. Nur bei den Membertypen hat default einen relevantenAnteil. Allerdings könnten von den 452 default-Membertypen 422 private sein, 21werden gar nicht benutzt. Dagegen sind von den 132 Membertypen, deren minimalerZugri�smodi�kator default ist, 117 public und 6 protected deklariert. Ähnlicheslässt sich bei den Methoden feststellen. Hier ist in 7.325 Fällen default der minimaleZugri�smodi�kator, allerdings nur 1.084 mal der tatsächliche, wobei dies in 517 Fäl-len sogar zu groÿzügig ist. Der default-Modi�kator kommt somit � wenn überhaupt� oft nur dann zum Einsatz, wenn er nicht mal nötig ist.

71

7 Erprobung

public: 4.966 (81%)

private: 592

(10%)

default: 556 (9%)

protected: 40 (1%)

(a) Alle Typen: tatsächlich

public: 2.926 (48%)

protected: 7 (0%)

not used: 579 (9%)

private: 1.251 (20%)

default: 1.391 (23%)

(b) Alle Typen: minimal

public: 4.466 (98%)

default: 104 (2%)

(c) Nur Top-Level-Typen: tatsächlich

public: 2.770 (61%)

not used: 541

(12%)

default: 1.259 (28%)

(d) Nur Top-Level-Typen: minimal

public: 500

(32%)

protected: 40 (3%)

default: 452

(29%)

private: 592

(37%)

(e) Nur Membertypen: tatsächlich

public: 156

(10%)

protected: 7 (0%)

default: 132 (8%)

not used: 38 (2%)

private: 1.251 (79%)

(f) Nur Membertypen: minimal

public: 39.060 (76%)

private: 8.704 (17%)

default: 1.084 (2%)

protected: 2.347 (5%)

(g) Methoden: tatsächlich

public: 22.751 (44%)

protected: 1.646 (3%)

not used: 6.035 (12%)

private: 13.438 (26%)

default: 7.325 (14%)

(h) Methoden: minimal

Abbildung 17: Verteilung der Zugri�smodi�katoren in den Projekten der Fallstudie C.

72

7.5 Alternative Berechnung der Metriken

7.5 Alternative Berechnung der Metriken

Paketübergreifende Benutztbeziehungen sind in Java nicht ungewöhnlich. Abb. 17zeigt, dass wie schon in den Fallstudien A und B auch bei den Projekten der Fallstu-die C public daher nicht nur bei den tatsächlichen, sondern auch bei den minimalenZugri�smodi�katoren stark vertreten ist. Bei 47 % der Typen und 44 % der Methodenblieb den Entwicklerinnen und Entwicklern keine andere Wahl, als die Zugreifbarkeitauf public einzustellen. Da man bei diesen Typen und Methoden also nichts �falsch�machen kann, bildet der Anteil der restlichen Typen und Methoden die Obergrenzefür die IGAT- und IGAM-Metriken. Im Schnitt kann der IGAT daher nicht über 53% und der IGAM nicht über 56 % liegen. Weiterhin stellt man fest, dass zumindestbeim IGAT der public-Anteil unter den minimalen Zugri�smodi�katoren den ent-scheidenden Ein�uss auf das Ergebnis der Metrik hat. In Abb. 18 sieht man, dass �blendet man die Projekte Sweet Home 3D und jrDesktop aus � der public-Anteilunter den minimalen Zugri�smodi�katoren der Typen und die IGAT-Metrik nahezuproportional gegeneinander verlaufen.

IGAT public-Anteil

PDFs

amSw

eet

Hom

e 3D

jrDes

ktop

Doct

orJ

Free

Col

Free

Min

d

Blue

J

PMD

FindB

ugs

Cobe

rtur

a

JabR

ef

JDep

end

0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

Abbildung 18: Vergleich von IGAT und des Anteils von public unter den minimalen Zugri�s-modi�katoren der Typen in den Projekten der Fallstudie C.

Somit liefert das Betrachten der Metriken IGAT und IGAM möglicherweise keinausreichendes Bild, möchte man gerade die Sorgfalt der Entwicklerinnen und Ent-wickler bei der Wahl der Zugri�smodi�katoren untersuchen. Eine Alternative wäre

73

7 Erprobung

bei der Berechnung der Metriken diejenigen Typen und Methoden herauszulassen,deren minimaler Zugri�smodi�kator ohnehin public ist. Das Ergebnis wäre dannnicht mehr der Anteil der Typen/Methoden mit zu groÿzügigem Zugri�smodi�katoran der Gesamtmenge der Typen/Methoden, sondern der Anteil der Typen/Methodenmit zu groÿzügigem Zugri�smodi�kator an denjenigen Typen/Methoden, bei denenüberhaupt eine Einschränkung der Zugreifbarbarkeit möglich wäre. Ich nenne dieseVarianten der Metriken hier IGAT2 und IGAM2; die formalen De�nitionen �ndensich in Anhang D.Abb. 19 zeigt einen Vergleich der Metrikvarianten für die Projekte der Fallstudie C.Teilweise weichen die Ergebnisse deutlich voneinander ab. So schneidet beispielswei-se PDFsam, das nach der ursprünglichen Berechnung das beste Ergebnis hat, beiden alternativen Metriken äuÿerst schlecht ab; Sweet Home 3D erreicht allerdingsauch hier vergleichsweise gute Werte � ein Ergebnis, das schon die Betrachtungen inAbschnitt 7.4.3 nahe legen.

Die Werte der Metriken IGAT2 und IGAM2 zeigen aber auch, dass in den meistenProjekten die Entwicklerinnen und Entwickler in der überwiegenden Zahl der Fäl-le, in denen sie die Zugreifbarkeit ihrer Typen und Methoden hätten einschränkenkönnen, dies nicht oder nicht ausreichend getan haben. Die alternative Berechnungweist daher deutlicher als die ursprünglichen Metriken auf Mängel im Umgang mitden Zugri�smodi�katoren hin.Der Nachteil dieser Varianten ist jedoch, dass sie möglicherweise schwieriger zu ver-stehen und nachzuvollziehen sind als IGAT und IGAM. Die einfache Aussage �x %der Zugri�smodi�katoren ist groÿzügiger als notwendig� ist für eine Entwicklerin odereinen Entwickler eventuell nützlicher als die Aussage �y % Prozent der Typen/Metho-den, deren Zugreifbarkeiten eingeschränkt werden kann, haben einen zu groÿzügigenZugri�smodi�kator�. Im zweiten Fall ist die Bezugsgröÿe nicht unmittelbar erkenn-bar; im ersten ergibt sie sich einfach aus der Gröÿe des Projekts bzw. der Gröÿe desbetrachteten Quelltextausschnitts.

7.6 Analysegeschwindigkeit

Die Bestimmung der minimalen Zugri�smodi�katoren ist recht aufwendig. Für je-de Übersetzungseinheit muss ein AST erzeugt werden und die Bindungen zu denbenutzten Elementen aufgelöst werden. Die Maps müssen verwaltet werden und anjedem AST-Knoten verschiedene Prüfungen durchgeführt werden; beispielweise mussfür jede deklarierte Methode entlang des Vererbungspfades und in allen implemen-tierten Interfaces nach einer ggf. überschriebenen Methode gesucht werden.Die Fallstudien haben jedoch gezeigt, dass sich die Zugri�sanalyse zumindest fürProjekte in diesen Gröÿenordnungen in durchaus akzeptabler Zeit durchführen lässt.

74

7.6 Analysegeschwindigkeit

IGAT IGAT2Bl

ueJ

Cobe

rtur

a

Doct

orJ

FindB

ugs

Free

Col

Free

Min

d

JabR

ef

JDep

end

jrDes

ktop

PDFs

am PMD

Swee

t Ho

me

3D

0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,39

0,74

0,52

0,82

0,28

0,95

0,51

0,84

0,32

0,79

0,35

0,72

0,59

0,89

0,59

0,81

0,25

0,50

0,16

0,85

0,46

0,85

0,21

0,36

(a) IGAT und IGAT2

IGAM IGAM2

Blue

J

Cobe

rtur

a

Doct

orJ

FindB

ugs

Free

Col

Free

Min

d

JabR

ef

JDep

end

jrDes

ktop

PDFs

am PMD

Swee

t Ho

me

3D

0

0,1

0,2

0,3

0,4

0,5

0,6

0,7

0,8

0,9

1

0,37

0,68

0,310,34

0,71

0,85

0,38

0,71

0,35

0,69

0,25

0,73

0,44

0,81

0,43

0,53

0,40

0,60

0,26

0,74

0,31

0,56

0,30

0,54

(b) IGAM und IGAM2

Abbildung 19: Vergleich der Metrikvarianten für die Projekte der Fallstudie C.

75

7 Erprobung

So dauerte die Berechnung der Metriken43 für das kleinste Projekt der Fallstudie CJDepend nur etwas mehr als zwei Sekunden. Für das gröÿte Projekt FindBugs warenrund 70 Sekunden nötig. Abb. 20 zeigt jedoch, dass nicht nur die Gröÿe des Projektsentscheidend für die Dauer der Analyse ist. So hat o�enbar auch die durchschnittlicheVererbungstiefe einen gewissen Ein�uss.

Analysedauer (Sekunden) NCLOC DIT

JDep

end

jrDes

ktop

PDFs

am

Doct

orJ

PMD

Cobe

rtur

aSw

eet

Hom

e 3D

JabR

efFr

eeM

ind

Blue

JFr

eeCo

lFin

dBug

s

0

10

20

30

40

50

60

70

An

alys

edau

er (

Sek

un

den

)

0

10.000

20.000

30.000

40.000

50.000

60.000

70.000

80.000

90.000

100.000

110.000

NC

LOC

0,00

0,25

0,50

0,75

1,00

1,25

1,50

1,75

2,00

2,25

2,50

2,75

3,00

3,25

DIT

Abbildung 20: Vergleich der Analysedauer mit der Länge des Quelltextes (NCLOC44) und derdurchschnittlichen Vererbungstiefe (DIT45).

43 durchgeführt auf einem Laptop aus dem Jahre 2007, CPU: Intel Celeron M (1,7 GHz), 2 GBRAM, Betriebssystem: Kubuntu 8.04, Eclipse 3.5

44 Non-Commented Lines of Codes, vgl. Kapitel 4.5.145 Depth of Inheritance Tree: Durchschnittliche Entfernung der Klassen von der Object-Klasse in

der Vererbungshierarchie

76

8 Fazit

Ziel dieser Arbeit war es, ein Verfahren zu entwickeln, einen Aspekt der Kapselunginnerhalb von Java-Systemen, nämlich die angemessene Verwendung von Zugri�smo-di�katoren, quantitativ zu bewerten. Abschlieÿend folgt nun eine Zusammenfassungdes Geleisteten sowie ein Ausblick auf noch ausstehende Arbeiten.

8.1 Zusammenfassung

Anhand von Beispielen aus Praxis und Ausbildung wurde die softwaretechnischeProblematik zu groÿzügiger Zugreifbarkeit von Typen und Methoden dargestellt.Dabei wurde die These entwickelt, dass besonders die Möglichkeit, in Java einen Typoder eine Methode innerhalb eines Pakets zu kapseln, also die default-Zugreifbarkeitzu wählen, oft nicht genutzt wird.

Daraufhin wurde das Konzept des minimalen Zugri�smodi�kators eingeführt. Die-ses beruht auf der Annahme, dass die tatsächliche Benutzung eines Elements inner-halb des Quelltextes eines Java-Programms dessen Zugreifbarkeit bestimmen sollte.Der minimale Zugri�smodi�kator eines Typs oder einer Methode ist der strengsteZugri�smodi�kator, der ausreicht, um alle Benutzungen im gesamten System zu ge-währleisten. Dieser minimale Zugri�smodi�kator ist nicht in allen Fällen die richtigeWahl. So kann es Gründe geben, die dazu führen, dass einem Element eine höhereZugreifbarkeit zuzuordnen ist. Auch ist es möglich, dass bestehende Benutzungendie aus softwaretechnischer Sicht angemessene Zugri�sebene eines Elements bereitsüberschreiten. Annäherungsweise kann der minimale Zugri�smodi�kator jedoch alsMaÿstab für die �richtige� Zugreifbarkeit dienen.Auf Grundlage dieses Konzepts wurden die Softwaremetriken Inappropriate Genero-sity with Accessibility of Types (IGAT) und Inappropriate Generosity with Accessi-bility of Methods (IGAM) de�niert, die den Anteil derjenigen Typen bzw. Methodenangeben, deren tatsächlicher Zugri�modi�kator groÿzügiger ist als der minimale.

Die Bestimmung der minimalen Zugri�smodi�katoren und die Berechnung der Me-triken wurde prototypisch durch die Entwicklung des Eclipse-Plug-Ins AccessAna-lysis realisiert. Damit wurde demonstriert, dass bei genauer Beachtung der Java-Sprachde�nition für jeden Typ und jede Methode ein minimaler Zugri�smodi�katorbestimmt werden kann, solange diese ausschlieÿlich im zur Analyse vorliegenden Java-Quelltext benutzt werden.Jedoch zeigte sich im Rahmen der praktischen Erprobung bei zwei Softwareunterneh-men, dass heutige Softwaresysteme aus einer heterogenen Landschaft verschiedenerTechnologien und Frameworks bestehen, so dass eine ausschlieÿliche Analyse von

77

8 Fazit

Java-Quelltext nicht ausreicht, um die minimalen Zugri�smodi�katoren aller Ele-mente zu bestimmen.

An einer Auswahl von zwölf Open-Source-Projekten, bei denen aufgrund ihrer Struk-tur falsch positive Ergebnisse weitestgehend vermieden werden konnten, konnten dieMetriken dennoch erprobt werden und lieferten brauchbare Ergebnisse. Diese zeig-ten, dass tatsächlich ein groÿer Teil der Typen und Methoden dieser Projekte übergroÿzügigere Zugri�smodi�katoren verfügt als eigentlich notwendig.Allerdings wurde auch deutlich, dass die Metriken nicht unbedingt den tatsächlichenUmgang der Entwicklerinnen und Entwickler mit Zugri�smodi�katoren widerspie-geln. Das Problem liegt dabei in der �achen Paketstruktur von Java-Systemen. Wer-den zusammengehörige Typen zur Quelltextstrukturierung in mehrere Pakete aufge-teilt, müssen, sofern gegenseitige Abhängigkeiten bestehen, etliche Elemente publicdeklariert werden. Dadurch ist in vielen Systemen der Anteil der Typen und Metho-den sehr hoch, deren minimaler Zugri�smodi�kator public ist. So können trotzmangelhaften Umgangs mit den restlichen Zugri�smodi�katoren gute Ergebnisse beiIGAT und IGAM erzielt werden.Um diesen E�ekt zu elimieren, wurde eine alternative Berechnung der Metriken zurDiskussion gestellt. Dieser liegt nicht mehr die Gesamtzahl an Typen bzw. Metho-den zu Grunde, sondern nur noch die Anzahl derjenigen, bei denen überhaupt ei-ne Einschränkung der Zugreifbarkeit möglich ist, also all diejenigen, deren minima-ler Zugri�smodi�kator strenger ist als public. Die Vermessung der ausgewähltenOpen-Source-Projekte nach dieser Variante zeigte noch deutlicher, wie selten von derMöglichkeit Gebrauch gemacht wird, Zugreifbarkeiten einzuschränken.

Sowohl bei den beiden kommerziellen als auch bei den Open-Source-Projekten be-stätigten die Untersuchungen die These, dass die Beschränkung der Zugreifbarkeitauf Paketebene nur sehr selten eingesetzt wird. Insbesondere Top-Level-Typen wer-den wie vermutet fast immer public deklariert. Wenn auch die zugrundeliegendeStichprobenmenge zu klein ist, um eine allgemeine Aussage zu tre�en, konnte ge-zeigt werden, dass sich die Vernachlässigung des default-�Modi�kators� in der Praxistatsächlich beobachten lässt.

8.2 Ausblick

Sowohl die interne als auch die externe Validierung der Metriken IGAT und IGAMkonnten in dieser Arbeit nur ansatzweise vorgenommen werden. Um eine vollstän-dige interne Validierung zu ermöglichen, wäre es notwendig das dahinterstehendetheoretische Modell, das in dieser Arbeit eher informell aufgebaut wurde, stärker zuformalisieren.Eine umfassendere externe Validierung bedarf einer empirischen Untersuchung, ob

78

8.2 Ausblick

die Metriken tatsächlich im Zusammenhang mit Qualitätsmerkmalen wie Verständ-lichkeit, Änderbarkeit, Erweiterbarkeit oder Testbarkeit stehen. Derartige Nachweisesind allerdings sehr schwer zu führen, da diese Eigenschaften von vielen verschiede-nen Faktoren abhängen.Darüberhinaus wäre es interessant, die Nützlichkeit beider Berechnungsvarianten imPraxiseinsatz zu vergleichen.

Um das Eclipse-Plug-In AccessAnalysis in realen Projekten einsetzen zu können, wärein jedem Fall eine Erweiterungsschnittstelle (Extension point) nötig, um die Analy-se, die bisher auf Java-Quelltext beschränkt ist, auf weitere Dokumente ausweiten zukönnen, z.B. auf JSPs oder Kon�gurationsdateien verschiedener Frameworks. Eben-falls nützlich wäre es, Sonderfälle de�nieren zu können, beispielsweise für Typen oderMethoden, die mit einer bestimmten Annotation, wie z.B. �@Test�, versehen sind.

Eine Übertragung der hier vorgestellten Konzepte auf andere objektorientierte Pro-grammiersprachen wäre wünschenswert, ist aber nur unter bestimmten Voraussetzun-gen möglich. Das Prinzip des minimalen Zugri�smodi�kators basiert auf der klarenhierarchischen Gliederung der Zugri�sebenen in Java und der sich daraus ergebendenOrdnung der Zugri�smodi�katoren. Solch eine Ordnung lässt sich nicht in allen ob-jektorientierten Sprachen ableiten. So gibt es beispielsweise in C# die orthogonalenZugri�sebenen internal und protected. internal erlaubt den Zugri� inner-halb der gleichen Assembly46 und protected durch alle Unterklassen [ECM06,� 10.5]. Es bedürfte somit einer geeigneten Konvention, ob für Elemente, die nurdurch Unterklassen innerhalb der gleichen Assembly benutzt werden, internaloder protected als minimaler Zugri�smodi�kator gilt.Neben der de�nierbaren Ordnung der Zugri�smodi�katoren muss die betre�endeSprache über eine Typsystem verfügen, das die vollständige statische Analyse derBenutztbeziehungen zulässt. Sind diese Anforderungen erfüllt, dürfte die Implemen-tation eines ähnlichen Verfahrens möglich sein.

46 In C# ist eine �Assembly� das Ergebnis eines Übersetzungsvorgangs [ECM06, � 4], z.B. einProgramm oder eine Bibliothek, vergleichbar mit einer JAR-Datei in Java.

79

A Zugri�smodi�kator-Regeln ausgewählter Quelltextanalyse-Werkzeuge

A Zugri�smodi�kator-Regeln ausgewählter

Quelltextanalyse-Werkzeuge

A.1 PMD

vgl. [PMD09]

A.1.1 Code Size Rules

ExcessivePublicCount A large number of public methods and attributes declaredin a class can indicate the class may need to be broken up as increased e�ort will berequired to thoroughly test it.

A.1.2 Controversial Rules

UnusedModi�er Fields in interfaces are automatically public static �nal, andmethods are public abstract. Classes or interfaces nested in an interface are automa-tically public and static (all nested interfaces are automatically static). For historicalreasons, modi�ers which are implied by the context are accepted by the compiler,but are super�uous.

DefaultPackage Use explicit scoping instead of the default package private le-vel.

AvoidAccessibilityAlteration Methods such as getDeclaredConstructors(), get-DeclaredConstructor(Class[]) and setAccessible(), as the interface PrivilegedAction,allow to alter, at runtime, the visilibilty of variable, classes, or methods, even if theyare private. Obviously, no one should do so, as such behavior is against everythingencapsulation principal stands for.

A.1.3 Design Rules

AvoidProtectedFieldInFinalClass Do not use protected �elds in �nal classessince they cannot be subclassed. Clarify your intent by using private or packageaccess modi�ers instead.

80

A.2 FindBugs

A.1.4 Finalizer Rules

FinalizeShouldBeProtected If you override �nalize(), make it protected. If youmake it public, other classes may call it.

A.1.5 Unused Code Rules

UnusedPrivateField Detects when a private �eld is declared and/or assigned avalue, but not used.

UnusedPrivateMethod Unused Private Method detects when a private methodis declared but is unused.

A.2 FindBugs

vgl. [FB09]

A.2.1 Correctness

Se: Method must be private in order for serialization to work This classimplements the Serializable interface, and de�nes a method for custom serialization/-deserialization. But since that method isn't declared private, it will be silently ignoredby the serialization/deserialization API.

A.2.2 Malicious code vulnerability

FI: Finalizer should be protected, not public A class's �nalize() methodshould have protected access, not public.

MS: Field should be both �nal and package protected A mutable static �eldcould be changed by malicious code or by accident from another package. The �eldcould be made package protected and/or made �nal to avoid this vulnerability.

MS: Field should be package protected Amutable static �eld could be changedby malicious code or by accident. The �eld could be made package protected to avoidthis vulnerability.

81

A Zugri�smodi�kator-Regeln ausgewählter Quelltextanalyse-Werkzeuge

A.2.3 Performance

UPM: Private method is never called This private method is never called.Although it is possible that the method will be invoked through re�ection, it is morelikely that the method is never used, and should be removed.

A.2.4 Dodgy

CI: Class is �nal but declares protected �eld This class is declared to be�nal, but declares �elds to be protected. Since the class is �nal, it can not be derivedfrom, and the use of protected is confusing. The access modi�er for the �eld shouldbe changed to private or public to represent the true use for the �eld.

82

B Benutztbeziehungen in Java

B.1 Typen

Im Folgenden sind die Benutzungsbeziehungen von Typen in Java aufgeführt. In denmeisten Beispielen könnte statt des einfachen Typs U ebenso ein Array U[] ste-hen. Die Benutztbeziehungen sind aufgeteilt in explizite Benutzungen, bei denen derbenutzte Typ namentlich im Quelltext vorkommt, und impliziten Benutzungen, beidenen der benutzte Typ der Typ eines auszuwertenden Ausdrucks ist, beispielsweiseder Rückgabetyp einer Methode.

B.1.1 Explizite Benutzungen

Vererbung [JLS05, � 8.1.4]

class A extends U {...

}

Die Klasse A benutzt die Klasse U, indem sie sie beerbt.

Erweiterung [JLS05, � 9.1.3]

interface A extends U {...

}

Das Interface A benutzt das Interface U, indem es es erweitert.

Implementation [JLS05, � 8.1.5]

class A implements U {...

}

Die Klasse A benutzt das Interface U, indem sie es implementiert.

83

B Benutztbeziehungen in Java

Exemplarerzeugung [JLS05, � 15.9]

class A {Object m() {

return new U();}

}

Die Klasse A benutzt die Klasse U, indem sie in der Methode m() ein Exemplar vonihr erzeugt.

Felddeklaration [JLS05, � 8.3, � 9.3]

class A {private U u;

}

Die Klasse A benutzt den Typ U, indem sie ein Feld dieses Typs deklariert.

Lokale Variablendeklaration [JLS05, � 14.4]

class A {void m() {

U u;...

}}

Die Klasse A benutzt den Typ U, indem sie in der Methode m() eine lokale Variabledieses Typs deklariert.

Methodenparameter [JLS05, � 8.4.1]

class A {void m(U u) {

...}

}

Die Klasse A benutzt den Typ U, indem sie eine Methode m() mit einem Parameterdiesen Typs deklariert.

84

B.1 Typen

Rückgabetyp [JLS05, � 8.4.5]

class A {U m() {

...}

}

Die Klasse A benutzt den Typ U, indem sie eine Methode m() mit Rückgabetyp Udeklariert.

throws-Klausel [JLS05, � 8.4.6]

class A {void m() throws U {

...}

}

Die Klasse A benutzt den Throwable-Untertyp U, indem sie eine Methode m()deklariert, die zur Ausnahmebehandlung ein U-Objekt wirft.

Statischer Methodenaufruf [JLS05, � 15.12]

class U {static void foo() {

...}

}

class A {void m() {

U.foo();}

}

Die Klasse A benutzt die Klasse U, indem sie die statische Methode foo() an dieserKlasse aufruft.

85

B Benutztbeziehungen in Java

Statischer Feldzugri� [JLS05, � 15.11]

class U {static final int foo = 42;

}

class A {void m() {

int ufo = U.foo;...

}}

Die Klasse A benutzt die Klasse U, indem sie auf das statische Feld foo dieser Klassezugreift.

enum U {EINS, ZWEI, DREI

}

class A {Object m() {

return U.EINS;}

}

Die Klasse A benutzt den Enum-Typen U, indem sie auf eine entsprechende Enum-konstante zugreift.

Statischer Zugri� auf Membertyp [JLS05, � 6.5.5.2]

class U {static class Foo {

static final int bar = 42;}

}

class A {void m() {

int ufo = U.Foo.bar;...

}}

Die Klasse A benutzt die Klasse U, indem sie auf die statische Memberklasse Foo ausdieser Klasse zugreift.

86

B.1 Typen

Grenze für formalen Typparameter [JLS05, � 4.4]

class A<T extends U> {...

}

Die Klasse A benutzt den Typ U, indem sie ihn als Grenze für einen Typparameterangibt.

Aktueller Typparameter [JLS05, � 4.5]

class A {private List<U> uList;

}

Die Klasse A benutzt den Typ U, indem sie ihn als Argument für einen Typparameterverwendet.

Grenze für Wildcard [JLS05, � 4.5.1]

class A {void m(List<? super U> list) {

...}

}

Die Klasse A benutzt den Typ U, indem sie ihn als untere Grenze für einen Wild-cardtypen angibt.

class A {void m(List<? extends U> list) {

...}

}

Die Klasse A benutzt den Typ U, indem sie ihn als obere Grenze für einen Wildcard-typen angibt.

87

B Benutztbeziehungen in Java

Typvergleich [JLS05, � 8.4.6]

class A {boolean m(Object o) {

return o instanceof U;}

}

Die Klasse A benutzt den Typ U, indem sie ihn für einen Typvergleich verwendet.

Expliziter Cast [JLS05, � 15.16]

class X {static void foo(U u) {

...}

}

class A {void m(Object o) {

X.foo((U) o);}

}

Die Klasse A benutzt den Typ U, indem sie einen Ausdruck nach U castet.

Typliteral [JLS05, � 15.8.2]

class A {Class m() {

return U.class;}

}

Die Klasse A benutzt den Typ U, indem sie an ihm .class aufruft.

Annotation [JLS05, � 9.7]

class A {@Uvoid m() {

...}

}

Die Klasse A benutzt den Annotationstyp U, indem sie eine Methode damit anno-tiert.

88

B.1 Typen

Annotationelement [JLS05, � 9.6]

@interface A {U u();

}

Der Annotationstyp A benutzt den Annotationstyp U, indem sie ein Element vomTyp U deklariert.

Statischer Import [JLS05, � 7.5.3, 7.5.4]

package p;

public class U {...

}

import static p.U.*;

class A {...

}

Die Klasse A benutzt die Klasse U, indem sie Member von ihr statisch importiert.

B.1.2 Implizite Benutzungen

Methodenaufruf [JLS05, � 15.12]

class U {void foo() {

...}

}

class X {U bar() {

return new U();}

}

class A {void m(X x) {

x.bar().foo();}

}

Die Klasse A benutzt die Klasse U, indem sie eine Methode an einem Methoden-Rückgabewert vom Typ U aufruft.

89

B Benutztbeziehungen in Java

Feldzugri� [JLS05, � 15.11]

class U {int foo = 42;

}

class X {U bar() {

return new U();}

}

class A {void m(X x) {

int xfo = x.bar().foo;}

}

Die Klasse A benutzt die Klasse U, indem sie an einem Methoden-Rückgabewert vomTyp U auf ein Feld zugreift.

Zugri� auf Membertyp [JLS05, � 6.5.5.2]

class U {class Foo {

...}

}

class X {U bar() {

return new U();}

}

class A {Object m(X x) {

return x.bar().new Foo();}

}

Die Klasse A benutzt die Klasse U, indem sie an einem Methoden-Rückgabewert vomTyp U ein Exemplar einer inneren Klasse erzeugt.

90

B.2 Methoden

B.2 Methoden

Im Folgenden die Benutztbeziehungen von Methoden in Java.

Methodenaufruf [JLS05, � 15.12]

class U {void used() {

...}

}

class A {void m(U u) {

u.used();}

}

Die Klasse A benutzt die Methode used() der Klasse U, indem sie sie an einer Va-riable aufruft.

class U {void used() {

...}

}

class X {U foo() {

return new U();}

}

class A {void m(X x) {

x.foo().used();}

}

Die Klasse A benutzt die Methode used() der Klasse U, indem sie sie am Rückga-bewert einer Methode aufruft.

91

B Benutztbeziehungen in Java

class U {private void used() {

...}

private class A {void m(U u) {

used();}

}}

Die Klasse A benutzt die Methode used() der umschlieÿenden Klasse U, indem siesie implizit an U.this aufruft.

class U {static void used() {

...}

}

class A {void m() {

U.used();}

}

Die Klasse A benutzt die statische Methode used() der Klasse U, indem sie sie ander Klasse U aufruft.

package p;

public class U {public static void used() {

...}

}

import static p.U.*;

class A {void m() {

used();}

}

Die Klasse A benutzt die statisch importierte Methode used() der Klasse U, indemsie sie implizit an U aufruft.

92

B.2 Methoden

class U {void used() {

...}

}

class A extends U {void m() {

used();}

}

Die Klasse A benutzt die von U geerbte Methode used(), indem sie sie implizit anthis aufruft.

class U {void used() {

...}

}

class A extends U {void m() {

super.used();}

}

Die Klasse A benutzt die Methode used() ihrer Oberklasse U, indem sie sie ansuper aufruft.

class U {void used() {

...}

}

class X extends U {}

class A {void m(X x) {

x.used();}

}

Die Klasse A benutzt die Methode used() der Klasse U, indem sie sie an einemAusdruck vom Typ einer Unterklasse von U aufruft, die used() nicht überschreibt.

93

B Benutztbeziehungen in Java

Konstruktoraufruf [JLS05, � 8.8.7.1, 15.9]

class Used {Used() {

...}

}

class A {Object m() {

return new Used();}

}

Die Klasse A benutzt den Konstruktor Used() der Klasse Used, indem sie ihn imRahmen einer Exemplarerzeugung aufruft.

class Used {Used() {

...}

}

class A extends Used {A() {

super();...

}}

Die Klasse A benutzt den Konstruktor Used() ihrer Oberklasse, indem sie ihn alsSuperkonstruktor explizit aufruft.

class Used {Used() {

...}

}

class A extends Used {A() {

...}

}

Die Klasse A benutzt den Konstruktor Used() ihrer Oberklasse, indem ihr Kon-struktor ihn implizit aufruft.

94

B.2 Methoden

class Used {Used() {

...}

}

class A extends Used {}

Die Klasse A benutzt den Konstruktor Used() ihrer Oberklasse, indem ihr Default-Konstruktor ihn implizit aufruft.

class Used {Used() {

...}

Used(int i) {this();...

}}

Die Klasse Used benutzt den eigenen Konstruktor Used(), indem sie ihn aus einemanderen Konstruktor aufruft.

Überschreiben und Verdecken [JLS05, � 8.4.8]

class U {void used() {

...}

}

class A extends U {void used() {

...}

}

Die Klasse A benutzt die Methode used() ihrer Oberklasse U, indem sie sie über-schreibt.

95

B Benutztbeziehungen in Java

class U {static void used() {

...}

}

class A extends U {static void used() {

...}

}

Die Klasse A benutzt die statische Methode used() ihrer Oberklasse U, indem siesie verdeckt.

Erben um zu Implementieren (vgl. Kapitel 3.2.3)

interface I {public void used();

}

class U {public void used() {

...}

}

class A extends U implements I {}

Die Klasse A benutzt die Methode used() ihrer Oberklasse U, um damit die Ope-ration used() aus dem Interface I zu implementieren.

96

C Das AccessAnalysis-Plug-In

C.1 Systemvoraussetzungen

• Eclipse ab Version 3.4

• Java 1.6

C.2 Installation

C.2.1 Eclipse 3.4 (Ganymede)

• Wählen Sie im Menü Help Ñ Software Updates...

• Wechseln Sie zum Reiter Available Software.

• Fügen Sie die Datei AccessAnalysis-<version>.zip als Update Site hinzu(Abb. 21(a)).

• Installieren Sie das Feature AccessAnalysis (Abb. 21(b)).

C.2.2 Eclipse 3.5 (Galileo) und 3.6 (Helios)

• Wählen Sie im Menü Help Ñ Install New Software...

• Fügen Sie die Datei AccessAnalysis-<version>.zip als Update Site hinzu(Abb. 22(a)).

• Installieren Sie das Feature AccessAnalysis (Abb. 22(b)).

97

C Das AccessAnalysis-Plug-In

(a) Update Site hinzufügen

(b) Feature installieren

Abbildung 21: Installationdialoge (Eclipse 3.4).

98

C.2 Installation

(a) Update Site hinzufügen

(b) Feature installieren

Abbildung 22: Installationsdialoge (Eclipse 3.5 und 3.6).

99

C Das AccessAnalysis-Plug-In

C.3 Benutzung

• Wählen Sie im Package Explorer oder einer anderen View ein oder mehrereProjekte aus.

• Klicken Sie mit rechts auf das Projekt bzw. die ausgewählten Projekte undwählen Sie Analyse Access (Abb. 23(a)).

• Daraufhin wird das komplette Projekt analysiert, während ein Fortschrittsbal-ken angezeigt wird.

• Nach Abschluss der Analyse werden die Ergebnisse in der View AccessAnalysisangezeigt (Abb. 23(b)).

• Über die Schalt�ächen oben rechts oder das Kontextmenü lässt sich der Ergeb-nisbaum auf Paketeebene ( ), Typebene ( ) oder komplett, d.h auf Metho-denebene ( ), aufklappen.

• Einzelne Zeilen lassen sich markieren und in die Zwischenablage kopieren. Mitder Tastenkombination Strg-A können alle aufgeklappten Ergebnisse markiertwerden.

100

C.3 Benutzung

(a) Package-Explorer-Menü

(b) Ergebnisausgabe in der AccessAnalysis-View

Abbildung 23: Benutzung von AccessAnalysis.

101

D Alternative Metrikde�nitionen

D Alternative Metrikde�nitionen

D.1 IGAT2

De�nition 5:Die Metrik IGAT2 sei folgendermaÿen de�niert:

IGAT2pU, P q � |T�pU,P q||T#pU,P q|

wobei

• P der Quelltext aller Übersetzungseinheiten eines Java-Programms ist,

• U mit U � P eine Quelltext-Teilmenge aus P (z.B. der gesamte Quelltext, einPaket oder eine Typdeklaration)

• T#pU, P q die Menge aller in U deklarierten Typen, deren minimaler Zugri�smodi-�kator in Bezug auf P strenger ist als public, und |T#pU, P q| deren Anzahl,

• T �pU, P q mit T �pU, P q � T#pU, P q die Menge aller in U deklarierten Typen, derenZugri�smodi�kator jeweils groÿzügiger ist als der minimale Zugri�smodi�kator inBezug auf P , und |T �pU, P q| deren Anzahl.

D.2 IGAM2

De�nition 6:Die Metrik IGAM2 sei folgendermaÿen de�niert:

IGAMpV, P q � |M�pV,P q||M#pV,P q|

wobei

• P auch hier der Quelltext aller Übersetzungseinheiten eines Java-Programms ist,

• V mit V � P eine Quelltext-Teilmenge aus P (z.B. der gesamte Quelltext, einPaket, eine Typ- oder Methodendeklaration)

• M#pV, P q die Menge aller in V deklarierten Methoden, deren minimaler Zugri�s-modi�kator in Bezug auf P strenger ist als public, und |M#pV, P q| deren Anzahl,

• M�pV, P q mitM�pV, P q �M#pV, P q die Menge aller in V deklarierten Methoden,deren Zugri�smodi�kator jeweils groÿzügiger ist als der minimale Zugri�smodi�ka-tor in Bezug auf P , und |M�pV, P q| deren Anzahl.

102

E Inhalt der CD-Beilage

Die dieser Arbeit beigelegte CD enthält vier Dateiordner mit folgendem Inhalt:

diplomarbeit: Diese Arbeit als PDF-Dokument.

fallstudiec: Der Quelltext der in Fallstudie C untersuchten Open-Source-Projekte.

quelltext: Der Quelltext des AccessAnalysis-Plug-Ins.

updatesite: Die Installationsdatei des AccessAnalysis-Plug-Ins.

103

Abkürzungen

Abkürzungen

Abb. Abbildung

AHF Attribute Hiding Factor

API Application programming interface

AST Abstract syntax tree

COCOMO Constructive Cost Model

CPU Central processing unit

CU Class Unity

DIN Deutsches Institut für Normung

DIT Depth of Inheritance Tree

DV Data Visibility

EF Encapsulation Factor

EJB Enterprise JavaBean

ERS Empirisches Relationensystem

FRS Formales Relationensystem

GHz Gigahertz

GQM Goal-Question-Metric

HTML Hypertext Markup Language

IDE Integrated Development Environment

IGAM Inappropriate Generosity with Accessibility of Methods

IGAT Inappropriate Generosity with Accessibility of Types

IH Information Hiding (Metrik)

104

Abkürzungen

IHFC Information-Hiding Factor

ISO International Organization for Standardization

JAR Java Archive

JDK Java Development Kit

JDT (Eclipse) Java Development Tools

JSP Java Server Page

LOC Lines of Code

MHF Method Hiding Factor

MOOD Metrics for Object Oriented Design

NCLOC Non-Commented Lines of Codes

PDF Portable Document Format

QTK Quelltextkonventionen

RAM Random-access memory

RCP (Eclipse) Rich Client Plattform

v zyklomatische Komplexität

vgl. vergleiche

105

Literatur

Literatur

[AC94] Abreu, Fernando Brito e ; Carapuça, Rogério: Object-Oriented Soft-ware Engineering: Measuring and Controlling the Development Process.In: Proceedings of the 4th International Conference on Software Quality(QSIC). McLean, VA, USA, 1994

[AGH05] Arnold, Ken ; Gosling, James ; Holmes, David: The Java Program-ming Language. Fourth Edition. Upper Saddle River, NJ, USA : Addison-Wesley, 2005

[Alb79] Albrecht, Allan J.: Measuring Application Development Productivity.In: Proceedings of IBM Applications Devision Joint SHARE/GUIDE Sym-posium. Monterey, CA, USA, 1979, S. 83�92

[BCH�95] Boehm, Barry W. ; Clark, Bradford ; Horowitz, Ellis ; Westland,Chris ;Madachy, Ray ; Selby, Richard: Cost Models for Future SoftwareLife Cycle Processes: COCOMO 2.0. In: Annals of Software EngineeringSpecial Volume on Software Process and Product Measurement (1995), S.57�94

[BGS08] Bouillon, Philipp ; Groÿkinsky, Eric ; Steimann, Friedrich: Control-ling Accessibility in Agile Projects with the Access Modi�er Modi�er. In:Proceedings of TOOLS (46), 2008, S. 41�59

[BK09] Barnes, David J. ; Kölling, Michael: Java lernen mit BlueJ � Eine Ein-führung in die objektorientierte Programmierung. 4., aktualisierte Au�age.München : Pearson Studium, 2009

[Blo08] Bloch, Joshua: E�ective Java. Second Edition. Upper Saddle River, NJ,USA : Addison-Wesley, 2008

[Boe81] Boehm, Barry W.: Software Engineering Economics. Upper Saddle River,NJ, USA : Prentice Hall, 1981

[BR88] Basili, Victor R. ; Rombach, H. D.: The TAME project: towardsimprovement-oriented softwareenvironments. In: IEEE Transactions onSoftware Engineering 14 (1988), Nr. 6, S. 758�773

[BR04] Bennicke, Marcel ; Rust, Heinrich: Messen im Software-Engineering undmetrikbasierte Qualitätsanalyse. ViSEK/024/D, Version 1.2. VirtuellesSoftware Engineering Kompetenzzentrum, BTU Cottbus, 2004

[BW84] Basili, Victor R. ;Weiss, David M.: A Methodology for Collecting ValidSoftware Engineering Data. In: IEEE Transactions on Software Enginee-ring 10 (1984), Nr. 6, S. 728�738

106

Literatur

[CK94] Chidamber, Shyam R. ; Kemerer, Chris F.: A Metrics Suite for Ob-ject Oriented Design. In: IEEE Transactions on Software Engineering 20(1994), Nr. 6, S. 476�493

[CM78] Cavano, Joseph P. ; McCall, James A.: A framework for the measure-ment of software quality. In: ACM SIGMETRICS Performance EvaluationReview 7 (1978), Nr. 3-4, S. 133�139

[CZ08] Cao, Yong ; Zhu, Qingxin: Improved Metrics for Encapsulation Based onInformation Hiding. In: The 9th International Conference for Young Com-puter Scientists (ICYCS 2008). Los Alamitos, CA, USA : IEEE ComputerSociety, 2008, S. 742�747

[DeM97] DeMarco, Tom: Warum ist Software so teuer? München : Carl HanserVerlag, 1997

[ECM06] ECMA International: Standard ECMA-334 � C# Language Speci�ca-tion. 4th edition. Genf, Schweiz, June 2006

[FB09] FindBugs Bug Descriptions. 2009. http://�ndbugs.sourceforge.net/bugDescriptions.html. In: FindBugs Project Page (SourceForge.net), Ab-ruf: 03.11.2010

[Fea08] Feathers, Michael: The Fact/Intention Gap. 2008. http://blog.objectmentor.com/articles/2008/10/21/the-fact-intention-gap. In: ObjectMentor � Industry experts in software best practices, Abruf: 03.11.2010

[Fla05] Flanagan, David: Java in a nutshell. 5th Edition. Sebastopol, CA, USA: O'Reilly Media, 2005

[Fow99] Fowler, Martin: Refactoring: improving the design of existing code. Bo-ston, MA, USA : Addison-Wesley, 1999

[Fow02] Fowler, Martin: Public versus Published Interfaces. In: IEEE Software19 (2002), Nr. 2, S. 18�19

[FP97] Fenton, Norman E. ; Pfleeger, Shari Lawrence: Software Metrics: ARigorous & Practical Approach. Second Edition. Boston, MA, USA : PWSPublishing Co., 1997

[GHJV95] Gamma, Erich ; Helm, Richard ; Johnson, Ralph ; Vlissides, John:Design patterns: elements of reusable object-oriented software. Boston, MA,USA : Addison-Wesley, 1995

[Gro07] Groÿkinsky, Eric: Access Modi�er Modi�er � Ein Werkzeug zur Einstel-lung der Sichtbarkeit in Java-Programmen, Fernuniversität Hagen, Master-arbeit, 2007

107

Literatur

[Hal77] Halstead, Maurice H.: Elements of Software Science. New York, NY,USA : Elsevier Science Inc., 1977

[HK81] Henry, Sallie ; Kafura, Dennis: Software Structure Metrics Based on In-formation Flow. In: IEEE Transactions on Software Engineering 7 (1981),Nr. 5, S. 510�518

[HMHG07] Heinisch, Cornelia ;Müller-Hofmann, Frank ; Goll, Joachim: Ja-va als erste Programmiersprache � Vom Einsteiger zum Pro�. 5., überar-beitete und erweiterte Au�age. Wiesbaden : B. G. Teubner Verlag, 2007

[Int01] International Organization for Standardization: Software engi-neering � Product quality � Part 1: Quality model. ISO/IEC 9126-1. Genf,Schweiz, 2001

[JDT09] Eclipse JDT API Speci�cation. 2009. http://help.eclipse.org/galileo/topic/org.eclipse.jdt.doc.isv/reference/api/overview-summary.html. In:Eclipse Online Hilfe, Abruf: 03.11.2010

[Jig10] Project Jigsaw. http://openjdk.java.net/projects/jigsaw/. In: OpenJDKWebsite, Abruf: 03.11.2010

[JLS05] Gosling, James ; Joy, Bill ; Steele, Guy ; Bracha, Gilad: The JavaLanguage Speci�cation. Third Edition. Upper Saddle River, NJ, USA :Addison-Wesley, 2005

[Lil08] Lilienthal, Carola: Komplexität von Softwarearchitekturen � Stile undStrategien, Universität Hamburg, Dissertation, 2008

[LLL08] Lincke, Rüdiger ; Lundberg, Jonas ; Löwe, Welf: Comparing softwaremetrics tools. In: ISSTA '08: Proceedings of the 2008 international sympo-sium on Software testing and analysis. New York, NY, USA : ACM, 2008,S. 131�142

[Mar94] Martin, Robert C.: OO Design Quality Metrics: An Analysis of De-pendencies. (1994). http://www.objectmentor.com/resources/articles/oodmetrc.pdf, Abruf: 03.11.2010

[McC76] McCabe, Thomas J.: A Complexity Measure. In: IEEE Transactions onSoftware Engineering 2 (1976), Nr. 4, S. 308�320

[Mey97] Meyer, Bertrand: Object-oriented Software Construction. 2nd Edition.Upper Saddle River, NJ, USA : Prentice Hall, 1997

[MR03] Mughal, Khalid A. ; Rasmussen, Rolf W.: Programmer's Guide to JavaCerti�cation, A: A Comprehensive Primer. Second Edition. Upper SaddleRiver, NJ, USA : Addison-Wesley, 2003

108

Literatur

[OH08] Ordonez, Mauricio J. ; Haddad, Hisham M.: The State of Metrics inSoftware Industry. In: ITNG '08: Proceedings of the Fifth InternationalConference on Information Technology: New Generations. Washington,DC, USA : IEEE Computer Society, 2008, S. 453�458

[Par72] Parnas, David L.: On the criteria to be used in decomposing systems intomodules. In: Communications of the ACM 15 (1972), Nr. 12, S. 1053�1058

[PMD09] Current Rulesets. 2009. http://pmd.sourceforge.net/rules/index.html. In:PMD Project Page (SourceForge.net), Abruf: 03.11.2010

[Pom06] Pomberger, Gustav: Prozedurorientierte Programmierung. In: Rechen-berg, Peter (Hrsg.) ; Pomberger, Gustav (Hrsg.): Informatik-Handbuch.4., aktualisierte und erweiterte Au�age. München : Hanser Verlag, 2006,S. 563�574

[RC94] Rising, Linda S. ; Calliss, Frank W.: An information-hiding metric. In:Journal of Systems and Software 26 (1994), Nr. 3, S. 211�220

[Rei08] Reinhold, Mark: Project Jigsaw. 2008. http://blogs.sun.com/mr/entry/jigsaw. In: There's not a moment to lose! � Mark Reinhold's Blog, Abruf:03.11.2010

[RSSW10] Ratz, Dietmar ; Scheffler, Jens ; Seese, Detlef ; Wiesenberger,Jan: Grundkurs Programmieren in Java. 5., überarbeitete Au�age. Mün-chen : Carl Hanser Verlag, 2010

[SA07] Saini, Sunint ; Aggarwal, Mehak: Enhancing Mood Metrics Using En-capsulation. In: ICAI'07: Proceedings of the 8th WSEAS InternationalConference on Automation and Information. Stevens Point, Wisconsin,USA : World Scienti�c and Engineering Academy and Society (WSEAS),2007, S. 252�257

[Sch06] Schreier, Oliver Lars André: Einsatz von Softwaremaÿen zur Qualitäts-sicherung, Universität Hamburg, Diplomarbeit, 2006

[Sch10] Schiedermeier, Reinhard: Programmieren mit Java. 2., aktualisierteAu�age. München : Pearson Studium, 2010

[Sim01] Simon, Frank: Meÿwertbasierte Qualitätssicherung, BrandenburgischeTechnische Universität Cottbus, Dissertation, 2001

[Sny86] Snyder, Alan: Encapsulation and Inheritance in Object-Oriented Pro-gramming Languages. In: OOPLSA '86: Conference proceedings on Object-oriented programming systems, languages and applications. New York, NY,USA : ACM, 1986, S. 38�45

109

Literatur

[SSL01] Simon, Frank ; Steinbrückner, Frank ; Lewerentz, Claus: MetricsBased Refactoring. In: CSMR '01: Proceedings of the Fifth European Con-ference on Software Maintenance and Reengineering. Washington, DC,USA : IEEE Computer Society, 2001, S. 30

[SZ�08] Schmolitzy, Axel ; Züllighoven, Heinz et al.: Prüfungsunterlagen zurLehrveranstaltung �Softwareentwicklung I (SE1): Grundlagen objektorien-tierter Programmierung�. Universität Hamburg, MIN-Fakultät, Depart-ment Informatik, 2008

[Szy92] Szyperski, Clemens: Import is not inheritance why we need both: Modu-les and classes. In: Madsen, Ole (Hrsg.): ECOOP '92: European Confe-rence on Object-Oriented Programming Bd. 615. Berlin : Springer-Verlag,1992, S. 19�32

[Ull09] Ullenboom, Christian: Java ist auch eine Insel. 8., aktualisierte Au�age.Bonn : Galileo Press, 2009

[ZR06] Züllighoven, Heinz ;Raasch, Jörg: Softwaretechnik. In:Rechenberg,Peter (Hrsg.) ; Pomberger, Gustav (Hrsg.): Informatik-Handbuch. 4.,aktualisierte und erweiterte Au�age. München : Hanser Verlag, 2006, S.795�837

[Zus97] Zuse, Horst: A Framework of Software Measurement. Hawthorne, NJ,USA : Walter de Gruyter & Co., 1997

[Zü98] Züllighoven, Heinz: Das objektorientierte Konstruktionshandbuch nachdem Werkzeug- & Material-Ansatz. Heidelberg : dpunkt-Verlag, 1998

110

Erklärung

Ich versichere, dass ich die vorliegende Arbeit selbständig und ohne fremde Hilfe an-gefertigt und mich anderer als der im beigefügten Verzeichnis angegebenen Hilfsmittelnicht bedient habe. Alle Stellen, die wörtlich oder sinngemäÿ aus Verö�entlichungenentnommen wurden, sind als solche kenntlich gemacht.

Ich bin mit einer Einstellung in den Bestand der Bibliothek des Departments Infor-matik einverstanden.

Hamburg, November 2010