Posted on 2 Comments

Model View Controller

Model View Controller

Model View Controller ist ein Muster (engl.: Pattern) in der Softwareentwicklung, das insbesondere für die Entwicklung von Programmen mit Benutzeroberflächen verwendet wird. Bei dem Muster wird die Software in drei unabhängige, in sich geschlossene Komponenten unterteilt: Das Model (dt. Modell), den View (dt. Präsentation) und den Controller (dt. etwa die Programmsteuerung). Die Komponenten interagieren miteinander, um die Gesamtfunktionalität der Software umzusetzen.

Das MVC Pattern war ursprünglich für die klare Abgrenzung zwischen Daten, deren Darstellung und den Nutzerinteraktionen für GUIs (engl.: graphical user interfaces, dt.: graphische Benutzeroberflächen) gedacht. Mittlerweile ist es eines der am weitesten verbreiteten Muster für die Präsentationsschicht von Software und findet insbesondere im Rahmen der Webentwicklung Anwendung. In diesem Blogartikel wollen wir kurz auf die Geschichte und Anwendung des Musters eingehen und anschließend klären, wie es funktioniert, welche Ausprägungen es gibt und welche Vor- und Nachteile seine Verwendung mit sich bringt.

Historie und Verwendung des MVC Pattern

Das MVC Pattern wurde ursprünglich in den 70er und 80er Jahren für die objektorientierte Sprache Smalltalk entwickelt. Es war eines der ersten Muster, das Software im Hinblick auf die Verantwortlichkeiten der einzelnen Komponenten betrachtete, und diente vor allem der sauberen Trennung von Daten- und Präsentationsschicht. Die Definitionen, die damals für das MVC Pattern und seine Komponenten verwendet wurden, haben sich heutzutage weiterentwickelt – maßgeblich durch den stärkeren Fokus auf Webanwendungen und die steigende Komplexität von Softwarearchitekturen.

Mittlerweile gibt es Frameworks in verschiedenen Sprachen, die die Umsetzung von MVC erleichtern oder sogar erzwingen. Dazu gehören die Frameworks Spring für Java, Django für Python, Rails für Ruby oder ASP.NET MVC für C#. Im Kontext von Webanwendungen unterscheidet man außerdem thin client-Anwendungen, also Software, bei der alle Komponenten auf dem Server laufen, und Anwendungen, bei denen ein Teil des Codes clientseitig im Browser ausgeführt wird. Die Frameworks ASP.NET MVC, Django oder Rails unterstützen beispielsweise eine rein serverseitige Umsetzung von MVC, während AngularJS und viele weitere JavaScript-Frameworks auch die Ausführung von clientseitigem Code erlauben.

Die Komponenten des MVC Pattern

Wie bereits erwähnt gibt es in einer Model View Controller-Architektur die drei namensgebenden Komponenten Model, View und Controller. Diese haben folgende Funktionen und Verantwortlichkeiten:

  • Model (Modell): Das Model ist der Kern des Musters und beschreibt die Datenstruktur und die Daten, die unabhängig von der Nutzeroberfläche existieren. Grundsätzlich muss das Model darstellbar sein, einen Zustand verwalten und den Zustand auf Anfragen hin ändern können. In modernen Umsetzungen des MVC Patterns kann das Model neben einfacher Datenmanipulation auch Geschäftslogik enthalten und umfasst die Datenquellen wie beispielsweise eine relationale Datenbank.
  • View (Präsentation): Der View ist die optische Darstellung des Models für den Nutzer. Der View kennt das Model, ist aber nicht dafür zuständig, die Daten zu verarbeiten und enthält keinerlei fachliche Logik – er soll also möglichst „dumm“ sein. Es kann für eine Information mehrere Views geben, beispielsweise in Form von unterschiedlichen Diagrammen für denselben Datensatz.

Der View ist außerdem die Komponente, mit der der Nutzer auf oberster Ebene interagiert. Insbesondere in der Webentwicklung werden deswegen einfache Validierungen des Inputs im View durchgeführt, auch wenn diese klassischerweise nicht als Teil dieser Komponente gesehen werden.

  • Controller (Steuerlogik): Der Controller ist die Komponente, die eigentlich den Userinput entgegennehmen und verarbeiten soll. Er erhält die Nutzerinteraktion aus dem View, konvertiert sie in Befehle für entweder das Model oder den View und steuert damit den Workflow. Soll Userinput insbesondere in fachlicher Hinsicht validiert werden, obliegt dies dem Controller. Obwohl heutzutage Geschäftslogik eher im Model implementiert wird, gibt es auch Ansätze, bei denen der Controller zusätzlich fachliche Routinen ausführt.

Die Zusammenarbeit der Komponenten

Wie aus der Beschreibung der Komponenten ersichtlich wird, gibt es keine finale Definition für alle Verantwortlichkeiten. Ähnlich ist auch die Form der Zusammenarbeit zwischen den Komponenten abhängig von der jeweiligen Ausprägung des Musters. Grundsätzlich gilt für MVC folgendes:

  • Das Model erhält Anweisungen durch den Controller und führt entsprechende Berechnungen oder Datenaktualisierung durch. Alternativ kann das Model direkt durch den Controller manipuliert werden. In jedem Fall agiert das Model nicht auf Basis der Interaktion des Users mit dem View, sondern benötigt immer die Steuerung durch den Controller.
  • Der Controller erhält Informationen über die Nutzerinteraktion und Eingaben durch den View. Dafür wird meist das Observer (Beobachter) Pattern verwendet. Wir gehen gleich noch genauer auf dieses Muster ein.
  • Der View stellt die Daten des Models für den Nutzer dar und reagiert auf Datenänderungen, indem er seine Darstellung ändert. Um die Änderungen zu bemerken wird ebenfalls oft das Observer Pattern verwendet.
Abbildung 1: Der Controller erhält das Nutzerinput aus dem View und manipuliert das Model. Die Änderungen am Model führen dazu, dass der View aktualisiert wird.

Diese Herangehensweise hat den Nachteil, dass alle Komponenten miteinander interagieren, was vor allem die Testbarkeit reduziert. Es gibt zwei Abwandlungen des MVC Patterns, die eine strikte Trennung zwischen Model und View erzwingen: Der Model View Adapter und der Model View Presenter. Beim Model View Presenter wird der Controller wie der Name vermuten lässt durch einen Presenter (dt. Präsentierer) ersetzt. Dieser dient als Bindeglied zwischen Model und View und hat die Aufgabe, beide Schnittstellen miteinander zu verbinden. Dazu nimmt er wie bei MVC die Anfragen des Nutzers über den View entgegen und leitet sie an das Model weiter. Gleichzeitig ist er aber auch dafür verantwortlich, den View zu aktualisieren. Dadurch müssen Model und View niemals von der Existenz des anderen wissen oder miteinander kommunizieren.

Abbildung 2: Der Presenter erhält das Nutzerinput aus dem View, ändert das Model entsprechend und aktualisiert auf Basis des geänderten Models den View

Das MVP Pattern wird zwischen den Ausprägungen Supervising Controller und Passive View unterschieden. Bei einem Supervising Controller (dt.: überwachende Steuerlogik) sendet der Presenter ganze Datenobjekte an den View, sodass dieser für die Datensynchronisation beispielsweise durch Data Bindings zuständig ist. Das verringert die Testbarkeit, der Quellcode selbst wird aber schmaler. Bei einem Passive View hingegen übernimmt der Presenter die Synchronisation von Model und View vollständig.

Der Model View Adapter funktioniert ähnlich wie der Model View Presenter. Man spricht hier von einem Mediating oder Adapting Controller (dt. etwa vermittelnde Steuerlogik), der ebenfalls die Interaktion zwischen View und Model vollständig übernimmt. Ein Unterschied zum MVP Pattern ist, dass es mehrere Adapter für ein Model-View-Paar geben kann, während Model, View und Presenter meist in einem Dreieck auftreten.

Was ist das Observer Pattern?

Nachdem wir nun einige Strukturen, die das MVC Pattern annehmen kann, gesehen haben, wollen wir noch einmal auf das vorhin erwähnte Observer Pattern eingehen. Es handelt sich dabei um ein Verhaltensmuster, das der Weitergabe von Objektänderungen an alle Strukturen, die von dem Objekt abhängig sind, dient.

Konkret auf MVC bezogen bedeutet das, dass beispielsweise eine Änderung am Model dazu führen soll, dass der View sich ändert. Gleichzeitig soll das Model aber weder die Views noch ihre Schnittstelle kennen. Mit dem Observer Pattern können sich Objekte (in diesem Fall Views) als Beobachter bei einem Objekt (in diesem Fall dem Model) an- und abmelden. Das Model kennt nun seine Beobachter und informiert sie bei Änderungen. Dazu muss das Model nicht wissen, wie die Beobachter mit den Informationen umgehen, es propagiert lediglich die Art der Änderung über eine möglichst einfach gehaltene Schnittstelle. Ähnlich kann auch der Controller die Eingabeinformationen des Views erhalten, indem er ihn beobachtet.

Vor- und Nachteile des MVC Pattern

Einer der größten Vorteile des MVC Pattern ist, dass es eine höhere Kohäsion und lose Kopplung der einzelnen Komponenten erzwingt. Das bedeutet, die Komponenten sind gleichzeitig in sich zusammenhängend und voneinander unabhängig. Zudem untertsützt das Muster Separation of Concerns (dt. Trennen von Verantwortlichkeiten), indem die internen Abläufe der einzelnen Komponenten verborgen und nur Schnittstellen zur Interaktion bereitgestellt werden.

Lose Kopplung, hohe Kohäsion und Separation of Concerns machen Software und ihre Komponenten wartbarer, besser wiederverwendbar und erleichtern die Weiterentwicklung.

Betrachten wir beispielsweise Code, bei dem die Oberfläche nicht nur für die Anzeige von Daten, sondern auch für das Handling des Inputs verantwortlich ist. Soll die Repräsentation wiederverwendet werden, ist das nicht möglich, ohne auch den Code für die Nutzereingaben zu verwenden und anders herum. Ändert sich etwas am Nutzerinput ist es sehr wahrscheinlich, dass auch die Repräsentation sich ändern muss, da beide Komponenten nicht mit dem Gedanken der Unabhängigkeit designed wurden und daher mit hoher Wahrscheinlichkeit mehr Abhängigkeiten voneinander haben als nötig.

Ohne eine klare Trennung der Verantwortlichkeiten kann sich der Entwickler außerdem nie sicher sein, dass eine interne Änderung einer Komponente keine Nebeneffekte in einem anderen Teil der Software nach sich zieht. Sowohl Weiterentwicklung als auch Refactoring und Wartung sind daher riskanter und nehmen mehr Zeit in Anspruch.

Die Wiederverwendbarkeit von Komponenten ist zum einen innerhalb der Software und zum anderen für das Deployment auf verschiedenen Zielplattformen relevant. Innerhalb der Software kann ein kleines Objekt mit einer klar definiert Verantwortlichkeit besser in einem neuen Kontext verwendet werden. Während des Deployment hingegen kann beispielsweise das Model über das Internet angeboten werden und ist dadurch auf Windows, Mac und Linux verfügbar. Nur die Views und ggf. Controller müssen dann noch einmal separat für die einzelnen Betriebssysteme implementiert werden.

Zuletzt steigern voneinander unabhängige Komponenten die Effizienz während der Entwicklung: Mehrere Entwickler können gleichzeitig an unterschiedlichen Komponenten arbeiten, ohne, dass sie sich gegenseitig behindern oder blockieren.

MVC bringt allerdings auch Nachteile mit sich, insbesondere wenn die Software bzw. die Komponenten nicht korrekt geschnitten oder sauber umgesetzt sind. Zu den Nachteilen gehören eine geringere Übersichtlichkeit und Navigierbarkeit des Codes, da viele Schichten und Indirektionen existieren. Das kann auch die Fehlersuche und das Debugging erschweren. Da sich die Logik über alle Schichten erstreckt, müssen diese untereinander konsistent gehalten werden, was ebenfalls zu Mehraufwand führen kann. Zuletzt erfordert MVC vergleichsweise viel Boilerplate Code, der lediglich existiert, um das Muster zu erfüllen. Gerade für kleine Anwendungen führt das zu viel Overhead während der Implementierung.

Zusammenfassung

Model View Controller ist ein Entwurfsmuster, das vor allem für die Entwicklung von Software mit Benutzeroberflächen und in der Webentwicklung verwendet wird. Bei dem Muster wird die Software in die drei Komponenten Model, View und Controller unterteilt, die jeweils eigene Verantwortlichkeiten haben. So ist das Model für die Datenstruktur, der View für die Präsentation der Daten und der Controller für die Verarbeitung der Nutzereingaben und die Steuerung des Workflows verantwortlich. Der Controller nimmt die Eingaben des Nutzers über den View entgegen und aktualisiert das Model. Die Geschäftslogik des Programms kann dabei sowohl im Controller als auch im Model liegen. Anschließend wird im klassischen MVC der View durch die Änderung des Models aktualisiert. In anderen Ausprägungen, wie dem Model View Presenter oder dem Model View Adapter, geschieht sowohl die Steuerung des Models als auch des Views über den Controller. Dieser wird in diesem Fall Presenter oder Mediating Controller genannt. Durch dieses Design müssen View und Model nicht mehr von der Existenz des anderen wissen und sind noch stärker entkoppelt.

Durch MVC können verschiedene Aspekte der Software sauber voneinander getrennt werden. Dadurch wird nicht nur paralleles Arbeiten an verschiedenen Komponenten ermöglicht, einzelne Teile der Software sind auch besser wiederverwendbar und können unabhängig voneinander gewartet oder weiterentwickelt werden. Allerdings bedeutet die Einführung mehrerer Indirektionen, wie sie in MVC unvermeidlich ist, einen erhöhten Overhead vor allem in kleinen Projekten. Der Code kann zudem unübersichtlich werden, wenn die Komponenten nicht korrekt geschnitten, sauber implementiert und konsistent gehalten sind.

Ähnliche Produkte

2 Kommentare zu “Model View Controller

  1. Eine sehr gute Darstellung des Pattern. Vielleicht könnte man noch auf eine konkrete Umsetzung auszugsweise verweisen, damit es für Praktiker leichter zu greifen ist.

    1. Hallo Steve,

      danke für den Hinweis, das reichen wir nach!

      BG

Schreibe einen Kommentar