Model-View-Controller-Pattern: Unterschied zwischen den Versionen

aus GlossarWiki, der Glossar-Datenbank der Fachhochschule Augsburg
Wechseln zu:Navigation, Suche
 
(45 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 
{{MVC:Menü}}
 
{{MVC:Menü}}
=Definition=
+
==Definition==
Das [[Model-View-Controller-Paradigma]] oder [[Model-View-Controller-Paradigma|-Pattern]], kurz [[MVC]], bezeichnet ein [[Architekturmuster]], bei der eine [[Komponente (UML)|Anwendungs-Komponente]] in drei eigenständige Module unterteilt wird:
+
Ein [[Model-View-Controller-Pattern]], kurz [[MVC-Pattern]], bezeichnet ein [[Entwurfsmuster]], das
[[Model (MVC)|Model]] (Modell), [[View (MVC)|View]] (Darstellung, Präsentation) und [[Controller (MVC)|Controller]] (Steuerung).
+
auf dem [[Model-View-Controller-Paradigma]] beruht, das also für die MVC-Module  
 +
[[Model-View-Controller-Paradigma/Model|Model]], [[Model-View-Controller-Paradigma/View|View]] und [[Model-View-Controller-Paradigma/Controller|Controller]]
 +
geeignete [[Klasse (OOP)|Klassen]]- und [[Objekt (OOP)|Objekt]]-Strukturen definiert.
  
 +
==Verschiedene Realisierungsmöglichkeiten==
  
'''MVC-Paradigma'''
+
Es gibt mehrere Möglichkeiten, geeignete Klassen- und Objekt-Strukturen zu definieren,
 +
{{dh}}, es gibt mehrere MVC-Pattern-Varianten.
  
Man sagt, dass eine [[Anwendung]] oder ein [[Programmsystem]] auf dem
+
Zwei wichtige Aspekte, die dabei berücksichtigt werden müssen, sind die
[[Model-View-Controller-Paradigma|MVC-Paradigma]] beruht,
+
* '''Kommunikation''': Auf welche Arten kommunizieren die Module miteinander?
wenn das Prinzip der Aufteilung zentraler Komponenten
+
* '''Initialisierung''': Wie werden die Module initialisiert?
in die drei Module [[Model (MVC)|Model]], [[View (MVC)|View]] und [[Controller (MVC)|Controller]]
 
wesentlicher Bestandteil dieser Anwendung bzw. dieses Systems ist.
 
  
 +
Basierend auf diesen Vorüberlegungen sollen drei mögliche MVC-Pattern vorgestellt werden:
 +
* [[Model-View-Controller-Pattern/Singleton|Initialisierung mittels Singleton(s)]]  (weniger empfehlenswert)
 +
* [[Model-View-Controller-Pattern/Dependency Injection|Initialisierung mittels Dependency Injection]] (empfehlenswert)
 +
* [[Model-View-Controller-Pattern/Observer|Kommunikation ausschließlich mittels des Observer Patterns]] (empfehlenswert)
  
'''MVC-Pattern'''
+
==Kommunikation zwischen MVC-Modulen==
 +
[[Datei:VCM-Prozess 01.png|gerahmt|rechts|VCM-Prozess]]
 +
Ein wichtiges [[Programmierprinzip]] ist es, so wenige Abhängigkeiten wie möglich zu erzeugen (''few interfaces''), da Abhängigkeiten die Komplexität und die Fehleranfälligkeit erhöhen.
 +
Die Abhängigkeiten entstehen dadurch, dass die MVC-Module miteinander kommunizieren müssen.
  
Wenn darüber hinaus eine konkrete Struktur für die drei Module [[Model (MVC)|Model]], [[View (MVC)|View]] und [[Controller (MVC)|Controller]] vorgegeben ist (z.B. in Form von [[Klasse]]n-[[Template]]s), spricht man vom [[Model-View-Controller-Paradigma|MVC-Pattern]].
+
Für die Kommunikation zwischen zwei Modulen gibt es mehrere Möglichkeiten. Die wichtigsten davon sind:
 +
# [[Unicast-Nachricht]]en: Modul A ruft Methoden von Modul B direkt auf.
 +
# [[Multicast-Nachricht]]en: Modul A informiert alle Module, die als Nachrichtenempfänger angemeldet wurden, mit Hilfe von [[Signal]]en ([[Observer-Pattern]]).
 +
## Der Sender informiert mit einer Nachricht die Empfänger lediglich, dass sich etwas geändert hat. Die Empfänger müssen sich daraufhin die für sie wichtigen Informationen per direktem Zugriff vom Sender holen.
 +
## Der Sender schickt in der Nachricht detailierte Informationen mit, so dass der Empfänger danach nicht mehr auf den Sender zugreifen muss.
  
=Konzept=
+
Weitere Kommunikationsmöglichkeiten, wie {{zB}} [[Broadcast-Nachricht]]en,  die Kommunikation über globale Variablen (insbesondere über [[Klassenattribute]]) etc., sollten {{iAllg}} vermieden werden.
Es gibt keinen Standard, der festlegt, wie MVC umzusetzen ist. Je nach Anwendungsgebiet sind manche Module wichtiger als andere. Auch kann nicht pauschal festgelegt werden, welches Modul für welche Funktionen zuständig ist. Hier unterscheiden sich viele MVC-Realisierungen teilweise ziemlich deutlich.
+
Bei Broadcast-Nachrichten, die an eine Vielzahl von nicht-beteiligten Objekten gehen, muss jeder
 +
einzelne Empfäger entscheiden, ob die jweils empfangene Nachricht für ihn überhaupt von Interesse ist.  
 +
Bei globalen Variablen kann {{iAllg}} nur schwer nachvollzogen werden, wer welche Variablen zu Kommunikation nutzt oder ob bestimmte Variablen überhaupt noch zur Kommunikation benötigt werden. Der zugehörige Code wird im Laufe der Zeit im unwartbarer.
  
Im Prinzip lassen sich die Bereiche jedoch wie folgt eingrenzen:
+
==Initialisierung von MVC-Modulen==
  
==Model (Modell)==
+
Je nach Art der Kommunikation müssen die verschiedenen Module unterschiedlich initialisiert werden:
Das [[Model (MVC)|Modell]] speichert als zentrales Modul sämtliche Daten und enthält häufig auch die Anwendungslogik. Die Kommunikation nach außen (beispielsweise Zugriffe auf Datenbanken oder andere Anwendungen) findet im Allgemeinen ebenfalls im Modell statt (vergleiche aber [[Model-View-Controller-Service-Paradigma]]).
 
Zudem speichert das Modell den aktuellen Anwendungsstatus, also den Zustand, in dem sich die Anwendung bei der Interaktion mit dem Benutzer befindet.
 
  
Eine weitere Aufgabe des Modells ist es, andere Module (View und Controller) zu informieren, wenn sich der Zustand des Modells ändert. Änderungen werden i. Allg. unmittelbar mitgeteilt. Oftmals wird hierfür das [[Observer-Pattern]] verwendet.
+
# [[Unicast-Nachricht]]en: Modul A muss das Modul B kennen, bevor es mit diesem Modul kommunizieren kann.
 +
# [[Multicast-Nachricht]]en: Modul B muss sich bei Modul A als Empfänger anmelden oder es muss von dritter Seite angemeldet werden, bevor es Nachrichten von A empfängt.
 +
## Modul B muss Modul A kennen, wenn Modul B sich sebst als Empfänger bei Modul A anmelden muss oder wenn Modul B nach Empfang einer Nachricht weitere Informationen von Modul A erfragen muss.
 +
## Wenn Modul B von einem Dritten als Empfänger angemeldet wird und Modul A alle notwendigen Informationen in den Multicast-Nachrichten mitschickt, braucht Modul B das Modul A nicht zu kennen.
  
==View (Darstellung, Präsentation)==
+
==Das MVC-Pattern als 3-Schichten-Pattern==  
Das Präsentationsmodul ist für die Ausgabe der Modell-Daten zuständig. Es kann mehrere Darstellungen ein und desselben Modells geben, die die Modell-Daten auf unterschiedlichste Art und Weise repräsentieren (z.B. optisch, akustisch oder auch haptisch).
+
[[Datei:VCM-Schichtenarchitektur 01.png|gerahmt||rechts|Das MVC-Pattern als Spezialfall des [[Layer-Pattern]]s]]
  
Logische Sichten bleiben hingegen dem Modell vorbehalten. Zum Beispiel ist das Modell dafür zuständig, dass ein Administrator Zugriff auf andere (mehr) Daten hat als ein Redakteur oder Standard-Benutzer.
+
Man kann die drei MVC-Module in Schichten anordnen: In der untersten Schicht ist das Modell angesiedelt, darüber liegt der Controller
 +
und zuoberst die View.
  
==Controller (Steuerung)==
+
Das Layer- oder [[Layer-Pattern|Schichtenpattern]] erlaubt nur, dass höhere Schichten direkt auf tiefere zugreifen, aber nicht umgekehrt.
Die Steuerung nimmt Eingaben aus verschiedensten Quellen entgegen (z.B. Daten, die ein Benutzer über die View eingibt) und leitet diese bereinigt und normalisiert an das Modell weiter.  
+
Ordnet man die drei MVC-Module so an, wie zuvor beschrieben, darf die View sowohl auf den Controller als auch auf das Modell zugreifen
 
+
und der Controller auf das Modell. Das Modell darf dagegen auf kein anderes Modul direkt zugreifen.
Häufig wird die Anwendungslogik nicht im Modell, sondern im Controller implementiert.
+
 
+
Diese Schichteneinteilung ist sinnvoll. Wenn ein Modell, {{dh}} eine Abbildung eines Realitätsauschnitts auf ein Datenmodell, erstellt wird,
==Anmerkung==
+
ist weder festgelegt, wie die Manipulationen an diesem Modell realisiert werden, noch, auf welche Arten diese Daten den Benutzern
Gerade weil umstritten ist, ob die Anwendungslogik Bestandteil des Modells oder des Controllers ist, sollte man das Logik-Modul als eigenständiges Modul realisieren. Dies wird im [[View-Controller-Logic-Service-Data-Paaradigma|VCLSD-Paradigma]] umgesetzt.
+
präsentiert werden. Auch der Controller, der die Benutzereingaben verarbeitet, braucht nicht zu wissen, welche Views das Modell darstellen.
 
+
Eine View dagegen muss das Modell kennen, dessen Daten sie visualisiert. Außerdem muss sie einen geeigneten
= Der MVC-Prozess =
+
Controller kennen, wenn sie Benutzeraktionen, wie {{zB}} Mausklicks auf bestimmte Buttons, verarbeiten lassen will.
[[Medium:MVC-Prozess 01.png|gerahmt||rechts|MVC-Prozess (in Anlehnung an [[Reenskaug (2003)]], Slide 17 auf Seite 10, sowie [[Commons:File:MVC-Process.svg]])]]
 
Das MVC-Paradigma lässt sich sehr schön als Interaktionsprozess zwischen vier Teilnehmern darstellen: Die [[Anwendungsdomäne]] wird im so genannten Modell (Model) nachgebildet. Dieses informiert eine oder mehrere Views über jede Änderung des aktuellen Zustands. Dem Benutzer (User) wird der aktuelle Zustand des Modells von einer oder mehrere dieser Views präsentiert. Über die Steuerung (Controller) kann der Benutzer das Modell manipulieren, das heißt, dessen Zustand (und damit auch die zugehörigen Darstellungen) ändern.
 
  
== Beispiel Jump 'n' Run==
+
===Heterogene Kommunikationswelt: Unicast- und Multicast-Kommunikation===
In einem [[Jump 'n' Run|Jump-'n'-Run]]-Spiel werden im Modell Daten über
 
die Spielfigur (Position, Laufrichtung, Geschwindigkeit ...), die Gegner, die Gegenstände etc. gespeichert.
 
  
Das Darstellungsmodul visualisiert die Elemente des Spiels mit Hilfe von Bildern und Animationen (Walk cyles etc.).  
+
Die Drei-Schichten-Architektur legt folgendes Kommunikationsverhalten nahe:
Jede Änderung im Modell hat, sofern sie sich im für den Spieler sichtbaren Bereich befindet,
+
* Ein View-Objekt kommuniziert direkt mit den ihr zugeordneten Controller- und Modell-Objekten sowie evtl. mit anderen View-Objekten.
eine Anpassung der Darstellung zur Folge.
+
* Ein Controller-Objekt kommuniziert direkt mit den ihr zugeordneten Modell-Objekten sowie evtl. mit anderen Controller-Objekten.
 +
* Ein Modell komminiziert höchstens mit anderen Modellobjekten direkt. Mit allen anderen Objekten kommuniziert sie nur per Multicast.
  
Der Spieler steuert die Spielfigur mit Hilfe der Tastatur. Jeder Tastendruck wird vom Steuerungsmodul analysiert und  
+
Auf diese Weise ist sichergestellt, dass zunächst alle Modell-Objekte erzeugt und initialisert werden können, da dafür keine
zur Manipulation der Spielfigur an das Modell weitergeleitet.  
+
anderen Objekte bekannt sein müssen. Danach werden die Controller-Objekte erzeugt und initialisiert. Die Modell-Objekte,
 +
mit den die Controller kommunizieren, existieren zu diesem Zeitpunkt schon. Zu guter Letzt werden die View-Objekte erzeugt und initialisiert.
  
Man beachte, dass das Modell i. Allg. aktiv ist, d.h. seinen Zustand selbststädig auch ohne Manipulatation durch die Steuerkomponete verändern kann. Beispielsweise werden die gegnerischen Figuren, sofern es welche gibt, vom Modell selbst bewegt.
+
===Homogene Kommunikationswelt: Reine Multicast-Kommunikation===
  
= Erweiterung des MVC-Prozesses=
+
Ein zweite Möglichkeit wäre, alle Objekte per Multicast-Nachrichten kommunizieren zu lassen. Allerdings sollten in diesem Fall
[[Medium:MVC-Prozess 02.png|gerahmt|rechts|MVC-Prozess 2 (mit erweiterter Interaktion)]]
+
die Empfänger-Objekte jeweils von dritter Stelle, das heißt vom Initialisierungs-Modul, beim Sender registriert werden. Außerdem müssten in den
Im zurvor beschriebenen MVC-Prozess kommuniziert der Benutzer direkt mit der Steuerkomponete. Dies ist z.B. bei einer Tastatur-Steuerung, bei Verwendung von [[Webcam]] und Mikrofon oder bei einer Kommunikation über eine Daten-Schnittstelle (wie z.B. eine [[serielle Schnittstelle]] oder einen [[USB-Controller]]) möglich.  
+
Multicast-Nachrichten alle
 +
wesentlichen Informationen mitgeschickt werden. Anderenfalls müsste beispielsweise ein Modell-Objekt alle Controller kennen,
 +
die mit diesen Modell-Objekt kommunizieren wollen: Entweder, um sich
 +
als Nachrichtenempfänger bei „seinen“ Controllern zu regisrieren, oder, um,  sobald Nachrichten vom Controller eintreffen,
 +
nähere Informationen vom Controller einholen zu können, welche Änderungen am Modell eigentlich vorgenommen werden sollen.
  
Meist werden jedoch dem Benutzer Interaktionselemente (wie Button, Slider und Texteingabe-Felder) über eine View präsentiert. In so einem Fall sollte die Darstellungkomponete die Benutzereingaben nicht selbst verarbeiten, sondern an ein zuständiges Steuerungsmodul weiterleiten.
+
==Drei verschiedene Arten von MVCS-Pattern==
  
Eine weitere Verfeinerung des vzuvor beschriebenen Prozessablaufs wird bei der Kommunikation zwischen Modell und Controller vorgenommen:
+
===Initialisierung mittels Singleton(s)===
Das Modell kann nicht nur die View, sondern auch die auch
+
Bei [[Model-View-Controller-Pattern/Singleton|diesem Pattern]]
die Steuerung direkt über Änderungen informieren, damit dieser dem User gegebenfalls ein Feedback (z.B. [[Force Feedback]]) geben kann. Hier
+
kommunizeren ebenfalls nur die Modell-Objekte mittels Multicast-Nachrichten. Die
kann man allerdings auch argumentieren, dass diese Art der Informations-„Visualisierung“ Aufgabe einer View wäre. Das heißt,
+
anderen Objekte kommunizieren mittels Unicast-Nachrichten.
im Allgemeinen kann die Steuerung darauf verzichten, auf Modellereignisse zu hören und zu reagieren.
 
  
== Beispiel Warenkorb==
+
Initialisiert werden alle Module mittels Zugriffen auf ein oder mehrere [[Singelton-Pattern|Singleton-Klassen]].
In einer [[Warenkorb]]-Anwendung werden im Modell Daten über
 
den Warenkorb und — sobald sich der Besteller eingeloggt hat — den zugehörigen Besitzer gespeichert: der Warenkatalog, eine aktuelle Auswahl des Warenkataloges,
 
der Inhalt des Warenkorbs, der Gesamtpreis der Waren im Warenkorb, die Anschrift des Bestellers etc.
 
Die Modelldaten oder zumindest Teile davon (wie z.B. der Warenkatalog) werden häufig  in einer Datenbank abgelegt (siehe auch [[Model-View-Controller-Service-Paradigma]]).
 
  
Ein Darstellungsmodul visualisiert Modelldaten, wie z.B. die aktuelle Auswahl des Warenkataloges, mit Hilfe von Texten, Bildern und Videos.
+
Der Nachteil dieses Patterns ist, dass die Singleton-Klassen wie globale Variablen wirken. Daher sollte
Der Benutzer kann die Auswahl der visualierten Elemente durch Filter oder Navigation abändern, er kann
+
auf diese Art der Realisierung im Allgemeinen verzichtet werden.
Elemente des Kataloges in seinen Warenkorb legen und dort wieder entfernen etc. Für all diese Aktionen werden
 
dem Benutzer in der View spezielle Eingabefelder ([Checkbox]]es, [[Drop-Down-Menü]]s, [[Textfeld]]er, [[Link]]s etc.) angeboten.
 
Jedes mal, wenn der Benutzer eines dieser Elemente mit Hilfe der Maus oder der Tastatur bedient, leitet das
 
zugehörige Darstellungsmodul eine entsprechende Nachricht an die Steuerung weiter.
 
  
Die Steuerung analysiert die geünschte Aktion des Benutzers und führt die entsprechenden Änderungen im Modell durch.
+
Details siehe: [[Model-View-Controller-Pattern/Singleton|DMVC-Pattern: Initialisierung mittels Singleton(s)]]
Zum Beispiel kann sie veranlassen, dass die aktuelle Auswahl des Warenkataloges den Wünschen des Benutzers gemäß geändert wird.
 
  
= Kommunikation zwischen zwei MVC-Komponenten=
+
===Initialisierung mittels Dependency Injection===
Auch der verfeinerte MVC-Prozess beschreibt das allgemeine Vorgehen häufig etwas ungenau. Viele Anwendungen bestehen aus mehreren MVC-Komponenten:
+
Bei [[Model-View-Controller-Pattern/Dependency Injection|diesem Pattern]] 
Eine oder mehrere Kernanwendungen (Domain-Komponenten) sowie einer Rahmenanwendung (Frame-Komponente), die den Zugang zu und zwischen den Kernanwendungen steuert.
+
kommunizeren nur die Modell-Objekte mittels Multicast-Nachrichten. Die  
In diesem Fall gibt es mehrere relativ unabhängige MVC-Prozesse. Die äußeren Komponenten (wie z.B. die Rahmenkomponente) können dabei mit den inneren Komponenten (wie z.B. die Kernkomponenten) kommunizieren.
+
anderen Objekte kommunizieren mittels Unicast-Nachrichten.
Der umgekehrte Weg sollte vermieden werden, damit Kernkomponenten problemlos in andere Umgebungen integriert werden können.
 
[[Medium:MVC-Prozess 03.png|gerahmt|links|MVC-Prozess 3 (mit Trennung in innere und äußere MVC-Komponenten)]]
 
  
Man beachte, dass die innere View in die äußere View eingebettet werden kann. Ansonsten sind die einzelnen Komponenten
+
Initialisiert werden alle Module mittels [[Dependency Injection]].
möglichst eigenständig und kommunizieren nur über wohldefinierte und möglichst schlanke Schnittstellen miteinander.  
 
  
== Beispiel Jump-'n'-Run-Spiel mit Trainingsmodus und Highscore==
+
Der Nachteil dieses Patterns ist, dass View- und Controller-Module ihre Kommunikationspartner kennen müssen.
 +
Dies widerspricht dem [[Programmierprinzip]], die Schnittstellen möglichst klein zu halten (small interfaces).
 +
Allerdings kann man dieses Problem abmildern, wenn man für jeden Kommunikationskanal eigene,
 +
möglichst schlanke Kommunikationsschnittstellen definiert.
  
Man kann das Jump-'n'-Run-Spiel aus dem ersten Beispiel als Kernanwendung in einen Rahmen einbetten, der den Zugang zu diesem Spiel ermöglicht.
+
Details siehe: [[Model-View-Controller-Pattern/Dependency Injection|MVC-Pattern: Initialisierung mittels Dependency Injection]]
Zum Beispiel kann die Rahmenanwendung verlangen, dass sich der Benutzer erst anmelden muss, bevor er mit dem Spiel beginnen kann.
 
Danach kann der Benutzer wählen, ob er ein neues Spiel starten, ein altes Spiel fortsetzen oder ein bestimmtes Level im
 
Trainigsmodus üben will. Die Rahmenanwendung kann darüber hinaus das Spiel mit einer Highscore-Anwendung (eine weitere Kernanwendung) koppeln,
 
die für beliebige Spiele benutzerspezifische Scores sowie jeweils einen Highscore verwaltet.
 
  
Wenn der Benutzer zum Beispiel den Trainigsmodus aktivieren möchte, kann die Steuerung der Rahmenkomponente zunächst mit Hilfe der Highscore-Anwendung ermitteln,
+
===Kommunikation ausschließlich mittels des Observer-Patterns===
ob der Benutzer schon genügend Punkte erspielt hat. Hierzu muss der die Highscore-Steuerung veranlassen, die gewünschten Daten im Higscore-Modell bereit zu stellen. Die Rahmen-Steuerung greift dann über das Rahmen-Modell darauf zu. Anschließend, sofern der Benutzer bereits genügnd Spielerfahrung hat, leitet die Rahmen-Steuerung den Wunsch nach Aktivierung des Trainingsmoduses Steurung des Spiels weiter.
+
Bei [[Model-View-Controller-Pattern/Observer|diesem Pattern]] 
 +
kommunizeren alle MVC-Objekte mittels Multicast-Nachrichten (die alle notwendigen Informationen
 +
beeinhalten, so dass der Empfänger nie beim Sender rückfragen muss).
  
=MVC-Pattern: Verschiedene Realisierungsmöglichkeiten=
+
Die Zuweisung der Nachrichten-Sender zu ihren Nachrichten-Empfängern erfolgt während der Initialisierungsphase
 +
von außerhalb. Das heißt, die einzelnen MVC-Objekte kennen einander nicht.
  
Es gibt mehrere Möglichkeiten für das MVC-Pattern geeignete Klassen-Templtes zu definieren.
+
Der Nachteil dieses Patterns ist, dass die eine Multicast-Kommunikation weniger effizient ist, als eine Unicast-Kommunikation.
Zwei wichtige Aspekte, die dabei berücksichtigt werden müssen, sind die
+
In zeitkritischen Anwendungen kann dies evtl. zu Problemen führen.
* [[Model-View-Controller-Pattern/Initialisierung|Initialiserung der Module]]
 
* [[Model-View-Controller-Pattern/Kommunikation|Kommunikation zwischen den Modulen]]
 
 
Basierend auf diesen Vorüberlegungen sollen drei mögliche MVC-Pattern vorgestellt werden:
 
* [[Model-View-Controller-Pattern/Dependency Injection|Initialiserung mittels Depenceny Injection]]
 
* [[Model-View-Controller-Pattern/Singleton|Initialiserung mittels Singleton(s)]]
 
* [[Model-View-Controller-Pattern/Observer|Kommunikation ausschließlich mittels des Observer Patterns]]
 
  
=Bemerkungen=
+
Details siehe: [[Model-View-Controller-Pattern/Observer|MVC-Pattern: Kommunikation ausschließlich mittels des Observer Patterns]]
==Vorteile==
 
Das MVC-Paradigma ermöglicht ein flexibles Programmdesign, welches die Wiederverwendbarkeit der einzelnen MVC-Module und komplexer MVC-Komponenten sowie eine daraus resultierende reduzierte Gesamtkomplexität gewährleistet, insbesondere bei großen Anwendungen. Folgende Vorteile ergeben sich insbesondere:
 
  
* Die Anwendungslogik ist von den dazugehörenden Darstellungen und den Benutzerinteraktionen klar getrennt: [[Seapration of Concern]].
+
==Quellen==
* Ein Modell kann durch viele Darstellungsmodule repräsentiert werden (z.B. Detail-View und Übersichts-View wie z.B. eine Landkarte mit Akteuren, spielerspezifische Views bei Multiuser-Spielen, vierschiedene Ansichten eines 3D-Modells etc.).
+
<ol>
* Bei Multiuser-Spielen muss nur das Modell auf allen beteiligten Rechnenr synchronisiert werden. Eine realtive geringe Bandbreite reicht zur Übertragung aus.
+
<li>{{Quelle|Gamma, E.; Helm, R.; Johnson, R.; Vlissides, J. (1995): Design Patterns}}</li>
* Bestehende Systeme können einfach erweitert werden, indem neue Module und MVC-Komponenten hinzugefügt werden.
+
<li>{{Quelle|Kowarschick, W.: Multimedia-Programmierung}}</li>
 +
</ol>
  
==Nachteile==
+
==Siehe auch==
* Bei kleinen Anwendungen bedeutet der Einsatz von MVC einen gewissen Mehraufwand.
+
*[[Model-View-Controller-Paradigma]]
 
 
==Geschichte==
 
In den Anfängen der Informatik war es nicht unüblich [[Spaghetti-Code]] zu entwickeln, was mit vielen Nachteilen verbunden ist. Erst die Einführung der strukturierten Programmierung in den 70er-Jahren und später die objektorientierte Programmierung in den 80er-Jahren schaffte Abhilfe und ermöglichte das Programmieren nach dem Model-View-Controller-Paradigma.
 
 
 
Ursprünglich wurde das MVC-Paradigma 1978/79 von der Firma Xerox für die [[GUI]]-Programmierung eingeführt. Zum Einsatz kam die damals ebenfalls von Xerox entwickelte [[Objektorientierung|objektorientierte]] Programmiersprache [[Smalltalk]].
 
 
 
In neueren Programmiersprachen wie [[Java]] kommt MVC ebenfalls bei der [[GUI]]-Programmierung zum Einsatz. MVC ist heute allgemeiner Standard beim Entwurf komplexer Softwaresysteme, bei denen die Anwendungslogik von anderen Teilen des Systems getrennt werden soll.
 
 
 
=Anwendungsgebiete=
 
* Allgemein: größere Softwareprojekte
 
* [[GUI]]-Programmierung (bspw. [[Framework|Frameworks]] wie [[Swing|Swing]])
 
* Web-Anwendungen (bspw. [[Framework|Frameworks]] wie [[Ruby on Rails]])
 
* [[Model-View-Controller-Paradigma/Umsetzungen|Beispiele für Umsetzungen des Model-View-Controller-Paradigmas]]
 
 
 
=Kommunikation zwischen den MVC-Modulen=
 
[[Medium:MVC-Prozess 02b.png|gerahmt|rechts|MVC-Prozess: Kommunikation]]
 
Ein wichtiges [[Programmierprinzip]] ist es, so wenige Abhängigkeiten wie möglich zu erzeugen (''few interfaces''), da Abhängigkeiten die Komplexität und die Fehleranfälligkeit erhöhen.
 
Die Abhängigkeiten entstehen dadurch, dass die MVC-Module miteinander kommunizieren müssen.
 
 
 
Für die Kommunikation zwischen den drei MVC-Modulen „Model“, „View“ und „Controller“ gibt es mehrere Möglichkeiten:
 
# Ein Modul hat direkten Zugriffe auf ein zweites (durchgezogene Linie im Diagramm „MVC-Prozess 2b“).
 
# Ein Modul (Sender) informiert beliebig viele andere Module (Empfänger) mit Hilfe von [[Multicast]]-Nachrichten ([[Observer-Pattern]], gestrichelte Linie im Diagramm „MVC-Prozess 2b“).
 
## Der Sender informiert mit der Nachricht die Empfänger lediglich, dass sich etwas geändert hat. Die Empfänger müssen sich daraufhin die für sie wichtigen Information per direktem Zugriff vom Sender holen.
 
## Der Sender schickt in der Nachricht detailierte Informationen mit, so dass der Empfänger nicht noch einmal auf den Sender zugreifen muss.
 
 
 
Ein Modellmodul sollte vollkommen unabhängig von anderen Modulen existieren. Es stellt lediglich Methoden zur Verfügung, mit deren Hilfe irgendwelche Steuerungsmodule die Daten des Modells manipulieren können. Mit Hilfe von Mulitcast-Nachrichten ''informiert'' ein Modell die übrigen Module über erfolgte Änderungen. Dabei muss sich der Programmierer entscheiden, ob mit einer derartigen Nachricht detailierte Informationen über die Änderungen mitgeschickt werden (2.2) oder nicht (2.1).
 
 
 
Man beachte, dass bei der Implementierung eines Modellmoduls weder die Steuerungs- noch die Darstellungsmodule bekannt sein müssen.
 
 
 
Ein Darstellungmodul lauscht auf Nachrichten einer oderer mehrerer Modellmodule. Es muss diese Modelle kennen, wenn es sich dort selbst zum Nachrichten-Empfang anmelden muss und/oder – sofern
 
die Nachrichten nicht schon alle wesentlichen Änderungsdaten enthalten – um nähere Informationen über die aktuelle Änderung vom Sendermodell einholen zu können.
 
 
 
Interaktive Darstellungsmodulen müssen außerdem die zugehörigen Steuerungsmodule über User-Aktionen informieren. Dies kann entweder direkt (1.) oder mit Hilfe von Multicast-Nachrichten erfolgen (2.).
 
Im ersten Fall müssen das Darstellungsmodule die zugehörigen Steuerungsmodule kennen, damit sie diese direkt informieren können. Im zweiten Fall müssen dagegen die Steuerungsmodule die zugehörigen Darstellungsmodule kennen, bei denen sie sich als Empfänger anmelden und gegebenfalls Detail-Informationen zu bestimmten Änderungen erfragen. Im Allgemeinen sollte der ersten Variante der Vorzug gegeben werden,
 
da es mehere View-Module kann, aber meist nur ein Controller-Modul gibt. Bei der zweiten Variante müsste der Controller jedesmal
 
angepasst werden, wenn sich die Anzahl der View verändert. 
 
 
 
Aus Gründen der Modularität sollten diejenigen Darstellungsmodule, die lediglich Modelldaten visualisieren, und die Darstellungsmodule mit interaktiven Elementen möglichst getrennt realisiert werden. 
 
 
 
Ein Steuerungsmodul schließlich manipuliert ein oder mehrere Modellmodule. Dies sollte stets per direktem Zugriff erfolgen, damit die Modellfunktionalität nicht von der Existenz spezieller Steuerungsmodule abhängt.
 
 
 
=Quellen=
 
 
<noinclude>
 
<noinclude>
* [[Kowarschick, W.: Multimedia-Programmierung]]</noinclude>
+
[[Kategorie:MVC]]
* [[Reenskaug, T. (1979): Thing-Model-View-Editor]] (Erste Notiz mit exemplarischen Beispielen)
+
[[Kategorie:Objektorientierte Programmierung]]
* [[Reenskaug, T. (1979a): Models-Views-Controllers]] (Grundlegende Definition von MVC)
+
[[Kategorie:Glossar]]
* [[Reenskaug, T. (2003): The Model-View-Controller (MVC). Its Past and Present]]
 
* [[Stoiber, D. (2005): Implementierung des Model-View-Controller Paradigmas]]
 
* [http://www.martinfowler.com/eaaDev/uiArchs.html Martin Fowler: GUI Architectures]
 
* [[WikipediaEN:Model–view–controller]]
 
* [[Wikipedia:Model View Controller]]
 
 
 
=Siehe auch=
 
*[[Model-View-Controller-Paradigma/Umsetzungen]]
 
*[[Model-View-Controller-Service-Paradigma]]
 
*[[View-Controller-Logic-Service-Data-Paradigma]]
 
*[http://heim.ifi.uio.no/~trygver/index.html Homepage von Trygve M. H. Reenskaug, Erfinder von MVC]
 
*[http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html Reenskaugs eigene Seite über MVC ]
 
*[[Wikipedia:Model View_Controller]]
 
*[http://joeberkovitz.com/blog/reviewtube/ Joe Berkovitz: MVCS]<noinclude>[[Kategorie:Objektorientierte Programmierung]]
 
[[Kategorie:Glossar]][[Kategorie:MVC]]
 
 
[[en:MVC]]
 
[[en:MVC]]
 
[[Kategorie:Kapitel:Multimedia-Programmierung]]
 
[[Kategorie:Kapitel:Multimedia-Programmierung]]
{{{{SITENAME}}-konformer Artikel}}</noinclude>
+
</noinclude>

Aktuelle Version vom 22. September 2017, 15:50 Uhr

Dieser Artikel erfüllt die GlossarWiki-Qualitätsanforderungen nur teilweise:

Korrektheit: 4
(großteils überprüft)
Umfang: 3
(einige wichtige Fakten fehlen)
Quellenangaben: 4
(fast vollständig vorhanden)
Quellenarten: 4
(sehr gut)
Konformität: 4
(sehr gut)

Diese Bewertungen beziehen sich auf alle im nachfolgenden Menü genannten Artikel gleichermaßen.

1 Definition

Ein Model-View-Controller-Pattern, kurz MVC-Pattern, bezeichnet ein Entwurfsmuster, das auf dem Model-View-Controller-Paradigma beruht, das also für die MVC-Module Model, View und Controller geeignete Klassen- und Objekt-Strukturen definiert.

2 Verschiedene Realisierungsmöglichkeiten

Es gibt mehrere Möglichkeiten, geeignete Klassen- und Objekt-Strukturen zu definieren, d. h., es gibt mehrere MVC-Pattern-Varianten.

Zwei wichtige Aspekte, die dabei berücksichtigt werden müssen, sind die

  • Kommunikation: Auf welche Arten kommunizieren die Module miteinander?
  • Initialisierung: Wie werden die Module initialisiert?

Basierend auf diesen Vorüberlegungen sollen drei mögliche MVC-Pattern vorgestellt werden:

3 Kommunikation zwischen MVC-Modulen

VCM-Prozess

Ein wichtiges Programmierprinzip ist es, so wenige Abhängigkeiten wie möglich zu erzeugen (few interfaces), da Abhängigkeiten die Komplexität und die Fehleranfälligkeit erhöhen. Die Abhängigkeiten entstehen dadurch, dass die MVC-Module miteinander kommunizieren müssen.

Für die Kommunikation zwischen zwei Modulen gibt es mehrere Möglichkeiten. Die wichtigsten davon sind:

  1. Unicast-Nachrichten: Modul A ruft Methoden von Modul B direkt auf.
  2. Multicast-Nachrichten: Modul A informiert alle Module, die als Nachrichtenempfänger angemeldet wurden, mit Hilfe von Signalen (Observer-Pattern).
    1. Der Sender informiert mit einer Nachricht die Empfänger lediglich, dass sich etwas geändert hat. Die Empfänger müssen sich daraufhin die für sie wichtigen Informationen per direktem Zugriff vom Sender holen.
    2. Der Sender schickt in der Nachricht detailierte Informationen mit, so dass der Empfänger danach nicht mehr auf den Sender zugreifen muss.

Weitere Kommunikationsmöglichkeiten, wie z. B. Broadcast-Nachrichten, die Kommunikation über globale Variablen (insbesondere über Klassenattribute) etc., sollten i. Allg. vermieden werden. Bei Broadcast-Nachrichten, die an eine Vielzahl von nicht-beteiligten Objekten gehen, muss jeder einzelne Empfäger entscheiden, ob die jweils empfangene Nachricht für ihn überhaupt von Interesse ist. Bei globalen Variablen kann i. Allg. nur schwer nachvollzogen werden, wer welche Variablen zu Kommunikation nutzt oder ob bestimmte Variablen überhaupt noch zur Kommunikation benötigt werden. Der zugehörige Code wird im Laufe der Zeit im unwartbarer.

4 Initialisierung von MVC-Modulen

Je nach Art der Kommunikation müssen die verschiedenen Module unterschiedlich initialisiert werden:

  1. Unicast-Nachrichten: Modul A muss das Modul B kennen, bevor es mit diesem Modul kommunizieren kann.
  2. Multicast-Nachrichten: Modul B muss sich bei Modul A als Empfänger anmelden oder es muss von dritter Seite angemeldet werden, bevor es Nachrichten von A empfängt.
    1. Modul B muss Modul A kennen, wenn Modul B sich sebst als Empfänger bei Modul A anmelden muss oder wenn Modul B nach Empfang einer Nachricht weitere Informationen von Modul A erfragen muss.
    2. Wenn Modul B von einem Dritten als Empfänger angemeldet wird und Modul A alle notwendigen Informationen in den Multicast-Nachrichten mitschickt, braucht Modul B das Modul A nicht zu kennen.

5 Das MVC-Pattern als 3-Schichten-Pattern

Das MVC-Pattern als Spezialfall des Layer-Patterns

Man kann die drei MVC-Module in Schichten anordnen: In der untersten Schicht ist das Modell angesiedelt, darüber liegt der Controller und zuoberst die View.

Das Layer- oder Schichtenpattern erlaubt nur, dass höhere Schichten direkt auf tiefere zugreifen, aber nicht umgekehrt. Ordnet man die drei MVC-Module so an, wie zuvor beschrieben, darf die View sowohl auf den Controller als auch auf das Modell zugreifen und der Controller auf das Modell. Das Modell darf dagegen auf kein anderes Modul direkt zugreifen.

Diese Schichteneinteilung ist sinnvoll. Wenn ein Modell, d. h. eine Abbildung eines Realitätsauschnitts auf ein Datenmodell, erstellt wird, ist weder festgelegt, wie die Manipulationen an diesem Modell realisiert werden, noch, auf welche Arten diese Daten den Benutzern präsentiert werden. Auch der Controller, der die Benutzereingaben verarbeitet, braucht nicht zu wissen, welche Views das Modell darstellen. Eine View dagegen muss das Modell kennen, dessen Daten sie visualisiert. Außerdem muss sie einen geeigneten Controller kennen, wenn sie Benutzeraktionen, wie z. B. Mausklicks auf bestimmte Buttons, verarbeiten lassen will.

5.1 Heterogene Kommunikationswelt: Unicast- und Multicast-Kommunikation

Die Drei-Schichten-Architektur legt folgendes Kommunikationsverhalten nahe:

  • Ein View-Objekt kommuniziert direkt mit den ihr zugeordneten Controller- und Modell-Objekten sowie evtl. mit anderen View-Objekten.
  • Ein Controller-Objekt kommuniziert direkt mit den ihr zugeordneten Modell-Objekten sowie evtl. mit anderen Controller-Objekten.
  • Ein Modell komminiziert höchstens mit anderen Modellobjekten direkt. Mit allen anderen Objekten kommuniziert sie nur per Multicast.

Auf diese Weise ist sichergestellt, dass zunächst alle Modell-Objekte erzeugt und initialisert werden können, da dafür keine anderen Objekte bekannt sein müssen. Danach werden die Controller-Objekte erzeugt und initialisiert. Die Modell-Objekte, mit den die Controller kommunizieren, existieren zu diesem Zeitpunkt schon. Zu guter Letzt werden die View-Objekte erzeugt und initialisiert.

5.2 Homogene Kommunikationswelt: Reine Multicast-Kommunikation

Ein zweite Möglichkeit wäre, alle Objekte per Multicast-Nachrichten kommunizieren zu lassen. Allerdings sollten in diesem Fall die Empfänger-Objekte jeweils von dritter Stelle, das heißt vom Initialisierungs-Modul, beim Sender registriert werden. Außerdem müssten in den Multicast-Nachrichten alle wesentlichen Informationen mitgeschickt werden. Anderenfalls müsste beispielsweise ein Modell-Objekt alle Controller kennen, die mit diesen Modell-Objekt kommunizieren wollen: Entweder, um sich als Nachrichtenempfänger bei „seinen“ Controllern zu regisrieren, oder, um, sobald Nachrichten vom Controller eintreffen, nähere Informationen vom Controller einholen zu können, welche Änderungen am Modell eigentlich vorgenommen werden sollen.

6 Drei verschiedene Arten von MVCS-Pattern

6.1 Initialisierung mittels Singleton(s)

Bei diesem Pattern kommunizeren ebenfalls nur die Modell-Objekte mittels Multicast-Nachrichten. Die anderen Objekte kommunizieren mittels Unicast-Nachrichten.

Initialisiert werden alle Module mittels Zugriffen auf ein oder mehrere Singleton-Klassen.

Der Nachteil dieses Patterns ist, dass die Singleton-Klassen wie globale Variablen wirken. Daher sollte auf diese Art der Realisierung im Allgemeinen verzichtet werden.

Details siehe: DMVC-Pattern: Initialisierung mittels Singleton(s)

6.2 Initialisierung mittels Dependency Injection

Bei diesem Pattern kommunizeren nur die Modell-Objekte mittels Multicast-Nachrichten. Die anderen Objekte kommunizieren mittels Unicast-Nachrichten.

Initialisiert werden alle Module mittels Dependency Injection.

Der Nachteil dieses Patterns ist, dass View- und Controller-Module ihre Kommunikationspartner kennen müssen. Dies widerspricht dem Programmierprinzip, die Schnittstellen möglichst klein zu halten (small interfaces). Allerdings kann man dieses Problem abmildern, wenn man für jeden Kommunikationskanal eigene, möglichst schlanke Kommunikationsschnittstellen definiert.

Details siehe: MVC-Pattern: Initialisierung mittels Dependency Injection

6.3 Kommunikation ausschließlich mittels des Observer-Patterns

Bei diesem Pattern kommunizeren alle MVC-Objekte mittels Multicast-Nachrichten (die alle notwendigen Informationen beeinhalten, so dass der Empfänger nie beim Sender rückfragen muss).

Die Zuweisung der Nachrichten-Sender zu ihren Nachrichten-Empfängern erfolgt während der Initialisierungsphase von außerhalb. Das heißt, die einzelnen MVC-Objekte kennen einander nicht.

Der Nachteil dieses Patterns ist, dass die eine Multicast-Kommunikation weniger effizient ist, als eine Unicast-Kommunikation. In zeitkritischen Anwendungen kann dies evtl. zu Problemen führen.

Details siehe: MVC-Pattern: Kommunikation ausschließlich mittels des Observer Patterns

7 Quellen

  1. Gamma et al. (1995): Erich Gamma, Richard Helm, Ralph Johnson und John Vlissides; Design Patterns – Elements of Reusable Object-Oriented Software; Auflage: 1; Verlag: Addison-Wesley Longman; Adresse: Amsterdam; ISBN: 0201633612; 1995; Quellengüte: 5 (Buch)
  2. Kowarschick (MMProg): Wolfgang Kowarschick; Vorlesung „Multimedia-Programmierung“; Hochschule: Hochschule Augsburg; Adresse: Augsburg; Web-Link; 2018; Quellengüte: 3 (Vorlesung)

8 Siehe auch