PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : UML: Komposition im Klassendiagramm


thorben123
2011-07-02, 12:24:14
Guten Tag :)

Man sollte ja meinen, die Assoziationen im Klassendiagramm aus UML seien keine allzu große Sache. Ich bringe es dennoch fertig, damit arge Probleme zu haben.

Ich fange einfach mal an...

Bei der Komposition treffen folgende 3 Punkte immer zu, oder? (Bitte kommentieren, das ist quasi meine erste Frage)
- es handelt sich um eine Teile-Ganzes Beziehung
- das Teil ist existenzabhängig vom Ganzen
- das Ganze ist der alleinige Besitzer des Teils

Die Tatsache, dass man damit 3 Kriterien auf einmal ausdrücken will, möchte mir noch nicht so recht in den Kopf.

Sehe ich das richtig, dass man damit NICHT ausdrücken kann, dass das ganze auch von seinen Teilen existenzabhängig ist?

- ein Raum gibt es ohne Gebäude nicht, aber ohne einen Raum hat man quasi auch kein Gebäude

- die Nodes einer Liste (Datenstruktur) gibt es ohne die Liste selbst nicht, aber eine Liste gibt es ohne Nodes genauso wenig (von der leeren Liste mal abgesehen).

Solche Dinge kann man bei der Komposition in UML nicht erkennen, oder?

Wobei.. ich realisiere gerade, dass ein Ganzes immer von seinen Teilen abhängig ist, wird das dann eben impliziert und es interessiert nur die andere Richtung?

Vielleicht kann das jemand so geschickt formulieren, dass es klick macht ;)

Vielen Dank!

Ihr seht schon

throben123
2011-07-02, 12:33:01
okay, nochmal so ein Beispiel: schaut euch folgendes Diagramm an

http://s1.directupload.net/images/110702/mtg678nx.png


Laut diesem sind Seitenteil und Boden eines Regal von diesem Existenzabhängigkeit. Aber ist es nicht viel mehr so, dass diese Teile auch alleine existieren können und das Regal von diesen abhängig ist?

Trap
2011-07-02, 13:07:00
UML ist keine Programmiersprache und auch kein Werkzeug zur vollständigen formalen Spezifikation. Außerdem ist UML zur Beschreibung objektorientierter Software, nicht zur Beschreibung der Realität.

In OO-Software ist die Komposition wie von UML definiert eine häufig genutzte Relation (aber natürlich nicht die einzige). In der Realität ist sie so gut wie nie zutreffend. Wenn man die Definition aus Wikipedia (http://en.wikipedia.org/wiki/Class_diagram#Composition) nimmt, bedeutet es auf dein Beispiel angewendet, dass Seitenteile und Böden "zerstört werden", wenn das Regal "zerstört wird".

Nakai
2011-07-02, 15:14:12
Komposition: Objekt ist Teil des Objekts(kann bei C++ über STL oder Felder gelöst werden). Ergo kann nicht ohne Oberobjekt existieren.

Assoziation: Oberobjekt hat nur einen Verweis auf das Unterobjekt, ergo kann ohne das Oberobjekt existieren.

UML ist keine Programmiersprache und auch kein Werkzeug zur vollständigen formalen Spezifikation. Außerdem ist UML zur Beschreibung objektorientierter Software, nicht zur Beschreibung der Realität.


Das ist richtig, wird aber in den nächsten Jahren dramatisch in diese Richtung gehen. Die richtige Programmierung wird immer unnötiger.

UML ist sowieso der größte Mist. Es ist einfach Ansichtssache wie man etwas implementiert.

huha
2011-07-02, 16:52:02
Erstmal grundlegend: Software richtet sich nicht nach der Natur, sondern nach technischen Gegebenheiten und Notwendigkeiten. Man versucht natürlich, eine möglichst sinnvolle Abbildung der Natur hinzukriegen, das ist aber letztendlich der konkreten Anwendung und deren Gegebenheiten untergeordnet. Nur weil es möglich ist, will man das Modell nicht unnötig aufblähen, sondern eher schön kompakt halten; auch sollte man sich überlegen, welche Daten man von wo aus wie oft benötigt, damit die Performance nicht ins Bodenlose sinkt.

Ich hab jetzt von UML keine allzu große Ahnung (beschäftige mich eher mit EMF/Ecore, das ist aber wohl eine vereinfachte Untermenge von UML), aber ich denke mal, daß die grundlegenden Prinzipien oft genug ähnlich sind. Es gibt da übrigens auch unterschiedliche Meinungen und Auffassungen der Konzepte und meine ist sicher auch nicht die einzig wahre. ;)


- die Nodes einer Liste (Datenstruktur) gibt es ohne die Liste selbst nicht, aber eine Liste gibt es ohne Nodes genauso wenig (von der leeren Liste mal abgesehen).

Die leere Liste ist eben auch eine Liste!
Letztendlich geht's ja auch darum, eine Datenstruktur zu bauen, auf der dann Operationen leicht möglich sind, die man sonst aufwendig erstellen müßte. Bei einer verketteten Liste kann das zum Beispiel das Auslesen oder Einfügen eines Elements an einer bestimmten Stelle sein. Das will man im Prinzip nicht in die Implementierungsdetails der Nodes packen, da das nicht allzu viel damit zu tun hat, sondern nur mit der Datenstruktur, in der sich diese befinden.

Im Prinzip gibt's zwei (gebräuchliche) Möglichkeiten, Beziehungen zwischen Objekten darzustellen: Referenzen und Containments (jeder nennt die anders, das hier folgt nun meiner sicher von EMF inspirierten Nomenklatur, weil das alles so verwirrend ist; im Prinzip ist es aber für das Verständnis nicht so wichtig):
Eine Referenz ist einfach nur ein Verweis auf ein Objekt, also beim Beispiel einer einfach verketteten Liste beispielsweise der "next"-Node. Das sind die ganz normalen Kanten. ;)
Ein Containment ist erstmal auch nur ein Verweis auf ein Objekt, besagt aber noch zusätzlich, daß das Objekt, vom dem die Containment-Beziehung ausgeht, das andere Objekt in irgendeiner Form "enthält." Ein klassisches Beispiel hierfür sind die Nodes einer verketteten Liste. Das sind die komischen Kanten mit den Rauten.


Doch wo ist da jetzt konkret der Unterschied? Normale Referenzen kann man schließlich im Prinzip auch auf Objekte setzen, zu denen man keine Containment-Kante besitzt. Im Prinzip ist der Unterschied kein "natürlicher" Unterschied, sondern ein technischer: Irgendwo muß man die Datenstrukturen haben, die die Objekte speichern. Das will man im Prinzip einigermaßen effizient machen und nicht alles global in einer riesigen Struktur speichern, weil dann die Suche und sequentielle Verarbeitung schwierig wird. Außerdem erleichtern bzw. ermöglichen diese Strukturen auch die Serialisierung, falls man die Objekte irgendwo dauerhaft hinspeichern will.

In der Natur gibt es keine Entsprechung der Containment-Kanten, weil sie einfach nur technisch sind. Gegenstände in der Natur sind einfach "da" und müssen nicht erst noch geordnet werden. Man kann natürlich komische Beispiele konstruieren, die das Konzept etwas verdeutlichen, aber im Prinzip kann man auch ohne Containment-Kanten modellieren (sollte man allerdings nicht, da es, wie gesagt, technische Gründe hat, warum man die benutzt).

Mal ein konkretes Beispiel, worum es geht:
Wir bauen uns eine einfach verkettete Liste. Die besteht im Prinzip nur aus der Liste und entsprechenden Nodes. Die Liste hat einen ersten Node, der traditionell als "head" bezeichnet wird. Jeder Node hat einen Verweis auf den nächsten Node ("next"). Das sieht also (in EMF) so aus (in UML gibt's AFAIK keine gerichteten Kanten, in EMF schon--ist halt implementierungsnäher, macht aber hier keinen großen Unterschied):
https://www.forum-3dcenter.org/vbulletin/attachment.php?attachmentid=40168
Die Liste enthält hier alle Nodes, die ihr zugeordnet sind ("nodes"-Kante), was einige Vorteile in der Implementierung hat. Man könnte es aber natürlich auch irgendwie anders machen, z.B. nur eine Containment-Referenz auf head, "nodes" ganz rausschmeißen und bei den Nodes "next" auch als Containment-Referenz gestalten (würde man aber nicht, weil dann u.a. Löschen von Werten aus der Liste ziemlich aufwendig wird).

Man kann jetzt nicht sagen, das ist so oder so oder so, zumal bei modernen Programmiersprachen der Speicher üblicherweise sowieso verwaltet wird, es einen also auch nicht mehr allzu sehr interessiert, wo was konkret im Speicher liegt. Daher ist das "enthalten" doch mit sehr großer Vorsicht zu genießen, da es nichts über konkrete Datenkapselung aussagt. Man kann bequem eine (Referenz-)Kante von einer völlig anderen Klasse A zu einer Klasse B ziehen, die woanders (in Klasse C) enthalten ist. Ich finde es da einfacher, diese Betrachtung nicht bezüglich der Konzepte durchzuführen, sondern zu schauen, welche Auswirkungen das konkret technisch bedeutet und das entsprechend so zu handhaben.
Containment-Kanten sind insbesondere dann extrem wichtig, wenn es darum geht, aus dem Diagramm Code-Grundgerüste erzeugen zu lassen und die daraus entstandenen Daten dann irgendwie serialisiert werden müssen; dann muß jedes Datum natürlich irgendwo enthalten sein, weil sonst die Serialisierung nicht klappt.

okay, nochmal so ein Beispiel: schaut euch folgendes Diagramm an

http://s1.directupload.net/images/110702/mtg678nx.png


Laut diesem sind Seitenteil und Boden eines Regal von diesem Existenzabhängigkeit. Aber ist es nicht viel mehr so, dass diese Teile auch alleine existieren können und das Regal von diesen abhängig ist?

Das kommt jetzt ganz darauf an, was du noch modellieren willst. Daher ist der Vergleich mit der Natur auch immer blöd, weil er einfach zu nichts führt. Ich habe keine Ahnung von UML und weiß daher nicht, was man da alles Seltsames spezifizieren kann, aber dein Diagramm beschreibt aktuell, daß ein Regal zwei Seitenteile und mindestens drei Böden besitzt. Und zwar (und das sagt diese containment-Referenz!) nicht irgendwelche, sondern ganz konkrete. Ohne Regal gibt's die Böden und Seitenteile auch nicht, weil du keine Möglichkeit hast, die irgendwo zu speichern, um sie woanders referenzieren zu können. Das Regal übernimmt gewissermaßen die "Verwaltung" der Datenstruktur, in der die Seitenteile und Böden gespeichert sind.
Dein Modell ist ziemlich klein, daher ist das alles kein Problem. (Kleine Anmerkung: Zur Serialisierung würde man nun noch dafür sorgen, daß jede Klasse irgendwo enthalten ist; also Regal z.B. in "Lager", Bestellung und Lager in "Firma" oder irgendwie sowas.)
Dein Modell modelliert nun gewissermaßen bereits abgepackte Kartons mit fertigen Regalen drin. Dort existieren Seitenteile und Böden natürlich nur im Zusammenhang mit ihrem konkreten Regal.
Wenn du lieber modellieren willst, daß im Prinzip in einem Lager eine Menge Seitenteile und Böden rumliegen und sich der Kunde dann sein individuelles Regal zusammenstellen kann, dann wäre folgendes geschickter:
- Führe eine Klasse "Lager" ein, die den Stand an Böden, Seitenteilen [und bereits fertig zusammengestellten Regalen (jetzt konkret für das Modell nicht wichtig, macht man aber trotzdem so, weil man das später sowieso serialisieren muß und sich dann um ein Containment zu kümmern hat)] verwaltet. Diese besitzt Containment-Kanten auf Seitenteil und Boden [und Regal].
- Ersetze die Seitenteil- und Boden-Containment-Referenzen von Regal durch normale Referenzen. Die Multiplizitäten bleiben bestehen.

Zum Vergleich nochmal beide Diagramme, jeweils in EMF nachgebaut:
Deine Version:
https://www.forum-3dcenter.org/vbulletin/attachment.php?attachmentid=40169
Andere Version:
https://www.forum-3dcenter.org/vbulletin/attachment.php?attachmentid=40170

Was konkret du da wie brauchst, hängt immer davon ab, wie deine Anwendung aussieht. Jeder Zugriff kostet Zeit und wenn du deine Datenstruktur so aufbaust, daß selbst bei einfachsten Operationen in deiner Anwendung ewig im Modell rumgesucht werden muß, dann kann das Modell noch so gut sein, die Software dazu wird einfach lahm. ;)
Also niemals "einfach so" modellieren, sondern immer als Gedanken haben, was man damit machen soll und wie die Abläufe sein werden.


Das ist richtig, wird aber in den nächsten Jahren dramatisch in diese Richtung gehen. Die richtige Programmierung wird immer unnötiger.
Richtige Programmierung ist weiterhin notwendig. Es reicht halt einfach nicht, jemandem ein UML-Diagramm hinzuklatschen, "mach mal" zu sagen und dann zu erwarten, daß genau das dabei herauskommt, was man sich vorstellt.
Automatische Codegenerierung ist hilfreich, wenn es darum geht, ein Code-Gerüst zu bauen, das einem die Schreibarbeit abnimmt, aber die knackigen Teile muß man selbstverständlich noch von Hand übernehmen.

UML ist sowieso der größte Mist. Es ist einfach Ansichtssache wie man etwas implementiert.
Die Modellierungssprachen dienen auch nicht dazu, einen Sachverhalt zu modellieren, sondern zur Modellierung einer Anwendung. Da weiß man üblicherweise, wie man es braucht und modelliert dementsprechend. Wie es dann implementiert wird, kommt ganz darauf an, welche Prioritäten man setzt, aber die Modellierungssprachen geben einem da schon Hinweise.

Für die Implementierung in Sprachen, die keine Pointer bzw. Referenzen kennen (oder die Sprachen, die nur Pointer und Referenzen kennen), sind die Containment-Kanten übrigens solange äquivalent zu normalen Referenzen, bis man versucht, die Daten irgendwie geordnet auf die Festplatte zu bringen.
Wenn man das selber bauen will, weiß, was man tut und alles von Hand zusammenhauen, dann würde man die Containment-Kante von Regal zu Seitenteil garantiert als Array mit 2 Zellen implementieren, die Referenz-Kante in der anderen Version übrigens genauso. ;)

-huha

Tiamat
2011-07-02, 17:15:19
Das ist kein Problem.
Assoziationen:
Wenn eine Klasse A ein Object der Klasse B einfach nur verwendet, ohne die Klasse zu aggregieren.

Aggregation:
Ein Klasse A verwendet ein Object der Klasse B und aggregiert es in Klasse A. Klasse B ist aber auch von anderen Klassen instanzierbar.

Komposition:
Eine Klasse A beinhaltet sowohl Klassendefinition von B als auch min. eine Objektreferenz von B und benutzt diese auch. Die Klasse B ist nicht frei instanzierbar, häufig weil die Existenz von B ohne A keinen Sinn macht.

Deine Frage:
Eigentlich nur 2 Punkte, der 3. ist redundant.
1.Man möchte ein Objekt eines anderen Klassentyps B aggregieren
2.Die Klassendefinition von B ist zusätzlich in A untergebracht, daraus folgt implizit dein 3. Punkt

Bsp:

class Bankkonto {

private class Account{ .. }

}

Damit stellt man einfach sicher, dass kein anderer Dev hergeht und ein Objekt vom Typ Account instanziert, dass dann ohne ein Konto daherkommt. Weil ein Account vom Konto eigene Eigenschaften hat und sich für sich andere Zweck schlecht gebrauchen(missbrauchen) lässt. Beispiele gibt´s viele..

EGG-Beater
2011-07-02, 18:43:04
Ach UML, jeder definiert es sich so, wie er es gerade braucht. In manchen UML-Büchern wird geschrieben, dass man die Komposition gar nicht verwenden soll. Andere schreiben, die Aggregation ist zu vermeiden. (natürlich ist das jeweils andere dann immer das Mittel der Wahl gewesen)

Ich fürchte, du wirst keine eindeutige, exakte Definition dafür bekommen. Zumindest keine, der jeder zustimmen würde. Das ist auch immer eines der "schönsten" Details jeder Softwareengineering-Vorlesung ... wenn man merkt, dass andere das ganz anders sehen.

Tiamat
2011-07-03, 08:44:39
Achwas , du verwechselst da was. Es gibt Software-Enginering Bücher, die mit den Begriffen Aggregation und Komposition wild umherschmeißen, aber die Definition ist durchaus eindeutig.



An association may represent a composite aggregation (i.e., a whole/part relationship). Only binary associations can be aggregations. Composite aggregation is a strong form of aggregation that requires a part instance be included in at most one composite at a time. If a composite is deleted, all of its parts are normally deleted with it. Note that a part can (where allowed) be removed from a composite before the composite is deleted, and thus not be deleted as part of the composite. Compositions define transitive asymmetric relationships—their links form a directed, acyclic graph. Composition is represented by the isComposite attribute on the part end of the association being set to true.

UML Dokument der OMG-Group (http://www.omg.org/spec/UML/2.0/Infrastructure/PDF/)

Da stehen die zwei wesentlichen Eigenschaften, die ich erwähnt habe, drin.

Nakai
2011-07-03, 14:05:36
Richtige Programmierung ist weiterhin notwendig. Es reicht halt einfach nicht, jemandem ein UML-Diagramm hinzuklatschen, "mach mal" zu sagen und dann zu erwarten, daß genau das dabei herauskommt, was man sich vorstellt.
Automatische Codegenerierung ist hilfreich, wenn es darum geht, ein Code-Gerüst zu bauen, das einem die Schreibarbeit abnimmt, aber die knackigen Teile muß man selbstverständlich noch von Hand übernehmen.


Natürlich, genauso wie Modellierungstools noch per Hand geschrieben werden. Wir sind einfach mittlerweile an einem Punkt angekommen, wo Modellierung Zeit spart und schon sehr effiziente Strukturen bereitstellen kann. Codewiederverwertung und Modulisierung ist mittlerweile auch schon gang und gäbe. Falls neue Strukturen und Code notwendig sind, werden diese auch noch von Hand programmiert und optimiert.


mfg