Ziel: Computerprogramm in Rahmen eines iterativen OOA/D-Prozesses zu erstellen.
Zunächst fokussiere ich mich darauf, die groben Anforderungen für das System zu ermitteln.
Da es sich um einen iterativen Prozess handelt, wird nicht jedes Anforderungs-Detail genau spezifiziert. Schliesslich ändern die User ihre Anforderungen sowieso.
Use Cases sind nicht OO-spezifisch. Ich benutze seit Jahren Use Cases für die Ermittlung von Anforderungen in reinen Notes-Projekten.
Anwender verfolgen spezifische Business-Ziele. Ein Computersystem soll sie dabei unterstützen. OOA/D besteht aus einem Analyse Teil (das A) und einem Design-Teil (das D). In dem Analyseteil soll erst mal ermittelt werden, „was“ das System leisten soll. Im Design-Teil wird danach gesucht, „wie“ das System die Anforderungen erfüllen soll. Bevor man mit der OO-Analyse überhaupt richtig anfängt benötigt man erstmal eine Analyse der Anforderungen.
Sprachlich treffen in einem Software-Projekt 2 Welten aufeinander. Auf der einen Seite die Entwickler mit ihrer Fachsprache und auf der anderen Seite die Anwender mit ihrer Fachsprache. Der Vorteil von Fachsprachen besteht darin, dass komplexe Sachverhalte effizient ausgedrückt werden können. Der Nachteil ist, dass sie in aller Regel relativ hermetisch sind. D.h. Außenseiter in Bezug auf die jeweiligen Fachsprache verstehen erst mal nur Bahnhof. Die wichtige Quelle für die Anforderungen sind die Anwender. Deshalb soll auch deren Sprache dominieren. Die Entwickler müssen also lernen, sich in der Fachsprache der Anwender einigermassen zurechtzufinden. Als zusätzliches sinnvolles Analyse-Artefakt kann ein Glossar über die Fachsprache erstellt werden. Da hier ein System erstellt wird, dass Entwicklern hilft, Lotus-Script Funktionen zu speichern, katalogisieren und auszutauschen, sprechen hier Anwender und Entwickler die selbe Sprache. Die Anwender sind eben auch Entwickler.
Larman spricht von unterschiedlichen Formaten für Use-Cases. Zunächst kann das brief-informal Format benutzt werden.
Use Case1: Code-Dokument erstellen
Der Anwender wählt die Kategorie, unter dem die neue Funktion gespeichert werden soll oder er erzeugt eine neue Kategorie. Er gibt der Funktion einen Namen, gibt einen Kommentar an, fügt Referenzen auf bestehende Funktionen hinzu, von denen die neue Funktion abhängt, schreibt einen aussagekräftigen Kommentar, fügt den code ein und sendet an das System die Nachricht, dass das neue code-Dokument abgespeichert werden soll. Das System validiert, ob alle notwendigen Eingaben getätigt sind und übergibt den Text des Kommentarfeldes dem Volltextindiexierungsservice und speichert das code-Dokument in einer exterenen Datenbank ab.
So werden funktionale Anforderungen in der Form kleiner Geschichten aufgezeichnet, die darüber handeln, wie die Anwender das System benutzen, um ihre Geschäftsziele zu erreichen. Also keine unzusammenhängenden feature-Listen. Der Ausschnitt des beschriebenen Systemverhalten ist so groß, dass er aus der Sicht des Anwenders einen Wert für seine Arbeit hinzufügt. Füllt der Anwender eine Maske aus und speichert die Daten über einen „Speichern“-Button in eine Datenbank, ist „Speichern in eine Datenbank“ kein eigener Use Case. Für den Anwender ist die Eingabe der Daten und das Drücken des „Speicher“-Buttons ein atomarer Vorgang. Eingeben und Speichern zusammen ist also möglicherweise ein Use Case. Muß ein Anwender beispielsweise für einen Geschäftsvorgang ein Kategoriedokument erstellen und dann erst das eigentliche Dokument, dann ist Kategoriedokument erstellen kein eigener Use cases, sondern beides zusammen.
Begriffe der Informatik werden vermieden. So kann der Gebrauch von „Datenbank“ angegriffen werden. Ich finde das aber ok, weil es ein Begriff ist, der von den meisten verstanden wird. Der oben aufgezeichnete informelle Anwendungsfall nimmt viele Details nicht auf. Das ist möglicherweise gut so, um den use case für alle Beteiligten einfach verstänlich zu halten. Schliesslich will keiner bei der Arbeit unnötig intelektuell gefordert werden. Das führt sowieso nur zu zuviel Kaffee oder gar schlimmeren (z.B. Zigaretten).
In unseren Use Case fehlen aber noch definitiv die Fehlerbedingungen, die auftreten können und wie die Fehlermeldungen dem Anwender mitgeteilt werden. Ich kenne mindestens 2 größere Notes-Projekte, bei denen Verbindungsprobleme mit einer externen RDBMS dem Anwender nicht korrekt mitgeteilt wurden. Die standen dann im Log. Das las keiner. Die Systeme arbeiteten dann über einen mehr oder weniger langen Zeitraum nicht korrekt und die Anwender wurden verunsichert, da keiner wusste warum das System nicht richtig rund lief. Konkrete Fehlermeldungen sind also konkret wichtig.
Der oben aufgeführte Use Case sollte also noch in ein exakteres Format übertragen werden. Das informelle Format beschreibt eigentlich nur ein Szenario bzw. eine Instanz des Use Cases. Den sogenannten lucky path oder main success scenario(alles funktioniert). Daneben sollen auch Fehlerbedingungen aufgeführt werden.
Ausserdem sollte man bei der Spezifizierung der UML-Akteure genauer sein. Anwender ist ein wenig zu allgemein. Eine physische Person kann mehrere UML-Akteure verkörpern. Ein besserer Begriff für Akteur (engl. actor) wäre Rollen. Angeblich geht diese semantische Unschärfe auf Übersetzungsfehler aus dem schwedischen zurück. Die erste Person, die theoretisch über Use Cases publizierte, war der Ericson Mitarbeiter Ivar Jacobson.
Die Use Cases dienen letztlich in ihrer Gesamtheit dazu, alle Akteure (d.h. Rollen) eines Systems zu ermitteln.
Als Akteure haben wir zunächst den code-Dokument producer. Daneben sind auch andere Systeme, mit denen unser System kommuniziert, Akteure. In unserem Fall sind dies zunächst der Volltextindexierungs- Service und die Datenbank.
Deshalb gehen wir zum nächsten Format über, dem sogenannten casual Format (laut Larman).
Use Case1: Code-Dokument erstellen
Main Success Scenario:
Der code-Dokument producer wählt die Kategorie, unter dem die neue Funktion gespeichert werden soll oder er erzeugt eine neue Kategorie. Er gibt der Funktion einen Namen, gibt einen Kommentar an, fügt Referenzen auf bestehende Funktionen hinzu, von denen die neue Funktion abhängt, schreibt einen aussagekräftigen Kommentar, fügt den code ein und sendet an das System die Nachricht, dass das neue code-Dokument abgespeichert werden soll. Das System validiert, ob alle notwendigen Eingaben getätigt sind, übergibt den Text des Kommentarfeldes dem Volltextindiexierungsservice und speichert das code-Dokument in einer exterenen Datenbank ab.
Alternate Scenario1:
Wenn das System bei der Validierung der eingegebenen Daten bemerkt, dass die Daten nicht komplett sind, wird der code-Dokument producer mit einer Message-Box darauf aufmerksam gemacht. Eine Volltextindexierung und das Abspeichern der Daten in der Datenbank findet nicht statt.
Alternate Scenario2:
Wenn der Volltextindexierungsservice zurückmeldet, dass er den Text des Kommentarfeldes nicht verarbeiten kann, wird der Datensatz in die Datenbank mit einem Vermerk „nicht Volltextindexiert“ abgespeichert. Der Anwender wird mittels einer Messagebox über die nicht stattgefundene Volltextindizierung informiert. Bei einem späteren Systemstart, wird versucht die Volltextindexierung für das entsprechende code-Dokument durchzuführen. Der Vermerk im Datensatz in der Datenbank wird auf „volltextindiziert“ umgestellt. Der Anwender wird informiert.
Alternate Scenario3:
Wenn die Datenbank zurückmeldet, dass sie zur Zeit keine neuen Datensätze abspeichern kann, bekommt der code Dokument producer eine Meldung über eine Messagebox. Die Volltextindexierung wird rückgängig gemacht.
Sehr ähnlich sieht der Use Case “ Kategorie erstellen” aus
Use Case2: Kategorie erstellen:
Main Success Scenario:
Der code Dokument producer wählt eine Oberkategorie für die neue Kategorie aus oder nicht. Wenn nicht, ist die neue Kategorie eine first-level Kategorie. Über den Button „Kategorie abspeichern“ sendet er eine Nachricht an die Datenbank, dass sie die neue Kategorie abspeichern soll.
Alternate Scenario1:
Wenn der code Dokument producer nichts in das Namensfeld der Kategorie eingetragen hat,. erhält eine eine Fehlermeldung und der Datensatz wird nicht in die Datenbank abgespeichert.
Alternate Scenario2:
Wenn die Datenbank zurückmeldet, dass sie unter der gleichen Oberkategorie bereits eine gleichnamige Kategorie abgespeichert hat, erhält der Code-Dokument producer eine Fehlermeldung und der Datensatz wird nicht in die Datebank abgespeichert.
Alternate Scenario3:
Wenn die Datenbank zurückmeldet, dass sie zur Zeit keine neuen Datensätze abspeichern kann, bekommt der Code Dokument producer eine Meldung in Form einer Messagebox.
Der Use Case für „Code Dokument suchen“ sieht so aus:
Use Case2: Code Dokumente suchen:
Main Success Scenario:
Der Code Dokument Consumer (neuer Akteur!)
a) wählt in einem hierarchischen Kategorie-Baum (ähnlich wie Windows-Explorer) die gewünschte Kategorie aus und
b) macht einen Eintrag in das Feld Volltextsuche, betätigt den „Senden“-Button und
erhält eine Trefferliste, der gefundenen code Dokumente zurück.
Er kann die sich nun angucken. Wenn ihm ein code Dokument gefällt, kann er über den Button „code Dokument in die Zwischenablage kopieren“, den code inklusive aller referenzierten Unterfunktionen in die Zwischenablage des OS-kopieren und im Domino Designer über Strg-V wieder reinkopieren.
Alternate Scenario1:
Der Volltextindexierungsservice kann die Anforderung nicht verarbeiten. Der code Dokument consumer erhält vom System eine Fehlermeldung.
Kommt nun noch das Kollaborationsfeature „Replizierung für Arme“. Es kann später durch einen echten P2P-Service ersetzt werden... Sollte das System genutzt werden, lohnt sich die Mühe. Im ersten Release gibt es nur „Replizierung für Arme“
Use Case2: Replizierung durchführen:
Main Success Scenario:
Der replication requester wählt aus einer Liste an Teilnehmern aus, mit wem er replizieren will.
Betätigt der replication requester die Schaltfläche „request Datei erzeugen“ generiert das System eine xml-Datei (request.xml) als Übersicht über sämtliche Datensätze, die in der Datenbank des replication requesters enthalten sind.
Diese request.xml sendet er als email an denjeningen, von dem er eine pull-replikation haben will (replication requested).
Der replication responder empfängt die email und speichert die request.xml im selben OS-Verzeichnis wie sein code-store Programm. Er startet das code-store Programm. Er betätigt die Schaltfläche „replication request bearbeiten“. Das System überprüft, welche code-Dokument, Kategorie und Teilnehmer-Daten sich in seiner Datenbank enthalten sind, aber in der Übersicht der request.xml fehlen. Diese Datensätze packt das System in eine Datei response.xml.
Der replication responder sendet eine email an den replication requester mit der response.xml als attachment.
Der replication requester empfängt die email und packt die response.xml in das OS-Verzeichnis seines code-store Programms. Er startet das code-store-Programm und betätigt die Schaltfläche „replication-response einfügen“. Das System übergibt die Inhalte des Kommentarfeldes der Datensätze dem Volltextindexierungsservice, es fügt die neuen Datensätze aus der Datei response.xml in seine Datenbank ein und baut die Kategorisierung neu auf.
Alternate Scenario1
Das System kann die request.xml nicht erstellen. Der replication requester erhält eine Fehlermeldung als messagebox.
Alternate Scenario2:
Das System des replication responders kann die request.xml nicht verarbeiten. Der replication responder erhält eine Fehlermeldung als messagebox.
Alternate Scenario3
Das System des replication responders kann die response.xml nicht erstellen. Der replication responder erhält eine Fehlermeldung als Messagebox.
Alternate Scenario4
Das System des replication requesterskann die response.xml nicht verarbeiten. Der replication requester erhält eine Fehlermeldung als Messagebox.
Alternate Scenario5:
Wenn der Volltextindexierungsservice zurückmeldet, dass er den Text des Kommentarfeldes nicht verarbeiten kann, wird der Datensatz in die Datenbank mit einem Vermerk „nicht Volltextindexiert“ abgespeichert. Der Anwender wird mittels einer Messagebox über die nicht stattgefundene Volltextindizierung informiert. Bei einem späteren Systemstart, wird versucht die Volltextindexierung für das entsprechende code-Dokument durchzuführen. Der Vermerk im Datensatz in der Datenbank wird auf „volltextindiziert“ umgestellt. Der Anwender wird informiert.
Alternate Scenario6:
Wenn die Datenbank zurückmeldet, dass sie zur Zeit keine neuen Datensätze abspeichern kann, bekommt der code Dokument producer eine Meldung über eine Messagebox. Die Volltextindexierung wird rückgängig gemacht.
Es gibt noch weitere Use Cases zu den Themen Teilnehmerdaten verwalten, sowie Erweiterungen für die Anwendungsfälle "Code Dokument erstellen“ und „Kategorie erstellen“ (jeweils bestehende bearbeiten). Dies ist aber jetzt erst mal zu trivial, als das es aufgeführt werden müßte. Ich komme später darauf zurück.
Hier ist ein UML Use Case Diagramm, das alle Use Cases übersichtlich darstellt. So wahnsinnig sinnvoll ist dieser Diagrammtyp nicht, ausser das er eine Übersicht bietet.
(http://www.atnotes.de/attachments/useCasesCodeStore.gif)
Das <<verwendet>> zwischen "Code-Dokument erstellen" und "Kategorie erstellen" soll eigentlich <<uses>> heissen. Schuld ist erstmal Visio.
Wenn sich jemand den use case "code Dokument erstellen" noch mal durchliest, sieht er, dass in dem use case der code-Dokument producer eine neue Kategorie erstellen kann. Dies wird mit dem <<uses>> alias <<verwendet>> ausgedrückt.
Ach ja. Die lustigen Linien zwischen den Akteuren und den Use Cases zeigen an, welche Akteure bei weilchen Use Cases beteiligt sind.
Ich hätte auch noch die Anwendungsfälle "code-Dokument bearbeiten" und "Kategorie bearbeiten" hinzufügen können, die dann von den use cases "Code-Dokument erstellen" und "Kategorie erstellen" erben (Schlüsselwort <<extends>>) oder "code Dokument suchen" als abstrakten use case definieren können, von dem die use cases "code Dokument über Kategorie suchen" und "code Dokument über Volltextindex suchen" erben... . Das hätte aber das Diagramm überfrachtet. So wichtig ist der Sachverhalt nicht. Diese ganze Vererberei ist in OO-Land sowieso ein bischen out. Use Cases haben eine reichhaltiges Angebot an Erweiterungen (extension points, abstrakte use cases, etc). Die Literatur rät aber dringend dazu, die Dinge einfach zu halten, es sei denn man hat wirklich gute Gründe, die erweiterten features zu nutzen. Die sehe ich hier nicht.
Für die Inception Phase fehlt jetzt noch auf jeden Fall eine Aufstellung der nicht-funktionalen Anforderungen. Schliesslich behandeln Use Cases nur funktionale Anforderungen. Aber das kommt morgen.
Der Text der Use Cases wird in der nun folgenden OOAnanalyse dazu dienen, die Klassen der Business Domäne herauszufinden: Das heisst, die Namen der Klassen, ihre Verantwortlichkeiten und ihre Kollaborationen (also welche Klassen mit welchen anderen Klassen zusammenarbeiten).
Ein Use Case mit starker Querschnittsfunktionalität für das gesamte System („Code Dokument erstellen“) werde ich auch schon mal durchprogrammieren (schliesslich will ich ja iterativ arbeiten, d.h. die Dinge Requirement Analyse --> OO-Analyse --> OO-Design --> codieren --> testen nicht streng hintereinander, sondern durcheinander durchführen).
Aufgrund der Gui-Lastigkeit der Anwendung macht ein GUI-Prototyp Sinn. Das notieren der Use-Cases haben mir auch geholfen, ein Bild der GUI im Kopf zu entwickeln. Dies sollte ich dann auch festhalten, sonst vergesse ich das wieder.
Um dies zu notieren, bieten sich theoretisch Java-Swing GUI-IDE-Tools an. Da ich aufgrund schlechter Erfahrungen Anfang Dezember mit dem momentanen Stand dieser Tools ein bischen auf dem Kriegspfad mit demselben bin, werde ich den Prototyp mit dem Notes-Client machen.
Für den Use Case „Code Dokument erstellen“ generiere ich ein sogenanntes System Sequence Diagram. Das ist eine Sequenz an Nachrichten, die der Anwender mit dem System austauscht. Das System selbst wird dabei als black box betrachtet.
Inzwischen bin ich überzeugt, dass Potsmokers Einwände zu 95% korrekt waren. Ich habe Fehler gemacht. Ich bringe den Use Cases in ein vollständiges Format und ändere ein paar Dinge. Tatsächlich war der Begriff Datenbank unglücklich gewählt. Korrekt ist es zunächst bei einem Begriff zu bleiben, der aus der Welt der Problem-Domäne und nicht der Lösungs-Domäne angehört. Ich wähle also Code-Dokument Katalog statt Datenbank.
Ausserdem war es ein bischen design-overkill, den Anwender in die Rollen code-document producer, code-document consumer, etc. aufzuspalten.
Für dieses kleine System reicht eine Rolle Anwender, die mehrere Funktionen im System ausfüllt:
UC1: Code Dokument erstellen
Primärer Akteur: Anwender
Stakeholders and Interests:
[...] hier zu trivial
Main Success Scenario
Preconditions: Anwender ist im System authentifiziert
Postconditions:
Das neue Code-Dokument ist im Code Dokument Katalog eingefügt.
Der Indexierungsservice hat das Code-Dokument indexiert.
Das Code-Dokument kann über die Kategoriesuche und die Volltextsuche jederzeit aufgerufen werden.
Main Success Scenario:
1. Anwender startet Erstellung eines neuen Code Dokuments
2. Anwender fügt die benötigten textlichen Informationen (Beschreibung, Beschreibung der Verwendung, code)
3. Anwender wählt bei Bedarf aus der Liste der bestehenden LotusScript-Funktionen die aus, auf die der code im neuen Code-Dokument zugreift.
4. Anwender wählt die Kategorie des neuen Code Dokuments
5. Anwender teilt mit, dass Eingaben abgeschlossen.
6. System prüft Korrektheit der Eingaben.
7. Indexierungsservice indexiert Beschreibung.
8. System fügt Code Dokument dem Code-Dokument Katalog hinzu und persistiert diese Änderung in eine Datenbank (hehe).
9. System logged erfolgeiche Erstellung des neuen Code Dokuments.
10. System teilt Anwender mit, dass Code-Dokument erfolgreich dem Code-Dokument Katalog hinzugefügt wurde.
Extensions (or Alternative Flows)
4. a) Anwender erstellt eine neue Kategorie -> Use Case „Neue Kategorie erstellen”
6.a) Anwender wird mit einer Nachricht auf die fehlenden Eingaben. Zurück zu 3.
7.a) Indexierung schlägt fehl
8.a) System fügt Code Dokument dem Code-Dokument mit dem Attribut „Code-Dokument nicht indexiert“ hinzu und persistiert diese Änderung in eine Datenbank.
9.a) System locked Erstellung des neuen Code Dokuments mit Hinweis auf fehlende Volltextindexierung.
10.a) System teilt Anwender mit, dass Code-Dokument erfolgreich dem Code-Dokument Katalog hinzugefügt, aber nicht volltextindexiert wurde.
11. Bei einem Neustart des Systems wird versucht den Volltextindex zu erstellen (Teil des startup Use Cases!).
8.a) Hinzufügung des Code Dokuments zum Code Dokument Katalog und ?ersistierung diese Änderung in eine Datenbank.scheitert.
9.a) System logged gescheitertes Hinzufügen des Code Dokuments zum Code Dokument Katalog
10.a) User erhält Nachricht über gescheitertes Hinzufügen des Code Dokuments zum Code Dokument Katalog
Man kann nun noch für das Main Success Scenario ein sogenanntes System Sequence Diagram erzeugen. Das Sequence Sequence Diagram enthält die zwischen den Akteuren gesendeten Nachrichten. Dabei wird das System als Black Box betrachtet.
Ich habe ein bischen die Orthodoxie verlassen, indem ich nicht nur die Interaktion zwischen dem primären Akteur „Anwender“ und dem System zeige, sondern auch die Interaktion mit den sekundären Akteuren Datenbank, Indexierungsservice und Loggingservice. Ob das sinnvoll ist, kann ich nicht beurteilen. Eigentlich verliert das System dadurch ein wenig seinen (passiven) black box Charakter. Es ruft ja selber akiv die Operationen indexCodeDocument(), saveCodeDocument() und logMessage() auf.
Ich finde, man muß das nicht so päbstlich sehen. Modelle sind nie richtig oder falsch sondern immer mehr oder weniger nützlich. Bubbles don’t crash. An einem ausführbaren Programm kann in der Regel gut gezeigt werden, dass es nicht funktioniert. Bei einem Modell ist das schwieriger. Ein Modeller kann sich besser rausreden als ein Programmierer.
Da die deutsche Sprache in Computern sowieso meist zu einer kruden Mischung aus Deutsch und Englisch führt, nehme ich Englisch als Sprache. Als Input für die Namensfindung benutze ich den Text des Use Cases.
Beispiel:
Anwender wählt die Kategorie des neuen Code Dokuments
wird zur Operation selectCategory() usw.
Dieses generelle Vorgehen ist charakteristisch für den (Rational) Unified Process. Es wird sich von dem spezifischen Problem in der Welt der Anwender immer näher der Lösung, dem Computerprogramm angenähert. Auf dem Weg wird ein Haufen an Dokumenten erstellt. Bei jedem neuen Schritt wird auf die in die vorherigen Schritte erstellten Dokumente zurückgegriffen. Trotz aller Objektorientierung geht man also davon aus, dass die Domäne des Geschäftsprozesses, der durch die Software unterstützt werden soll, unterschiedlich ist von der Welt der Software. Ansonsten bräuchte man nicht diesen komplexen Analyseprozess. Mit Objektorientierung wird nur die semantische Lücke zwischen Geschäftsbereich und Software geringer, nicht geschlossen.
(http://www.atnotes.de/attachments/SSDCreateCodeDocumentz.gif)
Die Kästchen oben beschreiben den Akteur. Ich stelle sie als UML-Objekte dar. Der Syntax von UML-Objekten ist Objektbezeichner:Klassenbezeichner. Ich benötige keinen Objektbezeichner, deshalb nehme ich :Klassenbezeichner. Die vertikalen gestrichelten Linien sind die Objektlebenslinien. Das Diagramm zeigt, dass die Akteurs-Objekte länger leben als die Zeitspanne des dargestellten Use Cases. Die Pfeile stehen für Nachrichten, die zwischen den Objekten ausgetauscht werden. Eine Nachricht ist: Objekt x ruft die Operation a des Objekts y auf.
Beispiel: Der Akteur User ruft die Operation selectFunctionsUsed() des System auf.
Die Begriffe Operation und Methode werden oft synonym verwendet. Das ist nicht ganz richtig. Eine Operation bezeichnet lediglich den Methoden-Header. Methode strenggenommen nur die Implementierung.
public String intToString(int num) {
return “” + num;
}
ist eine Methode. (Header und Body).
public String intToString(int num)
die entsprechende Operation der Klasse, die von ausserhalb oder innerhalb eines Objekts der Klasse angesprochen werden kann. Da wir uns im konzeptionellen Analyse-Modus und nicht im Implementierungs-Modus befinden, interessieren uns nur die Operationen, nicht die Methoden.
Rückgaben von Operationen können optional als gestrichelte Pfeile angezeigt werden. Der Anwender sendet dem System eine Nachricht, indem er dessen Operation saveCodeDocument() aufruft.
Dies führt zu einer Sequenz von Nachrichten, die zwischen den Akteuren System, Database, IndexService und LoggingService gesendet werden. Am Ende erhält der Anwender „message“ als Rückgabewert der Operation.
In diesem frühen konzeptionellen Diagramm habe ich auf Operationsparameter und die Spezifizierung der Rückgabewerte verzichtet. Ein Modell soll nicht die wirkliche Welt darstellen, sondern sich auf die wichtigen Dinge fokussieren. Bubbles don’t crash.
Von diesen Operationen lassen sich später die tatsächlichen Methoden des ausführbaren Systems ableiten.