Loading AI tools
objektorientierte Varianten der zwei allgemeinen Tätigkeiten Anforderungsanalyse und Systementwurf im Entwicklungsprozess eines Softwaresystems Aus Wikipedia, der freien Enzyklopädie
Objektorientierte Analyse und Design (OOAD) sind objektorientierte Varianten der zwei allgemeinen Tätigkeiten Anforderungsanalyse (objektorientierte Analyse) und Systementwurf (objektorientiertes Design) im Entwicklungsprozess eines Softwaresystems.
Dadurch, dass in den Entwicklungsphasen Analyse und Design bereits objektorientierte Techniken eingesetzt werden, wird der Übergang zur Implementierung in einer objektorientierten Programmiersprache erleichtert.
Als Standardnotation für objektorientierte Modelle hat sich die Unified Modeling Language (kurz UML) etabliert. Ein Vorgehensmodell, das speziell für objektorientierte Techniken und die UML entwickelt wurde, ist der sogenannte Rational Unified Process (RUP).
In der Analyse geht es darum, die Anforderungen zu erfassen und zu beschreiben, die das zu entwickelnde Softwaresystem erfüllen soll. In dieser Phase werden alle Fakten gesammelt, dargestellt und überprüft. Dies kann in Form eines textuellen Pflichtenheftes oder einer Software Requirements Specification geschehen. Ergebnis der Analyse ist ein allgemeines Produktmodell in Form eines objektorientierten Analyse-Modells (OOA-Modell). Diese fachliche Beschreibung mit objektorientierten Konzepten enthält verschiedene Artefakte wie Diagramme und Darstellungen von Kontrollstrukturen.
Beim objektorientierten Design wird das in der Analyse erstellte Domänenmodell weiterentwickelt und darauf aufbauend ein Systementwurf erstellt. Dabei wird das allgemeine Modell in eine konkrete Softwarearchitektur umgeformt, die Informationen über Details der technischen Umsetzung enthält und direkt als Vorlage für die Implementierung in einer Programmiersprache dient, die idealerweise objektorientierte Programmierung (OOP) unterstützt.
Wesentliche Aufgabe der Projektorganisation ist es, für ein konkretes Softwareprojekt einen geeigneten Entwicklungsprozess zu definieren und diesen entsprechend umzusetzen.[1] Ein Vorgehensmodell zur Softwareentwicklung dient dazu, diese übersichtlich und in der Komplexität beherrschbar zu machen. Bei allen Vorgehensmodellen geht es darum, neben der Abgrenzung der Phasen voneinander, die Umwandlung eines Konzeptes (bzw. eine Produktspezifikation) in ein lauffähiges Softwareprodukt zu realisieren.
Vorgehensmodelle spalten somit einzelne Aktivitäten auf verschiedene Phasen im Entwicklungsprozess auf. Diese werden dann – u. U. mit geringen Modifikationen – einmal (z. B. Wasserfallmodell) oder mehrmals durchlaufen (z. B. Spiralmodell). Bei mehrmaligen Durchläufen erfolgt eine iterative (d. h. wiederholte) Verfeinerung der einzelnen Softwarekomponenten. Um die optimalen Vorgehensmodelle herrscht Uneinigkeit. In der Regel unterscheiden sie beim Entwicklungsprozess mindestens zwei große Tätigkeitsgruppen: die (von der programmiertechnischen Realisierung unabhängige) Analyse von Geschäftsprozessen (Geschäftsprozessmodell und Datenmodell) einerseits und die EDV-technische Realisierung (Design und Programmierung) andererseits.
Seit Beginn der 1980er-Jahre nehmen die Bedeutung und die Anzahl der objektorientierten Analyse- und Entwurfsmethoden ständig zu. Bei diesen werden die Ergebnisse der Phasen Analyse, Design und Implementierung objektorientiert erstellt. Für letzteren werden objektorientierte Programmiersprachen verwendet. Dadurch, dass in all diesen Phasen dieselben Techniken verwendet werden, wird eine bessere Durchgängigkeit bei den objektorientierten Techniken erreicht. In Analyse und Design wird sogar dieselbe Notation eingesetzt. Beim Übergang von der objektorientierten Analyse zum objektorientierten Design tritt somit kein Strukturbruch auf.[2] Einer der ersten Ansätze zur Modellierung der Anforderungen an Systeme war „Object-Oriented Analysis“ (OOA) von Peter Coad und Edward Yourdon.[3] „Object-Oriented Design“ (OOD) schließt direkt daran an und behandelt den Übergang zum Entwurf.[4]
Als Standardnotation für objektorientierte Modelle hat sich die Unified Modeling Language (kurz UML) etabliert, die in den 1990er-Jahren insbesondere von Grady Booch, Ivar Jacobson und James Rumbaugh entwickelt wurde. Die Modelle in UML sind das wesentliche Kommunikationsmittel zwischen Entwicklern und weiteren Beteiligten im Softwareentwicklungsprozess.
Ein Vorgehensmodell, das speziell für objektorientierte Techniken und die UML entwickelt wurde, ist der sogenannte Rational Unified Process (RUP). Es handelt sich dabei um ein kommerzielles Produkt der Firma Rational Software, die seit 2004 Teil des IBM-Konzerns ist. Federführend bei der Entwicklung waren wiederum die drei Programmierer Grady Booch, Ivar Jacobson und James Rumbaugh.[5] Der RUP definiert die folgenden Disziplinen:
Ein Vorteil des RUP ist die iterative Vorgehensweise, wodurch im Gegensatz zu linearen Vorgehensmodellen (wie etwa dem Wasserfallmodell) sich ändernde Anforderungen auch zu einem späteren Zeitpunkt noch berücksichtigt werden können.
Die zugrunde liegende Idee der Objektorientierung ist es, Zustand (Daten) mit Verhalten (Funktionen auf diesen Daten) zu verbinden. Der Programmablauf soll dabei als ein Zusammenspiel von Objekten und ihren Interaktionen aufgefasst werden. Die Modellierung der Objekte erfolgt dabei in einer Anlehnung an die reale Welt, in der Objekte und ihre Interaktionen ein wesentlicher Bestandteil sind. Ergänzt wird dies durch das Konzept der Klasse, in der Objekte aufgrund ähnlicher Eigenschaften zusammengefasst werden. Man kann sich Klassen als abstrakte Schablonen für Dinge mit gemeinsamen Eigenschaften und Verhaltensformen vorstellen. Ein Objekt wird im Programmcode als Instanz oder Inkarnation einer Klasse definiert.
Das Kernstück jeder objektorientierten Überlegung bildet also das Objekt. Dieses ist ein Exemplar eines bestimmten Datentyps oder einer bestimmten Klasse und wird während der Laufzeit erzeugt (instanziiert). Objekte enthalten nun Attribute und Methoden. Dabei sind Attribute nur Variablen und Konstanten, die Werte aufnehmen können, und beschreiben damit das „statische Wesen“ des Objektes. Im Gegensatz dazu gibt es die „Methoden“ die das gesamte „dynamische Verhalten“ des Objektes oder einer Klasse charakterisieren; sie enthalten die „algorithmische Essenz“ des Objektes.
Beispiel: Die Klasse car
für ein Auto definiert zwei Attribute fuel
(Benzin) und maxSpeed
(Höchstgeschwindigkeit). Diese beschreiben den Zustand eines Autos. Mit Methoden wie refuel()
(tanken) oder drive()
(fahren) lässt sich der Zustand eines Autos ändern. Sie charakterisieren dadurch das dynamische Verhalten. Allerdings ist die Klasse car
erst der (softwaretechnische) „Bauplan“ eines Autos. Um mit „konkreten“ Autos während der Laufzeit umzugehen, müssen Instanzen dieser Klasse erzeugt werden, beispielsweise Objekte polo
, mini
und beetle
. Eine Klasse wird daher bisweilen auch mit einer Ausstechform verglichen, die dazu dient, viele einzelne Plätzchen herzustellen.
Eine Klassifizierung ist im Allgemeinen eine Einschränkung/Vereinfachung der realen Welt in einem ganz speziellen Kontext. Es wird also niemals „die“ Klassifizierung geben. Sie ist immer abhängig vom Ziel, das mit der Klassifikation erreicht werden soll. Während beispielsweise eine Klasse „Auto“ im Kontext eines Autobauers möglicherweise Attribute wie Räder und Farbe besitzen wird und seine Bauteile (in Form von Attributen oder Beziehungen) kennen wird, hat eine Klasse „Auto“ im Kontext eines Händlers Attribute wie Produktnummer, Preis, Verbrauch und Erstzulassungsdatum. Im Kontext einer Zulassungsstelle wird es Attribute wie Kennzeichen, zulässiges Maximalgewicht und den Halter geben.
Grady Booch et al. nennen drei wichtige Aspekte, die objektorientierte Programmierung ausmachen:[6]
Das Ziel der Analyse ist es, die Anforderungen eines Auftraggebers an ein neues Softwaresystem zu ermitteln und zu beschreiben. Bei dieser Phase werden meistens alle Aspekte der Implementierung ausgeklammert. Es kann aber beispielsweise der Entwurf einer Benutzerschnittstelle (z. B. GUI-Entwurf) bereits in der Analyse durchgeführt werden, da für viele Anwender erst dadurch ein Bild der zukünftigen Anwendung entsteht.
Die objektorientierte Analyse geht von Objekten aus, die sich in der realen Welt befinden. Dies sind nicht nur Gegenstände, sondern auch Ereignisse und Begriffe aus dem Anwendungsbereich. Das zu realisierende Problem soll verstanden und in einem OOA-Modell beschrieben werden. Dieses Modell soll die essentielle Struktur und Semantik des Problems beschreiben, aber noch keine technische Lösung. Man spricht auch von einem Fachkonzept, welches aus einem statischen und einem dynamischen Modell besteht:
Das OOA-Modell muss alle Informationen enthalten, um daraus einen Prototyp der Benutzungsoberfläche abzuleiten.[7]
Ziel des Requirements Engineering (i. e. Anforderungsermittlung) ist es, die Anforderungen an ein neues Softwareprodukt zu ermitteln, zu spezifizieren, zu analysieren, zu validieren und daraus eine fachliche Lösung abzuleiten beziehungsweise ein Produktmodell zu entwickeln.[8] Objektorientierte Methoden des Requirements Engineering verallgemeinern die Konzepte der Objektorientierung, stellen dafür graphische Notationen bereit und betten die Konzepte in einen methodischen Rahmen ein. Sie führen zu einem integrierten Modell der funktionalen Anforderungen, in dem alle relevanten Systemaspekte berücksichtigt sind. Nichtfunktionale Anforderungen können allerdings nur textuell oder durch individuelle Erweiterung erfasst werden.[9]
Anforderungen (requirements) legen fest, was man von einem Softwaresystem erwartet. Gibt es einen bestimmten Auftraggeber, dann wird dieser die wichtigsten Anforderungen bestimmen. Wird ein Produkt für den anonymen Markt entwickelt, dann werden die Marketingabteilung und der Vertrieb die wesentlichen Anforderungen festlegen. Alle Personen und Organisationen, die ein Interesse an einer Softwareentwicklung haben oder vom Einsatz des Softwaresystems betroffen sind, werden mit dem englischen Begriff Stakeholder (dt. i. e. Teilhaber, Akteur, Interessenvertreter) bezeichnet.
Der IEEE Standard 830 (Software Requirements Specification) unterscheidet funktionale Anforderungen (functional requirements) von nichtfunktionalen Anforderungen (non-functional requirements). Eine funktionale Anforderung legt eine vom Softwaresystem oder einer seiner Komponenten bereitzustellende Funktion oder bereitzustellenden Service fest. Funktionale Anforderungen lassen sich gliedern in
Nichtfunktionale Anforderungen, auch Technische Anforderungen oder „Quality of Service“ (kurz QoS) genannt, meinen Aspekte wie Zuverlässigkeit, Verfügbarkeit, Nebenläufigkeit, Konsumierbarkeit, Internationalisierung, Informationssicherheit, Service-Anforderungen und Support. Nichtfunktionale Anforderungen haben großen Einfluss auf die Softwarearchitektur. Außerdem können sie zueinander im Konflikt stehen: So ist beispielsweise Sicherheit häufig im Widerspruch zu Benutzbarkeit, Speichereffizienz ist meist gegenläufig zu Laufzeiteffizienz.[11]
In Anlehnung an IEEE 830 nennt Balzert eine Reihe von Kriterien, die jede einzelne Anforderung erfüllen soll:[12]
Aufgabe des Requirements Engineers ist es, in Zusammenarbeit mit den Stakeholdern diese Qualitätskriterien an Anforderungen so gut wie möglich zu erreichen. In der Praxis ist man jedoch oft weit davon entfernt, diese zu erreichen: „Diese Problematik entsteht dadurch, dass die Gesprächspartner kein vollständiges Modell des zu entwickelnden Systems ‚im Kopf‘ haben.“[13]
Nach der DIN 69901 ist ein Lastenheft eine „vom Auftraggeber festgelegte Gesamtheit der Forderungen an die Lieferungen und Leistungen eines Auftragnehmers innerhalb eines (Projekt-)Auftrags“:[14] Das Lastenheft ist somit die Grundlage zur Lösungsfindung im Projektverlauf. Im Wesentlichen werden dabei folgende Ziele verfolgt[15]
Nach der DIN 69901 enthält ein Pflichtenheft „vom Auftragnehmer erarbeitete Realisierungsvorgaben auf der Basis des vom Auftraggeber vorgegebenen Lastenhefts“.[16] Aus der Sicht des Auftragnehmers stellt das Pflichtenheft die formelle und detaillierte Antwort auf die Anforderungen des Auftraggebers dar, die zuvor im Lastenheft beschrieben wurden. Die zu erbringenden Ergebnisse des Auftragnehmers werden dadurch in erforderliche Tätigkeiten (Pflichten) umgesetzt.[15]
Lasten- und Pflichtenheft sollen den Systemanalytiker also in die Lage versetzen, das OOA-Modell zu erstellen. Sie besitzen jedoch ein niedrigeres Detaillierungsniveau als das OOA-Modell.
Zur Modellierung der inneren Struktur eines Systems werden Strukturdiagramme herangezogen. Die beiden wichtigsten Diagrammtypen des objektorientierten Designs sind Klassendiagramm und Objektdiagramm. Um Objekte zu modellieren, wird untersucht, wie die Realität aussieht bzw. wie sie vereinfacht abgebildet werden kann. In einem Klassendiagramm werden alle beteiligten Klassen und deren Beziehungen abgebildet. In einem Objektdiagramm dagegen werden Objekte des Klassendiagramms zu einem bestimmten Zeitpunkt während der Ausführung dargestellt.[17]
In der UML-Notation werden Klassen als dreigeteilte Rechtecke angegeben, deren Bestandteile der Klassenname, eine Liste über alle Attribute und eine Liste über alle Operationen und Eigenschaften sind. Dabei werden diese drei Rubriken jeweils durch eine horizontale Linie getrennt. Wenn die Klasse keine Eigenschaften oder Operationen besitzt, kann die unterste horizontale Linie entfallen. Klassennamen beginnen mit einem Großbuchstaben und sind Substantive im Singular. Attribute werden mindestens mit ihrem Namen notiert und können zusätzlich Angaben zu ihrem Typ (d. h. Klasse), einen Initialwert, Eigenschaftswerte und Zusicherungen enthalten. Operationen werden ebenfalls mindestens mit ihrem Namen aufgeführt und können zusätzlich Angaben zu möglichen Parameter und deren Klasse, Initialwerte sowie eventuelle Eigenschaftswerte und Zusicherungen enthalten. Eine Operation meint dabei die abstrakte Definition einer Funktionalität – im Gegensatz zur Methode, der konkreten Implementierung einer Operation.
Eine Assoziation modelliert Verbindungen zwischen Instanzen einer oder mehrerer Klassen. Es ist jedoch üblich, von einer Assoziation zwischen Klassen zu sprechen, obwohl streng genommen die Objekte dieser Klasse gemeint sind.[18] Im häufigsten Fall handelt es sich um eine Beziehung zwischen genau zwei Klassen. Grafisch wird eine Assoziation durch eine Linie dargestellt. Sind mehr als zwei Typen an einer Assoziation beteiligt, wird diese durch eine Raute dargestellt, an die zu den Objekten führende Linien anliegen. Eine reflexive Assoziation besteht dagegen zwischen Instanzen derselben Klasse. Die Kardinalitäten einer Assoziation spezifizieren, wie viele Objekte der beteiligten Klasse ein bestimmtes Objekt kennen. Mann unterscheidet zwischen Kann- und Muss-Assoziationen: Eine Kann-Assoziation hat als Untergrenze eine Kardinalität von 0, eine Muss-Assoziation eine Kardinalität von 1 oder größer. Eine unbestimmte Obergrenze wird durch das Zeichen * gekennzeichnet. Assoziationen können benannt werden. Beschreibt der Name nur eine Richtung der Assoziation, wird die Leserichtung durch ein schwarzes Dreieck oder einen Pfeil angegeben. Ist die Bedeutung der Assoziation offensichtlich, kann der Name fehlen.[19]
Eine Aggregation ist eine spezielle Assoziation, die eine Rangordnung auf den verbundenen Instanzen einer Klasse definiert, die sich durch „ist Teil von“ bzw. „besteht aus“ beschreiben lässt (Teil-Ganzes-Beziehung). Man spricht von einem gerichteten azyklischen Graphen: Wenn B Teil von A ist, dann darf A nicht Teil von B sein. Kann ein Teilobjekt mehreren Aggregationsobjekten zugeordnet werden, spricht man von „shared aggregation“ (dt. i. e. geteilte Aggregation) oder „weak ownership“ (dt. i. e. schwacher Besitz). Im Klassendiagramm wird eine Aggregation durch eine nicht ausgefüllte Raute am „Ganzes-Ende“ der Assoziationslinie gekennzeichnet.[20]
Eine Komposition ist eine noch stärkere Form der Aggregation. Neben einer Teil-Ganzes-Beziehung gelten noch folgende Bedingungen:[21]
Bei der Komposition wird das „Ganzes-Ende“ durch eine gefüllte oder schwarze Raute gekennzeichnet.
Die Vererbung dient dazu, aufbauend auf existierenden Klassen neue zu schaffen, wobei die Beziehung zwischen ursprünglicher und neuer Klasse dauerhaft ist. Eine neue Klasse kann dabei eine Erweiterung oder eine Einschränkung der ursprünglichen Klasse sein. Neben diesem konstruktiven Aspekt dient Vererbung auch der Dokumentation von Ähnlichkeiten zwischen Klassen, was insbesondere in den frühen Phasen des Softwareentwurfs von Bedeutung ist. Auf der Vererbung basierende Klassenhierarchien spiegeln strukturelle und verhaltensbezogene Ähnlichkeiten der Klassen wider. Die vererbende Klasse wird meist Basisklasse (auch Elternklasse) genannt, die erbende abgeleitete Klasse (Kindklasse). Den Vorgang des Erbens nennt man meist Ableitung oder Spezialisierung, die Umkehrung hiervon Generalisierung, was ein vorwiegend auf die Modellebene beschränkter Begriff ist. In der UML wird eine Vererbungsbeziehung durch einen Pfeil mit einer dreieckigen Spitze dargestellt, der von der abgeleiteten Klasse zur Basisklasse zeigt. Geerbte Attribute und Operationen werden in der Darstellung der abgeleiteten Klasse nicht wiederholt.
Ein Objektdiagramm kann als Sonderfall des Klassendiagramms angesehen werden. Während ein Klassendiagramm die allgemeinen „Schablonen“ und alle möglichen Beziehungen der Objekte untereinander modelliert, stellt das zugehörige Objektdiagramm die tatsächlich erzeugten Objekte, deren Attributwerte und Beziehungen innerhalb eines begrenzten Zeitraums der Laufzeit dar. Die Darstellung umfasst somit typischerweise Ausprägungsspezifikationen von Klassen und Assoziationen. Wie sich ein Objekt in einer bestimmten Situation verhält, hängt wesentlich von seinem Zustand ab. Dieser ergibt sich aus der konkreten Wertbelegung seiner Attribute.
Die graphische Darstellung eines Objekts ist der einer Klasse sehr ähnlich. Objekte werden ebenfalls durch Rechtecke repräsentiert. Im ersten Feld ist der Objektname zusammen mit dem Typ angegeben. Zur Unterscheidung von der Klassen-Notation wird der Name des Objekts unterstrichen. Im zweiten Feld werden Attribute mit ihren Namen und einem beispielhaften oder im jeweiligen Zusammenhang aktuellen Wert aufgeführt. Operationen werden nicht genannt, da diese keine objekt-individuellen Ausprägungen besitzen und für alle Objekte einer Klasse identisch sind. Stattdessen wird in Kommunikations- und Sequenzdiagrammen der konkrete Nachrichtenaustausch zwischen Objekten dargestellt.[22]
Das Verhalten eines objektorientierten Systems wird durch Botschaften (auch Nachrichten genannt) beschrieben, mit denen Objekte untereinander kommunizieren. Objekte agieren dabei in den Funktionen von Sendern (Clients) und Empfängern (Suppliern): Der Sender sendet eine Botschaft mit der Aufforderung, eine Dienstleistung zu erbringen. Eine Botschaft besteht aus einem Selektor (einem Namen), einer Liste von Argumenten und geht an genau einen Empfänger. Der Empfänger interpretiert diese Botschaft und führt eine Operation aus. Der Sender der Botschaft weiß jedoch nicht, wie die entsprechende Operation ausgeführt wird (Geheimnisprinzip).
Eine aktuelle Beziehung zwischen Objekten wird Link oder Objektbeziehung genannt. Ein Link beschreibt also die konkrete Beziehung zwischen zwei Objekten einer Klasse und kann somit als eine Instanz einer Assoziation aufgefasst werden. Er wird ähnlich wie die Assoziation im Klassendiagramm als Linie zwischen den Objekten dargestellt. An den jeweiligen Verbindungsenden können Rollenbezeichnungen stehen, die das Verhalten der Objekte zueinander näher beschreiben.
Mit Anwendungsfällen (englisch use cases) werden die extern beobachtbaren Funktionen spezifiziert, das heißt das, was ein Anwendungssystem einem Benutzer anbieten soll. Ein Akteur ist dabei eine außerhalb des Systems liegende Einheit, die an der Interaktion mit dem System beteiligt ist. Dies kann ein Mensch sein, aber ebenso ein technisches System wie ein Betriebssystem oder ein Drucker. Folgende Regeln sind zu beachten:[23]
Anwendungsfälle werden klassischerweise so benannt, wie die Ziele aus Sicht der Akteure heißen: Mitglied anmelden, Geld abheben, Auto zurückgeben usw. Die Granularität von Anwendungsfällen kann sich stark unterscheiden: Auf sehr hohem Niveau beschreibt ein Anwendungsfall lediglich sehr grob und abstrakt, was passiert. Die Technik des Anwendungsfall-Schreibens kann jedoch bis auf Ebene von IT-Prozessen verfeinert werden, sodass das Verhalten einer Anwendung detailliert beschrieben wird. Dies widerspricht der ursprünglichen Intention von Use Cases, ist aber manchmal zweckmäßig.
Der inhaltliche Aufbau eines Anwendungsfalls folgt meistens einer zu definierenden Vorlage, die abhängig vom Kontext der späteren Benutzung des Anwendungsfalls ausgearbeitet werden muss. Meist werden für verschiedene Analysephasen auch unterschiedlich stark formalisierte Vorlagen verwendet, von der rein prosaischen Kurzbeschreibung bis zu einem vollständigen, ausgearbeiteten Anwendungsfall. Wie man „Use Cases“ strukturieren sollte und welche Bestandteile hineingehören, beschreibt beispielsweise Alistair Cockburn[24] (Siehe dazu auch Aufbau eines Anwendungsfalls).
Ein Anwendungsfalldiagramm stellt Anwendungsfälle und Akteure mit ihren jeweiligen Abhängigkeiten und Beziehungen dar. Es ist somit ein Verhaltensdiagramm, das das erwartete Verhalten eines Systems spezifiziert, und keine Ablaufbeschreibung, wie es etwa ein Sequenz- oder Kommunikationsdiagramm ist.
Ein Anwendungsfalldiagramm enthält eine Menge von Anwendungsfällen, die durch einzelne Ellipsen dargestellt werden und eine Menge von Akteuren, die daran beteiligt sind. Diese werden durch Linien mit den entsprechenden Anwendungsfällen verbunden. Ein Rahmen um die Anwendungsfälle symbolisiert die Systemgrenzen.
Eine Sequenz von Verarbeitungsschritten, die unter bestimmten Bedingungen auszuführen ist, wird Szenario genannt. Diese Schritte sollen das Hauptziel des Akteurs realisieren und ein entsprechendes Ergebnis liefern. Man unterscheidet zwei Kategorien von Szenarios: Solche, die eine erfolgreiche Bearbeitung des Geschäftsprozesses beschreiben, und solche, die zu einem Fehlschlag führen. Szenarios werden durch Interaktionsdiagramme dargestellt. Die UML bietet dafür zwei Arten von Diagrammen an: das Sequenzdiagramm und das Kommunikationsdiagramm. Sequenzdiagramme stellen den zeitlichen Ablauf in den Vordergrund, Kommunikationsdiagramme zeigen dagegen die prinzipielle Zusammenarbeit.[25]
In Sequenzdiagrammen sollen Szenarios so präzise modelliert werden, dass deren fachliche Korrektheit diskutiert werden kann, um eine geeignete Vorgabe für Design und Implementierung zu erstellen. Sequenzdiagramme beschreiben den Austausch von Nachrichten zwischen Ausprägungen mittels Lebenslinien und stellen in der Regel einen Weg durch einen Entscheidungsbaum innerhalb eines Systemablaufes dar. Sie besitzen zwei Dimensionen: Die Vertikale repräsentiert die Zeit, auf der Horizontalen werden die Objekte eingetragen.
Jedes beteiligte Objekt wird als Rechteck dargestellt und eine gestrichelte vertikale Linie darunter, die Lebenslinie, symbolisiert dessen Existenz während eines einer bestimmten Zeit. Eine Nachricht wird in einem Sequenzdiagramm durch einen Pfeil dargestellt, wobei der Name der Nachricht über den Pfeil geschrieben wird. Synchrone Nachrichten werden mit einer gefüllten Pfeilspitze, asynchrone Nachrichten mit einer offenen Pfeilspitze gezeichnet. Nachrichten, die asynchronen Signalen entsprechen, werden gleich dargestellt wie asynchrone Operationsaufrufe. Der wesentliche Unterschied zwischen asynchronen und synchronen Nachrichten ist, dass die synchronen Nachrichten die ausgehende Lebenslinie für weitere Nachrichten „blockiert“ ist, bis diese eine Antwort erhalten hat. Dies ist bei asynchronen Nachrichten nicht der Fall. Die schmalen Rechtecke, die auf den Lebenslinien liegen, sind Aktivierungsbalken, die den „Focus of Control“ anzeigen, also jenen Bereich, in dem ein Objekt über den Kontrollfluss verfügt, und aktiv an Interaktionen beteiligt ist.
Bedingungen werden in eckigen Klammern angegeben, also in der Form [Bedingung] Operation {}
. Die genannte Operation wird somit nur dann aufgerufen, wenn die Bedingung erfüllt ist. Wiederholungen werden durch * [Bedingung] Operation {}
dargestellt.
Ein Sequenzdiagramm muss mit dem Klassendiagramm konsistent sein, d. h. alle Botschaften, die an ein Objekt einer Klasse gesendet werden, müssen im Klassendiagramm in der Operationsliste dieser Klasse enthalten sein.
Das Kommunikationsdiagramm entspricht dem Kollaborationsdiagramm der UML 1.X. Es ist umbenannt worden, da der Name Kollaborationsdiagramm irreführend ist. Es gibt in der UML zwar auch das Modellelement Kollaboration, dieses hat aber nichts mit dem „Kollaborationsdiagramm“ zu tun.
Ein Kommunikationsdiagramm dokumentiert die Zusammenarbeit von Objekten und steht dem Objektdiagramm sehr nahe. Im Gegensatz dazu modelliert es jedoch nicht eine Momentaufnahme der Systemstruktur, sondern zeigt, wie die Objekte für die Ausführung einer bestimmten Operation zusammenarbeiten. Neben den Links zwischen den Objekten zeigt es auch die Botschaften, die diese einander senden. Eine solche wird in Form eines Pfeiles, der auf das empfangende Objekt zeigt, an die Verbindung zwischen zwei Objekten eingetragen. Eine Beschriftung an dem Pfeil zeigt den Inhalt der Botschaft. In der Regel teilt die Botschaft dem empfangenden Objekt mit, dass es eine seiner Operationen ausführen soll.
Objekte, die während der Ausführung neu erzeugt werden, sind mit {new}
, Objekte, die während der Ausführung gelöscht werden, mit {destroyed}
gekennzeichnet. Objekte, die während der Ausführung sowohl erzeugt als auch wieder gelöscht werden, sind {transient}
. Analog dazu können Objektverbindungen, die im Laufe der Ausführung erstellt werden mit {new}
, gelöschte Links mit {destroyed}
und Verbindungen, die innerhalb des Szenario sowohl auf- als auch abgebaut werden, mit {transient}
beschriftet werden.[26]
Der Zustand eines Objekts wird durch seine Attributwerte festgelegt. Je nachdem, in welchem Zustand sich nun ein Objekt befindet, kann es auf gleiche eingehende Nachrichten unterschiedlich reagieren. Dieses Verhalten von Objekten kann durch Zustandsautomaten modelliert werden: Dabei handelt es sich um eine Menge von Zuständen und eine Übergangsfunktion, die abhängig vom momentanen Zustand und dem eingehenden Ereignis den Nachfolgezustand bestimmt.
Die Zustände werden im Zustandsdiagramm als abgerundete Rechtecke dargestellt und müssen unterschiedliche Namen haben. Ein Zustandsübergang (Transition) wird als Pfeil vom Ausgangszustand zum neuen Zustand repräsentiert. Eine Transition wird mit dem Namen des Ereignisses (Triggers) beschriftet, das diese Transition auslöst. Es gibt zwei besondere Zustände: den Startzustand und den Endzustand. Jeder Zustandsautomat kann jeweils nur einen Startzustand besitzen. Der Startzustand wird im Diagramm als schwarz gefüllter Kreis und der Endzustand als schwarz gefüllter Doppelkreis gekennzeichnet.[27]
Ziel des objektorientierten Design ist die Systemplanung mit Objekten, die sich gegenseitig beeinflussen und die Probleme der Programmierung zu lösen. Im Gegensatz etwa zum Pflichtenheft berücksichtigt der objektorientierte Design-Entwurf auch technische Aspekte des Systems und zielt auf die Realisierung der Anforderungen ab – und nicht auf deren Verständnis. Dieser Entwurf befindet sich aber noch auf einem höheren Abstraktionsniveau als die tatsächliche Implementierung in einer Programmiersprache.
Im Übergang von der Analyse in die Designphase werden das Analysemodell und die in ihm spezifizierten Klassen erweitert und verbessert. Es geht darum, ein Modell des zu implementierenden Programmsystems zu erhalten. Man modelliert eine spezifische Implementation im Lösungsbereich und seiner zugehörigen Hard- und Softwareumgebung. Beim Ansatz von Coad und Yourdon wird das OOD in vier Komponenten zerlegt, in denen das bisherige Analysemodell überarbeitet und erweitert wird: die Problembereichskomponente, die Kommunikationskomponente, die Datenmanagementkomponente und die Task-Management-Komponente.
In dieser Phase werden die Ergebnisse der Analysephase überarbeitet und verbessert, um die Implementation der Klassen vorzubereiten. So können beispielsweise Attribute, Objektbeziehungen und Klassen ergänzt oder gestrichen werden. Ziel ist es, in sich abgeschlossene Klassen adäquater Komplexität zu modellieren.
Nach Heide Balzert ist eine häufige, jedoch falsche Vorstellung, dass sich alle konkreten Objekte des Problembereichs im Analysemodell als Klasse wiederfinden. So führt beispielsweise die mangelnde Bildung von komplexen Attributen zu vielen kleinen Klassen und in der Folge zu vielen überflüssigen Assoziationen. Dies erschwert die Verständlichkeit des Gesamtmodells.[28]
Der Begriff Kopplung beschreibt die Verknüpfung zwischen Klassen und ist ein Maß, das die Stärke dieser Verknüpfungen bzw. der daraus resultierenden Abhängigkeiten beschreibt. Die Kopplung von Objekten durch Operationsaufrufe soll möglichst gering, aber so hoch wie nötig gehalten werden, um verständliche eigenständige Klassen zu erhalten, und die wünschenswerte Kohäsion von Klassen und ihren einzelnen Operationen.[29]
Die Kohäsion beschreibt, wie gut eine Klasse eine logische Aufgabe oder Einheit abbildet. In einem System mit starker Kohäsion ist jede Klasse für genau eine wohldefinierte Aufgabe oder Einheit verantwortlich. Das Single-Responsibility-Prinzip besagt, dass jede Klasse nur genau eine fest definierte Aufgabe zu erfüllen hat. Diese Aufgabe wird durch das Zusammenspiel aller Attribute und Methoden dieser Klasse erfüllt. Das Zusammenspiel der Attribute und Methoden dieser Klasse ist dadurch sehr eng. Man spricht von starker Kohäsion.
Herrscht eine zu schwache Kohäsion vor, führt dies unter anderem dazu, dass gemeinsame Funktionalitäten einer Klasse nicht wiederverwendet werden, sondern mehrfach umgesetzt werden. Code-Duplizierung ist somit ein Zeichen schwacher Kohäsion. Das DRY-Prinzip (Don't Repeat Yourself — ‚Wiederhole dich nicht‘) hilft, diese zu vermeiden.
Im Design sollte auch die Vererbungsstruktur überarbeitet werden. In der Analyse werden Operationen, die für mehrere Unterklassen gelten, so „hoch wie möglich“ in die Vererbungsstruktur eingefügt, sofern sie eine gemeinsame Beschreibung besitzen. Nach Balzert und Wirfs-Brock et al. empfiehlt es sich, so viele abstrakte Klassen wie möglich zu schaffen, weil dadurch das Hinzufügen neuer Klassen erleichtert wird. Eine abstrakte Klasse ist eine spezielle Klasse, welche sich nicht instanziieren lässt und die somit nur als Strukturelement innerhalb einer Klassenhierarchie dient. Dadurch wird das Konzept der Vererbung voll ausgenutzt.
Der Vererbungsmechanismus kann auch dazu verleiten, dass Attribute und Operationen nur zu dem Zweck in einer Klasse „gesammelt“ werden, um dem Programmierer Schreibaufwand zu sparen. Man spricht in diesem Zusammenhang auch von „Spaghetti Code“. Solche willkürlich geschaffenen Klassen lassen sich leicht erkennen: Der Klassenname besitzt keine Aussagefähigkeit oder steht in keiner Beziehung zu den Attributen und Operationen der Klasse.[30]
Die Entwurfstätigkeiten dieser Komponente beschäftigen sich damit, wie ein Benutzer das System bedient und wie umgekehrt das System dem Benutzer Resultate und Informationen präsentiert, weshalb sie auch Mensch-Computer-Kommunikationskomponente genannt wird. Dabei soll die Benutzeroberfläche direkt auf den späteren Anwender zugeschnitten werden. Dazu werden neue, auf der Systemgrenze liegende Klassen entwickelt.
Eine wichtige Ausgangslage für diese Designtätigkeit bilden die Szenarios aus der dynamischen Modellierung, für deren Klassen die ein- oder auszugebenden Attribute und die zugehörigen Zugriffsfunktionen bereits während der Analysephase definiert wurden. Zu bereits in der Analysephase festgelegten Attributen und Methoden kommen nun Details zu Layout, Benutzereingaben und dem Verhalten von Fenstern hinzu. Eine klare Trennung zwischen den Klassen der Kommunikationskomponente und den Klassen der Problembereichskomponente ist notwendig, um das System im Hinblick auf Modifikationen stabiler werden zu lassen.[31]
Beim Entwurf dieser Komponente werden die Datenaspekte des Systems studiert und die Voraussetzungen für das Abspeichern und Wiederauffinden von Objekten geschaffen. Wichtige Aspekte sind Integrität, d. h. die Verhinderung unautorisierter Modifikation von Informationen und Konsistenz, d. h. die Korrektheit der in der Datenbank gespeicherten Daten.
Persistente Objekte lassen sich auf drei verschiedene Arten aufbewahren:[32]
Diese Komponente wird zur Koordination der Objekte und ihrer Methoden entworfen, und zwar für den Fall, dass in dem System das Verhalten verschiedener Objekt parallel oder die Kommunikation zwischen den Objekten asynchron modelliert werden soll. Man entwirft dazu Klassen, die das Starten und Terminieren der unterschiedlichen Tasks (oder auch: Prozesse), die von diesen auszuführenden Aktivitäten und Aktionen, sowie Interprozesskommunikation und Taskprioritäten festlegen. Um die gleichzeitige oder scheinbar gleichzeitige Bearbeitung mehrerer Tasks realisieren zu können, muss eine Mehrprozessormaschine oder ein Multi-Tasking-Betriebssystem zur Verfügung stehen. In der Regel wird auf eine spezielle Task-Klassenbibliothek zurückgegriffen. Üblicherweise können Tasks die Zustände „running“, „suspended“ oder „terminated“ annehmen.[33]
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.