Klassenmodell

Nachdem wir die Anwendungsfälle und das Anwendungsfalldiagramm erstellt hatten, war die Beschreibung der statischen Struktur des zu modellierenden Anwendungssystems durch ein Klassenmodell unsere nächste Aufgabe. Dabei dienten die ermittelten Anwendungsfälle von JWI als Grundlage. Im einzelnen war für uns zu tun:  
 
 

Ermittlung von Klassenkandidaten:

Zunächst haben wir die textuelle Beschreibung der Anwendungsfälle analysiert, um Substantive zu identifizieren, die zentrale Konzepte des zu modellierenden Anwendungssystems bezeichnen und darum als Klassenkandidaten in Erwägung zu ziehen sind. Dabei erschienen uns solche Konzepte als besonders relevant, die an den Handlungen der Anwendungsfälle aktiv oder passiv beteiligt sind, wie etwa "Produkte", "Kunden" oder "Bestellposten". Auf diese Weise konnten wir folgende Liste von Klassenkandidaten aufstellen: 
  • Bestellposten
  • Kunde
  • Kundenbestellung
  • Lieferant
  • Liefer-Kartei
  • Nachbestellung
  • Produkt
  • Wartei-Kartei.
Der interessierte Leser kann sich die Kandidaten im Kontext der Anwendungsfallbeschreibungen ansehen. 

Da sich herausstellte, daß sowohl zwischen den Klassen "Kundenbestellung" und "Nachbestellung" als auch zwischen den Klassen "Kunde" und "Lieferant" Gemeinsamkeiten bestehen (Beispielsweise haben sowohl Kunden als auch Lieferanten eine Adresse, und Kundenbestellungen wie Nachbestellungen setzen sich aus Bestellposten zusammen), wurde beschlossen, zwei zusätzliche abstrakte (d. h. nicht instanziierbare) Oberklassen "Bestellung" und "Geschäftspartner" einzuführen, um diese Gemeinsamkeiten zu modellieren. Von "Bestellung" wurden als instanziierbare Klassen "Kundenbestellung" und "Nachbestellung", von "Geschäftspartner" "Kunde" und "Lieferant" abgeleitet. 

Der Lieferschein wurde von uns an dieser Stelle des Modellierungsprozesses nicht als eigene Klasse modelliert, da zum einen die für einen Lieferschein zusammengestellten Informationen nach dem Ausdruck des Scheins nicht mehr benötigt werden (Rückinformationen über ausgelieferte Bestellposten werden über die "Liefer-Kartei" behandelt) und zum anderen eine Integration der Lieferscheinerstellung in die Klasse "Liefer-Kartei" favorisiert wurde, weil die Informationen in dieser Kartei zur Erstellung der Lieferscheine herangezogen werden. 

Mit der Erweiterung unserer ursprünglichen Klassenliste um die beiden abstrakten Klassen "Bestellung" und Geschäftspartner hatten wir die Klassen für den ersten Entwurf des Klassendiagramms beisammen und gingen daran, die Beziehungen zwischen den Klassen festzulegen. 


Guided Tour: Weiter bei Festlegung von Beziehungen zwischen den Klassen 

1. Änderung an den Klassen:

Problem:
Noch während der Erstellung des Klassenmodells fiel uns folgender Fehler in unserer Modellierung auf: Wie im ersten Entwurf des Klassendiagramms dargestellt, ist die Klasse "Bestellposten" über eine Entweder-Oder- Assoziation mit den Klassen "Liefer-Kartei" bzw. "Warte-Kartei" verknüpft. Außerdem besteht eine Kompositionsbeziehung zwischen ihr und "Bestellung", der abstrakten Oberklasse für "Kundenbestellung" und "Nachbestellung". Da nun letztere Klassen die Eigenschaften ihrer Oberklasse erben, wäre damit nicht nur "Kundenbestellung" indirekt über "Bestellposten" mit "Liefer-Kartei" bzw. "Warte-Kartei" verknüpft, sondern auch "Nachbestellung". Mit anderen Worten: Damit würden nicht nur Bestellposten von Kundenbestellungen entweder in die Liefer-Kartei oder in die Warte-Kartei eingetragen, sondern auch Bestellposten von Nachbestellungen, was nicht den Gegebenheiten von JWI entspricht (vgl. Anwendungsfall "Bestellung bearbeiten" vs. Anwendungsfall "Fehlbestände nachbestellen"). Außerdem zeigte es sich, daß die Klasse "Bestellposten" zu allgemein war, um sowohl die Bestellposten von Kundenbestellungen als auch die Bestellposten von Nachbestellungen adäquat modellieren zu können. 
     
Unsere Lösung:
    Der zweite Entwurf des Klassendiagramms enthält keine abstrakte Klasse "Bestellung" mehr, d. h. "Kundenbestellung" und "Nachbestellung" sind voneinander entkoppelt. Die zugehörigen Bestellposten werden durch die beiden neuen Klassen "Bestellposten Kundenbestellung" bzw. "Bestellposten Nachbestellung" modelliert, die von der nunmehr als abstrakte Oberklasse modellierten Klasse "Bestellposten" abgeleitet werden. "Bestellposten" ist weiterhin mit der Klasse "Produkt" verknüpft, so daß sich über die aufgebaute Vererbungsbeziehung auch die beiden abgeleiteten Bestellposten-Klassen auf diese Klasse beziehen können. 
     
Auswirkungen der Änderung:
    Die an den Assoziationen vorzunehmenden Änderungen werden im Abschnitt über die Beziehungen zwischen den Klassen beschrieben.

Guided Tour: Weiter bei den ersten beiden Änderungen an den Assoziationen 

2. Änderung an den Klassen:

Problem:
Bei der Erstellung des Aktivitätsdiagramms zur Operation "lieferscheine_erstellen()" der Klasse "Liefer-Kartei" stellten wir fest, daß wir für den von uns vorgeschlagenen Algorithmus eine Möglichkeit brauchen, die Daten der vorbereiteten Lieferscheine zwischenzuspeichern. 

 
Unsere Lösung:
Wir führten eine Klasse "Lieferschein" ein, deren Instanzen die Daten der erstellten Lieferscheine temporär speichern. Im zweiten Schritt des Algorithmus wird dann jeder Instanz von "Lieferschein" die Nummer des ausliefernden Lieferwagens zugeordnet. Wenn die Lieferscheine schließlich ausgedruckt worden sind, können sämtliche Instanzen von "Lieferschein" wieder gelöscht werden.
 
Auswirkungen der Änderung:
Diese Änderung hatte Auswirkungen auf die Attribute und Operationen der Klasse "Liefer-Kartei" sowie auf das Sequenzdiagramm und das Kollaborationsdiagramm des Anwendungsfalls "Lieferscheine erstellen".

Guided Tour: Weiter bei der 3. Änderung der Beziehungen 

3. Änderung an den Klassen:

Problem:
Bei der Erstellung der Sequenzdiagramme fiel uns auf, daß wir bei unserer Modellierung bis zu diesem Zeitpunkt noch keine Operationen vorgesehen hatten, die vom Benutzer aufgerufen werden können, um die Bearbeitung der Anwendungsfälle anzustoßen. Außerdem brauchten wir eine Möglichkeit, diverse für das Anwendungssystem globale Daten zu verwalten (z. B. die zuletzt vergebene Bestellnummer oder die Liste der lieferbaren Produkte). 
 
Unsere Lösung:
Es wurde eine administrative Klasse "Verwaltung" eingeführt, die allgemeine Verwaltungsaufgaben innerhalb des Anwendungssystems übernimmt. Sie ist für die Initialisierung des Anwendungssystems verantwortlich und bündelt die Operationen, die der Benutzer direkt anstoßen kann. Außerdem verwaltet sie eine Reihe von Attributen, die für das Anwendungssystem globale Daten beinhalten. Die Details sind in der Dokumentation des Beispielprojekts nachzulesen. 
 
Auswirkungen der Änderung:
Eine Instanz der Klasse "Verwaltung" wurde in fast alle Sequenz- und Kollaborationsdiagramme integriert (Eine Ausnahme bildeten die Diagramme zum Anwendungsfall "Lagerbestand ermitteln", da dieser vom Benutzer des Systems nicht direkt angestoßen, sondern vielmehr von anderen Anwendungsfällen benutzt wird (vgl. die Darstellung zu den Anwendungsfällen).) In das Klassendiagramm ging die Änderung allerdings infolge einer Absprache mit dem Projektleiter nicht ein. 
 

Weiter bei der 2. Änderung des Sequenzdiagramms "Lieferschein_erstellen": 
 

 

Festlegung von Beziehungen zwischen den Klassen

Parallel zur Ermittlung der Klassenkandidaten wurden bereits Beziehungen zwischen den Klassen festgelegt. Für jede Klasse haben wir dazu überlegt, mit welchen anderen Klassen sie in Beziehung stehen könnte. Nachdem die Partner einer Beziehung feststanden, wurde sie hinsichtlich Art, Direktionalität, Rollen, Kardinalitäten etc. spezifiziert. Dabei erwies sich die zuvor erstellte textuelle Beschreibung der Anwendungsfälle einmal mehr als hilfreiche Grundlage, da sie eine Reihe von Zusammenhängen zwischen den Konzepten aufzeigt. Außerdem konnte vorhandenes Vorwissen aus dem Datenbank-Bereich angewendet werden, etwa bei der Spezifizierung der Beziehung zwischen "Kunde" und "Kundenbestellung" (1:n-Beziehung) oder zwischen "Bestellposten" und "Produkt" (1:1-Beziehung). 

Die auf diese Weise festgelegten Beziehungen sind im einzelnen: 

  • Zwischen den abstrakten Oberklassen "Bestellung" und "Geschäftspartner" und den von ihnen abgeleiteten instanziierbaren Klassen ("Kundenbestellung" und "Nachbestellung" bzw. "Kunde" und Lieferant") bestehen Generalisierungsbeziehungen, die durch Pfeile von der speziellen zur allgemeinen Klasse repräsentiert werden.
  • Die Klassen "Bestellung" und "Bestellposten" sind durch eine Kompositionsbeziehung miteinander verknüpft, da zwischen beiden eine existentielle Abhängigkeit besteht: Ohne Bestellung keine Bestellposten und ohne Bestellposten keine Bestellung!
  • Um dem Sachverhalt gerecht zu werden, daß ein Bestellposten entweder nur der Liefer-Kartei oder nur der Warte-Kartei zugeordnet sein kann (vgl. Anwendungsfall "Bestellung bearbeiten"), wurde die UML-spezifische Entweder-Oder-Assoziation benutzt, die eine Instanz von "Bestellposten" entweder einer Instanz von "Liefer-Kartei" oder einer Instanz von "Warte-Kartei" zuordnet.
  • Die qualifizierende Assoziation wurde gewählt, um in den Beziehungen zwischen "Kundenbestellung" und "Kunde", "Nachbestellung" und "Lieferant" sowie "Bestellposten" und "Produkt" jeweils ein Attribut besonders herauszustellen, über das als "Schlüssel" der Zugriff auf Kunden, Lieferanten bzw. Produkte erfolgt.
  • Zwischen "Lieferant" und "Produkt" besteht eine bidirektionale Assoziation, die festlegt, daß ein Lieferant mehrere Produkte liefern kann (jedoch mindestens 1) und umgekehrt jedes Produkt von genau einem Lieferant geliefert wird (1:n-Beziehung).
Mit den festgelegten Klassen und Beziehungen konnte nun der erste Entwurf des Klassendiagramms erstellt werden. 


Guided Tour: Weiter bei Entwurf 1 des Klassendiagramms 

1. Änderung an den Beziehungen:

Problem:
Noch während der Erstellung des Klassenmodells fiel uns folgender Fehler in unserer Modellierung auf: Wie im ersten Entwurf des Klassendiagramms dargestellt, ist die Klasse "Bestellposten" über eine Entweder-Oder- Assoziation mit den Klassen "Liefer-Kartei" bzw. "Warte-Kartei" verknüpft. Außerdem besteht eine Kompositionsbeziehung zwischen ihr und "Bestellung", der abstrakten Oberklasse für "Kundenbestellung" und "Nachbestellung". Da nun letztere Klassen die Eigenschaften ihrer Oberklasse erben, wäre damit nicht nur "Kundenbestellung" indirekt über "Bestellposten" mit "Liefer-Kartei" bzw. "Warte-Kartei" verknüpft, sondern auch "Nachbestellung". Mit anderen Worten: Damit würden nicht nur Bestellposten von Kundenbestellungen entweder in die Liefer-Kartei oder in die Warte-Kartei eingetragen, sondern auch Bestellposten von Nachbestellungen, was nicht den Gegebenheiten von JWI entspricht (vgl. Anwendungsfall "Bestellung bearbeiten" vs. Anwendungsfall "Fehlbestände nachbestellen"). Außerdem zeigte es sich, daß die Klasse "Bestellposten" zu allgemein war, um sowohl die Bestellposten von Kundenbestellungen als auch die Bestellposten von Nachbestellungen adäquat modellieren zu können. 
 
Unsere Lösung: 
Die neu einzuführenden Klassen wurden bereits bei der ersten Änderung an den Klassen beschrieben. Die Klasse "Kundenbestellung" wurde mit der Klasse "Bestellposten Kundenbestellung" und die Klasse "Nachbestellung" mit der Klasse "Bestellposten Nachbestellung" über eine Kompositionsbeziehung verknüpft. "Bestellposten Kundenbestellung" und "Bestellposten Nachbestellung" wurden mit ihrer abstrakten Oberklasse "Bestellposten" assoziiert. Die Entweder-Oder-Assoziation wurde zwischen "Bestellposten Kundenbestellung" und "Liefer-Kartei" bzw. "Warte-Kartei" definiert. Das Ergebnis kann im zweiten Entwurf des Klassendiagramms betrachtet werden.
 

2. Änderung an den Beziehungen:

Problem:
Die in den Beziehungen zwischen "Kundenbestellung" und "Kunde" bzw. "Nachbestellung" und "Lieferant" bisher verwendeten qualifizierenden Attribute (vgl. Entwurf 1 des Klassendiagramms) sind überflüssig, weil die dadurch unterstützten Navigationsrichtungen über die entsprechenden Assioziationen in unserer Modiellierung keine hervorgehobene Rolle spielen. Sinnvoller ist die Verwendung von qualifizierenden Attributen in der Entweder-Oder-Assoziation zwischen "Bestellposten Kundenbestellung" und "Liefer-Kartei" bzw. "Warte-Kartei". So wird nämlich der kombinierte Schlüssel aus "Bestellnummer (bnr)" und "laufender Nummer (lfdnr)" dargestellt, über den die beiden Karteien auf Instanzen von "Bestellposten Kundenbestellung" zugreifen. 

 
Unsere Lösung:
Die drei genannten qualifizierenden Assoziationen wurden in einfache bidirektionale Assoziationen (1:n) umgewandelt. Die beiden Zweige der Entweder-Oder-Assoziation wurden auf der Seite von "Liefer-Kartei" bzw. "Warte-Kartei" um die qualifizierenden Attribute "bnr" und "lnr" ergänzt (vgl. Entwurf 2 des Klassendiagramms).
 

Guided Tour: Weiter bei Entwurf 2 des Klassendiagramms 

3. Änderung an den Beziehungen:

Problem:
Bei der Erstellung des Aktivitätsdiagramms zur Operation "lieferscheine_erstellen()" der Klasse "Liefer-Kartei" stellten wir fest, daß wir für den von uns vorgeschlagenen Algorithmus eine Möglichkeit brauchen, die Daten der vorbereiteten Lieferscheine zwischenzuspeichern. 
Unsere Lösung:
Die Klasse "Lieferschein" wurde bereits bei der zweiten Änderung an den Klassen beschrieben. Sie wurde mit der Klasse "Liefer-Kartei" über eine einfache bidirektionale Assoziation verknüpft, die verdeutlicht, daß der Liefer-Kartei keine oder beliebig viele Lieferscheine zugeordnet sein können, umgekehrt aber jeder Lieferschein nur der einen Liefer-Kartei des Systems zugeordnet sein darf (1:n-Beziehung).

Guided Tour: Weiter beim endgültigen Klassendiagramm 
 

1. Entwurf des Klassendiagramms

Dieser Abschnitt stellt die drei Entwicklungsstadien dar, die das Klassendiagramm zu JWI im Verlauf des Modellierungsprozesses durchlaufen hat. Die einzelnen Stadien sind jeweils mit Verweisen versehen, die zu den erforderlichen Änderungen verzweigen.

 
Abbildung 4: Entwurf 1 des Klassendiagramms
 

Guided Tour: Weiter bei den Attributen und Operationen

Zurück zur Festlegung der Klassen

Zurück zur Festlegung der Beziehungen


2. Entwurf des Klassendiagramms:

 
Abbildung 5: Entwurf 2 des Klassendiagramms
 

Guided Tour: Weiter bei den Sequenzdiagrammen

Zurück zur 1. Änderung an den Klassen

Zurück zu den ersten beiden Änderungen an den Beziehungen


3. Entwurf des Klassendiagramms:

 
Abbildung 6: Endgültiges Klassendiagramm
 
Guided Tour: Weiter bei den Klassen "Liefer-Kartei" und "Lieferschein"

Zurück zur 2. Änderung an den Klassen

Zurück zur 3. Änderung an den Beziehungen



 
 

Festlegung der Attribute und Operationen der Klassen

Die Attribute und Operationen der Klassen wurden im Wechselspiel mit den Sequenzdiagrammen festgelegt und weiter verfeinert. Wir begannen mit einem Satz von Attributen und Operationen für die einzelnen Klassen, den wir anhand der Anwendungsfälle ermittelt hatten, zeichneten damit die ersten Entwürfe der Sequenzdiagramme, erkannten dabei Defizite in unseren bisherigen Attributen und Operationen, nahmen die notwendigen Veränderungen vor, zeichneten weitere Entwürfe von Sequenzdiagrammen, erkannten weitere Defizite, nahmen weitere Veränderungen vor usw. Das Ganze lief also als inkrementeller Prozeß ab, an dessen Ende die Attribute und Operationen der einzelnen Klassen standen, wie sie in der Dokumentation des Beispielprojekts zu finden sind. Insgesamt waren mehr Änderungen bzw. Erweiterungen bei den Operationen als bei den Attributen erforderlich, was auf der einen Seite deutlich macht, daß die Beschreibungen der Anwendungsfälle allein die Abläufe im System nicht völlig transparent machen können und auf der anderen Seite die Bedeutung der Sequenzdiagramme für eben diese Aufgabe unterstreicht.

Im folgenden soll die Evolution der Klasseninterna beispielhaft für die Klassen  "Produkt", "Liefer-Kartei" und "Lieferschein" beschrieben und dabei die Wechselwirkung zwischen Klassenmodell und Sequenzdiagrammen aufgezeigt werden. Die genaue Semantik der einzelnen Attribute und Operationen kann der Dokumentation des Beispielprojekts entnommen werden. Die Änderungen, die sich von Entwurf zu Entwurf ergeben haben, sind rot gekennzeichnet. Wo eine Operation wegfiel, wurde sie in der Ausgangsabbildung durchgestrichen dargestellt.
  

1. Beispiel zur Klasse "Produkt":

Abbildung 7a zeigt die Interna der Klasse "Produkt", bevor wir an die Entwicklung der Sequenzdiagramme gingen. 
Abbildung 7a: Interna von "Produkt" (1)
 

Guided Tour: Weiter bei 1. Änderung der Klassen 

1. Änderung der Klasse "Produkt"

Bei der Erstellung des ersten Sequenzdiagramm-Entwurfs zum Anwendungsfall "Bestellung bearbeiten" stellten wir fest, daß die Klasse "Produkt" zwei weitere Operationen "akt_best_korrigieren" und "vormerken" benötigt, um den aktuellen Lagerbestand des Produkts nach unten (oder oben) korrigieren bzw. eine bestimmte Anzahl von Mengeneinheiten dieses Produkts zur Nachbestellung vormerken zu können. Die Operation "min_max_best_definieren" kam hinzu, um den Anwendungsfall "Maximalen und minimalen Lagerbestand definieren" abzudecken. Das neue Attribut "lnr" enthält die Nummer des Lieferanten für das Produkt. Es wird im Sequenzdiagramm zu "Fehlbestände nachbestellen"  zur Identifizierung des Lieferanten benötigt, an den die Nachbestellung für das Produkt gerichtet ist. (Dabei gilt die Annahme, daß jedes Produkt von genau einem Lieferant geliefert wird.) Das Ergebnis dieser Änderungen ist in Abbildung 7b dargestellt. 
Abbildung 7b: Interna von "Produkt" (2)


Guided Tour: Weiter beim Sequenzdiagramm "Fehlbestände nachbestellen" 

2. Änderung der Klasse "Produkt"

Für das Sequenzdiagramm zum Anwendungsfall "Wareneingang bearbeiten" bekam die Operation "wareneingang_bearbeiten" einen Parameter "eingetr_menge", in dem die eingetroffene Warenmenge für das Produkt angegeben wird. Außerdem wurde für das Sequenzdiagramm zu "Fehlbestände nachbestellen" eine weitere Operation namens "nachbestellen" erforderlich, die den Nachbestellungsvorgang für das Produkt durchführt (vgl. Abbildung 7c). 
 
Abbildung 7c: Interna von "Produkt" (3)
 
Guided Tour: Weiter bei den Zustandsdiagrammen 
  
 

2. Beispiel zu den Klassen "Liefer-Kartei" und "Lieferschein":

Die Integration der neuen Klasse "Lieferschein" in das Klassenmodell erforderte zunächst Änderungen an den Attributen bzw. Operationen der Klasse "Liefer-Kartei". Als neues Attribut kam eine Liste hinzu, die die Lieferscheinnummern ("lsnr") der erstellten Lieferscheine enthält. Zusätzlich zur bereits vorhandenen Operation "lieferscheine_erstellen" wurden zwei Hilfsoperationen "lieferscheine_zuordnen" und "lieferscheine_drucken" definiert, die während der Abarbeitung von "lieferscheine_erstellen" die zuvor vorbereiteten Lieferscheine durch die Lieferwagennummer ("lwnr") vervollständigen bzw. die vollständigen Lieferscheine ausdrucken (vgl. Abbildung 8a). 
 
 
 Abbildung 8a: Interna von "Liefer-Kartei" und "Lieferschein", (1)

Guided Tour: Weiter bei der 1. Änderung des Sequenzdiagramms "Lieferschein erstellen" 

1. Änderung der Klassen "Liefer-Kartei" und "Lieferschein":

Für den zweiten Entwurf des Sequenzdiagramms zum Anwendungsfall "Lieferscheine erstellen" wurde allerdings die Operation "lieferscheine_drucken" aus der Klasse "Liefer-Kartei" entfernt und dafür die Klasse "Lieferschein" um die Operation "ausdrucken" erweitert, da es sich dabei um eine Funktionalität handelt, die semantisch eher zu "Lieferschein" als zu "Liefer-Kartei" gehört. Damit sehen die Interna der beiden Klassen "Liefer-Kartei" und "Lieferschein" so aus, wie in Abbildung 8b dargestellt. 
 
Abbildung 8b: Interna von "Liefer-Kartei" und "Lieferschein", (2)

Guided Tour: Weiter bei der 1. Änderungen des Sequenzdiagramms "Wareneingang bearbeiten": 

2. Änderung der Klassen "Liefer-Kartei" und "Lieferschein":

In der endgültigen Fassung des Sequenzdiagramm zu "Lieferscheine erstellen" erhielt die "neu"-Operation der Klasse "Lieferschein" noch die Nummer ("lsnr") des neu erzeugten Lieferscheins als Rückgabewert, um der Klasse "Liefer-Kartei" diese Nummer für ihre "lieferscheine"-Liste mitzuteilen. Damit hatte die Klasse "Lieferschein" schließlich das in Abbildung 8c dargestellte Aussehen. 
 
 
Abbildung 8c: Interna von "Lieferschein"
(endgültige Fassung)
 
Guided Tour: Weiter bei der 4. Änderung des Sequenzdiagramms "Wareneingang bearbeiten"

Hintergrundinformationen

Hinweise zur Erstellung

Einordnung in das Gesamtbild der UML


Buch: Weiter bei den Sequenzdiagrammen

Buch: Zurück zu den Anwendungsfällen