Klassendiagramme in UML: Beziehungen, Kardinalitäten und Notation

Written By Johannes  |  Coding  |  0 Comments

Ein Klassendiagramm wirkt auf den ersten Blick schlicht. Rechtecke stehen für Klassen, Linien verbinden sie. Die eigentliche Aussage steckt jedoch in Details, die leicht übersehen werden, etwa in einer leeren oder ausgefüllten Raute, einer bestimmten Pfeilspitze oder einer Zahl am Ende einer Linie. Wer diese Zeichen falsch liest, setzt im Code eine andere Struktur um als die, die im Entwurf gemeint war. Dieser Überblick erklärt die Notation so, dass sich Diagramme sicher lesen und selbst korrekt zeichnen lassen.

Eine Klasse besteht aus drei Abschnitten

Klassendiagramme gehören zu den Strukturdiagrammen der UML und beschreiben, woraus ein System besteht, unabhängig vom zeitlichen Ablauf. Im Studium der Softwareentwicklung zählen sie deshalb zu den ersten Modellierungswerkzeugen, mit denen objektorientiertes Denken geübt wird.

Das Rechteck einer Klasse gliedert sich in drei waagerechte Felder. Das erste trägt den Klassennamen, das zweite nimmt die Attribute auf, das dritte die Operationen. Attribute werden nach dem Muster Sichtbarkeit, Name, Doppelpunkt und Typ notiert, bei Bedarf ergänzt um eine Multiplizität in eckigen Klammern und einen Standardwert. Operationen tragen ihre Parameter in runden Klammern und nach einem weiteren Doppelpunkt den Rückgabetyp. Statische Elemente werden unterstrichen, abstrakte Klassen und Operationen kursiv geschrieben oder mit der Eigenschaft abstract gekennzeichnet. Vor jedem Element steht ein Zeichen für die Sichtbarkeit:

  • Plus für öffentlich (public)
  • Minus für privat (private)
  • Raute für geschützt (protected)
  • Tilde für die Sichtbarkeit innerhalb des Pakets (package)

Assoziationen beschreiben dauerhafte Verbindungen

Eine durchgezogene Linie zwischen zwei Klassen steht für eine Assoziation. Ein Name in der Mitte der Linie, oft mit einem kleinen Dreieck für die Leserichtung, macht die Beziehung verständlich, zum Beispiel „bestellt“ zwischen Kunde und Bestellung. An den Enden können Rollennamen stehen, die beschreiben, welche Funktion eine Klasse in dieser Beziehung übernimmt. Eine offene Pfeilspitze zeigt die Navigierbarkeit an. Sie legt fest, dass eine Klasse die andere kennt, umgekehrt aber nicht zwingend. Hat die Beziehung selbst Eigenschaften, kommt eine Assoziationsklasse zum Einsatz. Die Teilnahme eines Studierenden an einem Kurs besitzt etwa eine Note, die weder zum Studierenden noch zum Kurs allein gehört. Diese Klasse wird über eine gestrichelte Linie mit der Assoziationslinie verbunden.

Multiplizitäten legen fest, wie viele Objekte beteiligt sind

Die Zahlen an den Linienenden heißen in der UML Multiplizitäten. Umgangssprachlich ist oft von Kardinalitäten die Rede, streng genommen bezeichnet die Kardinalität jedoch die tatsächliche Anzahl von Elementen, während die Multiplizität den zulässigen Bereich angibt. Gebräuchlich sind diese Angaben:

  • 1 für genau ein Objekt
  • 0..1 für kein oder ein Objekt
  • * oder 0..* für beliebig viele Objekte einschließlich keinem
  • 1..* für mindestens ein Objekt
  • 2..4 für einen festen Bereich

Entscheidend ist, an welchem Ende die Angabe steht. Die Multiplizität wird an die Klasse geschrieben, deren Anzahl sie beschreibt. Hat ein Kunde beliebig viele Bestellungen und gehört jede Bestellung zu genau einem Kunden, steht 0..* neben der Bestellung und 1 neben dem Kunden. Genau diese Stelle wird in Diagrammen am häufigsten vertauscht. Reflexive Assoziationen verbinden eine Klasse mit sich selbst, etwa wenn eine Person einer anderen Person desselben Typs als Vorgesetzte zugeordnet ist. Auch dort gehören an beide Enden Multiplizitäten und idealerweise Rollennamen.

Aggregation und Komposition unterscheiden sich in der Lebensdauer

Beide Beziehungen drücken ein Verhältnis von Ganzem und Teil aus, und bei beiden sitzt die Raute an der Seite des Ganzen. Die leere Raute steht für die Aggregation. Ihre Bedeutung lässt die UML bewusst offen, weshalb sie in vielen Projekten nur sparsam eingesetzt wird. Die ausgefüllte Raute kennzeichnet die Komposition und ist streng definiert. Ein Teil gehört zu höchstens einem Ganzen, und wird das Ganze gelöscht, verschwinden seine Teile mit ihm. Ein Rechnungsposten existiert nicht ohne seine Rechnung, ein Mitarbeiter dagegen sehr wohl ohne die Abteilung, der er zugeordnet ist.

Vererbung, Realisierung und Abhängigkeit

Eine durchgezogene Linie mit einem leeren Dreieck als Spitze zeigt eine Generalisierung. Das Dreieck zeigt auf die allgemeinere Klasse, von der die speziellere erbt. Wird statt der durchgezogenen eine gestrichelte Linie verwendet, handelt es sich um eine Realisierung, meist die Umsetzung einer Schnittstelle, die im Diagramm mit dem Stereotyp interface gekennzeichnet ist. Eine gestrichelte Linie mit offener Pfeilspitze beschreibt eine Abhängigkeit. Sie besagt, dass eine Klasse eine andere nutzt, etwa als Parameter, ohne sie dauerhaft als Attribut zu halten. Angebotene Schnittstellen lassen sich alternativ in der sogenannten Lollipop-Notation zeigen, bei der ein kleiner Kreis am Ende einer Linie für die Schnittstelle steht. Aufzählungstypen tragen den Stereotyp enumeration und führen ihre möglichen Werte im mittleren Abschnitt auf.

Vom Entwurf zum lesbaren Diagramm

Ein gutes Klassendiagramm zeigt nicht jede Kleinigkeit. Für Besprechungen genügen oft Klassennamen und die wichtigsten Beziehungen, für die Implementierung kommen Attribute und Operationen hinzu. Größere Systeme lassen sich übersichtlicher in mehreren Diagrammen darstellen, jeweils für ein Paket oder einen fachlichen Bereich.

Wer ein Klassendiagramm erstellen möchte, ohne jede Linie von Hand zu setzen, kann in Lucidchart auf eine UML-Formenbibliothek zurückgreifen und Diagramme zusätzlich aus Mermaid-Code erzeugen. Das beschleunigt vor allem Änderungen, wenn sich im Projekt Klassen oder Beziehungen verschieben.

Zum Nachschlagen der Notation eignet sich die Einführung in die grafische Beschreibungssprache UML des Karlsruher Instituts für Technologie. Sie beschreibt jedes Element zusätzlich ausführlich in Worten und ist dadurch auch für Menschen mit Sehbeeinträchtigung zugänglich.

So wird aus dem Diagramm Code

In Sprachen wie Java lässt sich die Notation weitgehend direkt übertragen. Attribute werden zu Feldern, Operationen zu Methoden, und eine Multiplizität von 0..* wird meist als Liste oder andere Sammlung umgesetzt. Eine Generalisierung entspricht dem Schlüsselwort extends, eine Realisierung dem Schlüsselwort implements. Kompositionen zeigen sich häufig darin, dass das Ganze seine Teile selbst erzeugt und nach außen nicht weitergibt.

Wer die Übertragung an kleinen Programmen üben möchte, findet mit dem Auslesen des Betriebssystems mit Java ein überschaubares Beispiel, an dem sich Klassen, Methoden und Rückgabewerte nachvollziehen lassen. Typische Fehler beim Modellieren sind vor allem diese:

  • Multiplizitäten am falschen Ende der Linie
  • Komposition, wo eine einfache Assoziation genügt
  • Vererbung für Beziehungen, die eigentlich eine Hat-ein-Beziehung sind
  • uneinheitliche Pfeilspitzen, die Generalisierung und Abhängigkeit verwechseln

{"email":"Email address invalid","url":"Website address invalid","required":"Required field missing"}
>