Softwaretechnik, 04. UML Klassendiagramme in der Systemanalyse

Material für die Softwaretechnik Vorlesung, Bernhard Rumpe

UML Klassendiagramme in der Systemanalyse und zur Generierung

Diese Erklärung ist gedacht für Studierende als Einführung in die Vorlesung Softwaretechnik, die

  1. verstehen wollen welche Grundkonzepte die UML Klassendiagramme zur Verfügung stellen, und
  2. wie Klassendiagramme intellektueller Notation dargestellt werden können, um dann als Eingabe für das MontiGem Tooling genutzt zu werden, das daraus einen ersten Prototypen für ein Business Informationssystem erstellt.

Diese Erklärung beinhaltet einige aber nicht alle Abschnitte des Kapitel 4 der Softwaretechnik Vorlesung. Eine vertiefende und vollständigere Einführung zu UML Klassendiagrammen findet sich in den UML-Büchern, speziell Buch 1, Kapitel 2.

  • … und viele weitere Anwendungsmöglichkeiten, zum Beispiel als Referenzmodelle, als Architekturbeschreibungen, als Datenmodelle oder als Konzeptmodelle zur Beschreibung der relevanten Konzepte eines zu implementierenden Systems.
  • Die wesentlichen Merkmale der Objektorientierung: Klassen, Objekte als deren Instanzen, Vererbung, Polymorphie.
  • Ein Klassendiagramm visualisiert eine Sammlung von Klassen, sowie einige später gezeigte Konzepte, wie die Vererbung und Assoziationen zwischen den Klassen.

  • Ein Klassendiagramm zeigt damit sowohl die Beziehungen zwischen Klassen, als auch wie hier zu sehen die Interna einzelner Klassen, hier eine Klasse mit vier Attributen und fünf Methoden, deren Typisierung und Sichtbarkeit.

  • Abstrakte Klassen, Interfaces und instantiierbare (normale) Klassen sowie hier nicht gezeigte Enum-Klassen gibt es ganz analog zu Java.
  • Anders als in Java ist Mehrfachvererbung (siehe HiWi) möglich. Sollte diese zum Einsatz kommen, so ist in einer späteren Phase zu überlegen, wie diese in einer Programmiersprache ohne Mehrfachvererbung zu realisieren ist. Sollten Sie eine HiWi-Stelle suchen: Melden Sie sich bei uns: Website of the SE

  • Bemerkung: Dafür gibt es Standardstrategien, denn es gibt
    immer Strategien ein in der Modellierung verwendetes aber in einer Implementierung fehlendes Konstrukt adäquat zu repräsentieren. Die einzige Implementierungsbarriere ist fehlende Ausführbarkeit.

  • Assoziationen lassen sich in einem Klassendiagramm sehr gut verwenden, um die Beziehungen zwischen den Objekten einer Klasse einzusetzen.

  • In objektorientierter Programmierung ist das Konzept “Assoziation” ebenfalls nicht direkt vorhanden und deshalb müssen Assoziationen durch (später diskutierte) ggf. komplexere Konstrukte ersetzt werden.

  • Es gibt normale Assoziationen und Komposition sowie qualifizierte Assoziationen (siehe unten).

  • Assoziationen können unter anderem Assoziationsnamen sowie auf beiden Seiten Rollennamen, Kardinalitäten und einen Pfeil tragen.

  • Der Pfeil klärt, ob in diese Richtung navigiert werden kann (zum Beispiel kennt die Person ihre Messages).

  • Eine Assoziation beschreibt grundsätzlich und immer die Beziehung zwischen Objekten der Klassen auf beiden Seiten. Die Objekte sind dann durch entsprechende Links miteinander verbunden, die durch die Kardinalität begrenzt werden.

  • Assoziationen und Vererbung haben eine grundlegend unterschiedliche Aufgabe: Vererbung verbindet Klassen, Assoziationen verbinden ihre Objekte durch Links. Eine Subklasse wird deshalb einzeln instantiiert (ein Objekt), eine Assoziation bzw. ihr Link verbindet zwei Objekte.

  • Eine Assoziation kann zweimal dieselbe Klasse verbinden, was eine rekursive Datenstruktur erlaubt, und zum Beispiel Listen, Bäume, oder allgemeine Graphen darzustellen erlaubt. Siehe auch Entwurfsmuster Composite.

  • Komplexere Formen von Assoziationen, die zum Beispiel drei verschiedene Klassen beinhalten sind in der UML möglich, aber wegen der hohen Komplexität eher zu vermeiden und hier auch nicht weiter diskutiert.

  • Wir empfehlen die Aggregation nicht zu nutzen, weil die Semantik nicht einheitlich geregelt bzw. im Detail dann unklar ist.
  • Komposition tätigt eine scharfe und deshalb auch meist hilfreiche aber nicht überall einsetzbare Aussage über den kombinierten Lebenszyklus der komponierten Objekte. Wenn Reifen am Auto ausgetauscht werden können, dann ist es keine dauerhafte Komposition.
  • Für eine effiziente Navigation, gerade bei unbegrenzter Kardinalität (*) und gegebenenfalls großen Mengen an Objekten auf der anderen Seite ist ein Qualifikator sehr hilfreich.

  • Ein Qualifikator wird auf einer Seite eine Assoziation angegeben und kann dann genutzt werden um direkt das richtige Objekt zu identifizieren.

  • Wird ein Datentyp, etwa String oder int eingesetzt, oder ein Attributname der gegenüberliegenden Klasse (auctionIdent), so werden Werte dieses Typs als Identifikatoren verwendet. Wer hier an eine Realisierung mit einer HashMap denkt liegt meist richtig.

  • Ist {ordered} angegeben, so kann eine Implementierung als Liste ziemlich sicher angenommen werden. In diesem Fall ist das ganze Interval von 1 bis zur Länge der Liste als Index verwendbar.

  • Ist der Qualifikator ein Attribut der gegenüberliegenden Klasse, so ist eine Besonderheit zu beachten: da das identifizierte Objekt seinen Identifikator (also seinen eigenen Attributwert) kennt, ist bei allen Links der Qualifikator-Wert identisch. Beispiel: Alle öffentliche Telefonbücher haben "Gerd Müller" mit derselben Nummer.
  • Demgegenüber ist in einem privaten Telefonbuch "Gerd Müller" durchaus unter verschiedenen Namen eintragbar - und kennt die dort eingetragenen Namen nicht.

  • Was machen wir nun mit Klassendiagrammen, wenn wir sie in der Analyse entwickelt, im Systementwurf präzisiert und für Software zugeschnitten haben? Entweder händisch oder durch Werkzeuge unterstützt Code daraus ableiten. Am aller sinnvollsten ist die vollautomatische Codegenerierung, die in diesen Abschnitt adressiert wird.
  • Dieses Bild zeigt die klassische Übersetzung einer Klasse aus dem Klassendiagramm in Java-Code sowie auch in C++-Code. Wenn man beides benötigt hat man schon einen gewissen Vorteil, weil dadurch nur noch eine redundanzfreie Informationsquelle für die Klasse Auction existiert. Und wir wissen ja: Redundanz ist immer schwierig, wenn man revolutionäre Software anpasst, weil es zu Inkonsistenz führt und dadurch viel unangenehme Prüfungsaufgaben mit sich bringt.
  • Richtig hilfreich ist ein Generator, wenn man weitere Generierungen damit vornimmt. Und dafür gibt es sehr viele Optionen:

  • Zum Beispiel Serialisierungsfunktionalität: der Transport eines Objekts von einem zum nächsten Prozess, zwischen Server und Client ist oft mit sehr viel Code verbunden.

  • Zum Beispiel die Persistierung in einer Datenbank, das Wiederfinden, etc. lässt sich generieren.

  • Ein noch überschaubares Beispiel verbesserter Codegenerierung. Das sind aber dennoch bereits Einsparungen.
  • Spannend wird es auch bei Assoziationen, die im Klassendiagramm, aber nicht in Java oder C++ zur Verfügung stehen. Im Beispiel wird eine qualifizierte Assoziation durch eine Map realisiert und gleichzeitig eine größere Anzahl an darauf operierenden Funktionen zur Verfügung gestellt.

  • Dieses Verfahren ist übrigens besonders hilfreich, wenn eine Assoziation in beide Richtungen navigiertwerden kann und aus Effizienzgründen eine redundante Realisierung auf beiden Seiten der Objekte gewünscht ist. Da kann die Konsistenzsicherung gleich mit rein generiert werden, indem man wie hier das benutzte Attribut privat macht und die generierten Funktionen entsprechende Konsistenzsicherung vornehmen. Unser unten besprochener Generator MontiGem macht dies.

  • Vermeidung lästiger Programmieraufgaben ist einer der wesentlichen Gründe einen Codegenerator einzusetzen: er hilft uns schneller, effizienter und qualitativ besser zu sein, aber insbesondere langweilige Tätigkeiten beim Programmieren zu vermeiden.
  • Natürlich kann mit einer Strukturdefinition, wie sie ein Klassendiagramm bietet kein komplettes System generiert werden, aber ein lauffähiges System mit Grundfunktionalität schon. Und wenn die Generierung so geschickt gemacht ist, wie die des MontiGem Generators, dann lässt sich der generierte Code auf vielfältige Weise durch handgeschriebene Teile oder wie später diskutiert auch durch Anpassung des Generators selbst systematisch ergänzen.

  • Wir diskutieren die Grundprinzipien der Generierung in Kapitel 9, stellen aber für die Übungen schon mal den MontiGem Generator zur Verfügung.

  • Der Generator bringt uns in drei Schritten vom Klassendiagramm zum laufenden System. Und wir ignorieren in dieser Vorlesung, dass auch handgeschriebener Code, GUI Modelle, Verhaltensbeschreibungen und ähnliches mehr noch möglich sind.

  • Mehr Details über die konkrete Nutzung im Übungsbetrieb.

  • Wollen Sie ihr eigenes Facebook aufbauen? Anbei ein Referenzmodell dazu. Mit dem MontiGem Generator ist Facebook light schon fast fertig.

And now let us switch to English for a while.

  • The textual CD4A language is designed in the spirit of Java, using similar keywords, types, delimiters for statements “;” and blocks “{“, “}”.

  • The body of a class diagram consists of a list of classes, interfaces, enumerations, associations, and compositions. The order is irrelevant; it is especially allowed to reference later classes early on. We suggest to either put all classes at the top and the associations later or to group a class and related associations into topical sections.

  • Please note that CD4A starts with the keyword classdiagram, while some tools also accept keyword umlp as the starting point.

  • The SocNet.cd example used here can also be directly examined.

  • More examples can be found in the CD4Analysis project.

  • To repeat, the bodies of classes are very similar to the classes in the Java language, because the syntax is inspired by Java. The lines 5–8 could directly come from a Java class, also no method or constructor is defined.

  • Neither classes nor interfaces require bodies, e.g., when you don’t know anything about them yet. An empty body can be denoted using a ;.

  • Associations are not present in Java, yet exhibit a complex set of information.

  • The text form reads from left to right almost identical to the graphical depiction above: Only the name of the association was moved to the left, and the middle contains the iconic forms of the arrow <->, ->, etc.

  • Note that we use underspecification as a significant construct within modeling languages, meaning that if certain information is not given, nothing is said. I.e. many pieces of information can be refined, for example -- just tells us that we don’t know in which directions navigation might be available.

  • Role names like (organizer) can also be attached on both sides.

  • Qualifiers like [[profileName]] resemble the box that they are embedded in. CD4A allows two kinds of qualifiers, either the name of an attribute of the other side (in this case class Person) or a data type resembling the key values of the qualified association. Semantics is defined in UML/P books by Bernhard Rumpe.

  • Compositions follow the same syntax as associations, just with the keyword composition to indicate their compositional semantics.
  • Enumerations are defined with a set of constants as their body.

  • Enumeration constants are visible inside the enumeration and can be used outside only through qualified names (like RelationType.FRIEND) or an explicit import statement.

An import statement similar to Java’s import is available. It allows to import foreign types, e.g. defined as Java classes, like Date or Account, but also allows to refer to other kinds of models that define datatypes, such as other class diagrams.

  • This is a core feature of allowing to compose class diagrams that build on each other but are independently developed by different teams of a project or taken from a library.

  • Please note this restriction: when generating from a bidirectional association, the class on the opposite side must be generatable or similarly genrated too. (I.e. association Person <-> Date will not work, because of the external class Date.)

  • The mechanism to make other models and libraries known to the compiler is described in the tool calling (see e.g. --path).

CD4A generally follows the requirements engineering guideline, which states that during the requirements elicitation process generic classes are not really needed and not also not introduced. However, it is sometimes convenient to rely on the most relevant basic generics directly, which are the four Optional< . >, Set< . >, List< . >, and Map< . , . >. But please note that these four directly correspond to associations that can describe the very same properties, but the CD4A generator for associations also produce lots of access and manipulation methods with integrated data consistency checking and can be used bidirectionally.

  • CD4A allows derived attributes (and associations), marked by /. It is notable that this indicates a dependency of this attribute from other attributes, which, however, there is not made explicit in the model itself.

  • The package name first of all describes in which directory the model of the class diagram can be found, but by default also carries over to the packages where the modeled (and finally generated) classes reside. Please note: an explicit statement, which is not shown here, can attach individual packages to each class.

  • Like in Java, the import statement is required when external datatypes, classes, etc. are used. Such an import may refer to another model or in this case to an already existing Java class. A context condition checks whether the used classes actually exist in the local model or in the imports.

  • It is a convention to name enums in UPPERCASE, in CamelCase for classes, interfaces, and enumeration types, and to use uncapped names for attributes.

  • In fact, CD4A applies the same restrictions and capabilities for names as does Java, which means that numbers and the dollar sign $ are allowed within a name and underscore _ in any position.

  • More (sometimes subtle) context conditions apply to give a well-formed model. However, the resulting error message should be detailed enough to explain the problem.

  • As a general guideline, CD4A uses similar naming and visibility conventions as Java does, i.e., enum constants and attributes are visible locally and can be used from outside using their qualification – as described above.

  • Note that this description does not infer how the CD4A model is actually used. During a requirement elicitation activity, such a model is basically used as a communication vehicle to understand the underlying data structure. However, appropriate tools (including the CD4A and MontiGem generators) are able to produce a lot of infrastructure for such a class diagram. This can be used both for prototyping and actual use later on. As indicated, this may include data structures, access functions, transport, communication and storage, and potentially also web representation.

MontiGem

MontiGem ist ein Generator für Informationssysteme, welches auf der UML/P basiert, einer Teilmenge der Modellierungssprache UML mit dem Fokus auf die Programmieranwendung. MontiGem wird eingesetzt, um datenzentrierte Anwendungen bzw. deren wesentliche Kernkomponenten und Infrastruktur auf der Basis von Klassendiagrammen (sowie weiteren Modellierungstechniken) zu erzeugen. Ein Beispiel-Modell sieht z.B. so aus:

umlp Verwaltung {
  class Person {
    int age;
  }

  class Paper {
    List<String> lines;
  }

  association [1] Person -> (owns) Paper [*];
}

MontiGem nutzt eine textuelle Variante der UML/P Klassendiagramme und erlaubt im Vergleich zur oben beschriebenen Form als initiales Keyword umlp (wie im Beispiel gezeigt) synonym zu classdiagram. Analog dazu haben Modellartefakte die Endung .umlp. Weiterhin erlauben import-Statements spezielle Datentypen/ Klassen in das aktuelle Diagramm einzubinden und dort nutzbar zu machen.

Wir werden MontiGem für die Übungsaufgaben benutzen, um damit direktes Feedback für die qualitativ hochwertige Modellierung von Strukturen zu gewinnen. Das Tool kann aus UML/P Klassendiagrammen lauffähige Applikationen generieren, die Sie dann auf Nützlichkeit ihrer Modelle überprüfen können. Konkret haben wir das Tool in Kombination mit dem Gruppen-orientierten Abgabemechanismus über gitlab so eingerichtet, dass eine interaktive Website generiert wird. Wir stellen diese Website für Sie unter passender URL und Zugangsdaten bereit. Bitte bedenken Sie, dass die Website u.A. durch Gitlab CI/CD Pipelines und unsere Server bereitgestellt werden muss. Es kann deswegen zu leichten Verzögerungen bis zum Sichtbarwerden geben.

Die oben genannte Web-Applikation wurde aus der Datei Verwaltung.umlp generiert. Um Änderungen am generierten System vorzunehmen, pushen Sie Änderungen des Modells auf den Default-Branch Ihres Git-Repositories. Die letzte erfolgreiche Pipeline veröffentlicht Ihr generiertes System automatisch.

Wir hoffen hier einen guten Zugang zu den wichtigsten Konzepten der Klassendiagramme als Teil der UML Modellierungssprache gegeben zu haben. Wir haben gezeigt, wie eine textuelle Fassung der Klassendiagramme definiert werden kann, die dann von unserem Werkzeug MontiGem in einen Prototypen eines laufenden Softwarsystems übersetzt wird.

Eine solche Übersetzung liefert eine gute Grundstruktur auf der sich dann ein komplettes System aufbauen lässt. Allerdings ist hier natürlich noch viel zu tun, denn es ist weder das Rechte/Rollen-Konzept festgelegt, noch Algorithmen zur Verarbeitung und Visualisierung der Daten, sowie meist gewünschte spezielle Anzeigeformen definiert. Es gibt allerdings einen Datenbank-basierten Speichermechanismus, grundlegende Anzeige- und Editier-Webseiten, einen kollaborativen Kommunikationsmechanismus und insbesondere für Entwickler interessant: die Möglichkeiten den generierten Code wie ein Framework zu behandeln und applikationsspezifisch anzupassen.

Join our mailing list for updates regarding courses and theses: