Softwarearchitektur verstehen und entscheiden

Aaron KreisÜber mich
Anwendungsarchitektur

Model View ViewModel

Anzeige bindet sich an ein Zwischenmodell

Die Idee und ihr Nutzen

Die Sachbearbeiterin Frau Meier trägt in der Schadenmaske ihrer Versicherung die Höhe eines Schadens ein. Bis zu ihrer Freigabegrenze von 10.000 Euro darf sie einen Schaden allein freigeben. Liegt der Betrag darüber, soll die Schadenmaske sofort den Hinweis „zweite Freigabe nötig“ zeigen und den Knopf „Allein freigeben“ ausgrauen, noch bevor Frau Meier etwas absendet. Dafür hält ein eigener Programmteil, das ViewModel, den eingegebenen Betrag und leitet daraus ab, was die Schadenmaske zeigen soll. Die Schadenmaske ist so mit dem ViewModel verbunden, dass sie dessen Werte automatisch anzeigt. Setzt das ViewModel den Hinweis auf sichtbar, zeigt die Schadenmaske den Hinweis sofort an. Diese Aufteilung heißt Model View ViewModel, kurz MVVM. Der Name nennt die drei Teile. Das Model enthält auf dem Server die Daten und die verbindlichen Regeln, die View ist die Schadenmaske, und das ViewModel hält die Werte, die die View anzeigt.

Bausteine: Frau Meier: tippt den Betrag ein; View: Schadenmaske, an das ViewModel gebunden; ViewModel: hält Betrag, Grenze und Anzeigezustand; Model auf dem Server: prüft Rechte und Grenze verbindlich. Verbindungen: Frau Meier — View; View — ViewModel (Betrag); View — ViewModel (Anzeigezustand); ViewModel — Model auf dem Server (Freigabe); ViewModel — Model auf dem Server (angenommen oder abgelehnt). Die View ist an das ViewModel gebunden und zeigt sofort dessen Anzeigezustand; verbindlich prüft erst das Model auf dem Server.

Wie funktioniert es?

Frau Meier tippt in das Betragsfeld der Schadenmaske 12.000 Euro ein. Die Schadenmaske ist die View, also die Anzeige. Das Betragsfeld ist über eine Datenbindung mit dem ViewModel verknüpft. Eine Datenbindung überträgt Werte automatisch zwischen einem Feld der View und einem Wert im ViewModel. So gelangen die 12.000 Euro ins ViewModel, ohne dass die View dafür eigenen Code enthält. Das ViewModel vergleicht den Betrag mit Frau Meiers Freigabegrenze von 10.000 Euro und setzt den Anzeigezustand, also die Werte, nach denen sich die View richtet. Im Anzeigezustand ist der Hinweis jetzt sichtbar und der Knopf „Allein freigeben“ inaktiv. Die Datenbindung überträgt den neuen Anzeigezustand zurück in die View, und die View zeigt sofort den Hinweis und graut den Knopf „Allein freigeben“ aus. Korrigiert Frau Meier den Betrag auf 9.000 Euro, läuft dasselbe erneut ab: Der Hinweis verschwindet, und der Knopf wird wieder aktiv. In einem zweiten Fall umgeht jemand die Schadenmaske. Ein verändertes Programm schickt eine Freigabe über 12.000 Euro direkt an das Model auf dem Server, den Programmteil mit den Daten und den fachlichen Regeln. Das Model auf dem Server prüft Rechte und Freigabegrenze selbst und lehnt die Freigabe ab.

Zum Model gehören hier der Schaden und die verbindliche Prüfung der Freigabegrenze. Das Model liegt meist auf dem Server. Das ViewModel ist ein Zwischenmodell, das die Daten für eine bestimmte Maske aufbereitet. Das ViewModel hält den eingegebenen Betrag, Frau Meiers Freigabegrenze und den daraus abgeleiteten Anzeigezustand, also ob der Hinweis sichtbar und ob der Knopf „Allein freigeben“ aktiv ist. Das ViewModel kennt keine konkreten Knöpfe oder Felder, sondern nur diese Werte. Die Datenbindung stellt der Programmrahmen bereit, die fertige Programmbibliothek, mit der die Schadenmaske gebaut ist. Welche Werte in welche Richtung fließen und ob sofort oder erst nach Verlassen des Feldes, legt das Team, das die Schadenmaske baut, für jede Datenbindung einzeln fest.

Die Schadenmaske läuft als Programm auf dem Arbeitsplatzrechner oder im Browser und schickt erst beim Absenden Daten an den Server der Versicherung. Dort findet die verbindliche Prüfung der Freigaberechte statt, weil jedes Programm auf dem Arbeitsplatzrechner verändert oder umgangen werden kann. Sendet Frau Meier die Freigabe ab, geht die Freigabe an das Model auf dem Server. Das Model auf dem Server prüft Rechte und Freigabegrenze verbindlich und nimmt die Freigabe an oder lehnt sie ab, unabhängig davon, was die View angezeigt hat. Die Regel steht also zweimal im Code. Das ViewModel nutzt sie für eine Rückmeldung an Frau Meier noch vor dem Absenden, das Model für die verbindliche Prüfung. MVVM teilt nur den Code der Oberfläche auf. Wie das Model auf dem Server aufgebaut ist, legt MVVM nicht fest.

MVVM: sofortiger Hinweis in der Maske, verbindliche Prüfung im Model

Beteiligte: Frau Meier: tippt den Betrag, Grenze 10.000 Euro; View: Schadenmaske, an das ViewModel gebunden; ViewModel: hält Betrag, Grenze und Anzeigezustand; Model auf dem Server: prüft Rechte und Grenze verbindlich; Verändertes Programm: schickt eine Freigabe an der Maske vorbei. Ablauf: 1. Frau Meier tippt in der View, der Schadenmaske, 12.000 Euro ein. 2. Die Datenbindung überträgt den Betrag von 12.000 Euro aus der View ins ViewModel. 3. Das ViewModel vergleicht den Betrag mit Frau Meiers Freigabegrenze von 10.000 Euro und setzt im Anzeigezustand den Hinweis auf sichtbar und den Knopf „Allein freigeben“ auf inaktiv. 4. Die View zeigt sofort den Hinweis „zweite Freigabe nötig“ und graut den Knopf „Allein freigeben“ aus. 5. Korrigiert Frau Meier den Betrag auf 9.000 Euro, verschwindet der Hinweis wieder, und der Knopf „Allein freigeben“ wird wieder aktiv. 6. Ein verändertes Programm umgeht die Maske und schickt eine Freigabe über 12.000 Euro direkt an das Model auf dem Server. 7. Das Model auf dem Server prüft Rechte und Freigabegrenze selbst und lehnt die Freigabe ab. Die Regel steht zweimal im Code. Das ViewModel nutzt sie für die Rückmeldung an Frau Meier vor dem Absenden, das Model für die verbindliche Prüfung.

Wann ist es sinnvoll und wann nicht?

MVVM lohnt sich

  • Eine Oberfläche hat viele Felder, die voneinander abhängen, und muss bei jeder Eingabe reagieren. Beispiele sind ein Programm auf dem Arbeitsplatzrechner, eine mobile App oder eine Webanwendung mit vielen Feldern im Browser. Ohne ViewModel braucht die Maske viel Code, der nur Werte hin und her kopiert: Feld auslesen, Wert merken, Anzeige ändern. Mit jedem weiteren abhängigen Feld wächst die Gefahr, eine Aktualisierung zu vergessen. Der Hinweis bleibt dann zum Beispiel stehen, obwohl der Betrag längst geändert wurde.
  • Das Verhalten der Maske soll automatisch und ohne Aufbau der Oberfläche getestet werden. Ein Test setzt im ViewModel den Betrag auf 12.000 Euro und prüft, ob der Anzeigezustand „zweite Freigabe nötig“ lautet. Steht der Code dagegen in der Maske selbst, muss jeder Test die ganze Maske aufbauen.
  • Der verwendete Programmrahmen bringt eine Datenbindung mit, etwa Windows Presentation Foundation oder Avalonia. Das Team muss die Datenbindung dann nicht selbst programmieren. Ohne MVVM bliebe die mitgelieferte Datenbindung ungenutzt, und das Team schriebe den Code zum Kopieren der Werte trotzdem selbst.

MVVM ist nicht das Richtige

  • Die Maske muss vor dem Absenden nicht reagieren. Ein Beispiel ist ein Formular mit wenigen Feldern, die nicht voneinander abhängen und die der Server erst nach dem Absenden prüft. MVVM dient dazu, dass die Maske schon bei jeder Eingabe reagiert, und hätte hier nichts zu tun. Dann schickt die Maske die Eingaben beim Absenden an den Server, das Model auf dem Server prüft sie, und die Maske zeigt das Ergebnis an. Das Team schreibt kein ViewModel und keine Datenbindungen und pflegt die Regeln nur im Model statt in ViewModel und Model.
  • Der Programmrahmen bietet keine Datenbindung. Das Team müsste das Übertragen der Werte zwischen View und ViewModel dann selbst programmieren und hätte genau den Code zum Hin- und Herkopieren von Werten, den MVVM vermeiden soll. Dann baut das Team die Maske nach Model View Controller: Ein Controller nimmt die Eingaben entgegen, ruft das Model auf und aktualisiert die Anzeige ausdrücklich. Eine selbst programmierte Datenbindung, die das Team testen und pflegen müsste, entfällt.

Nachteile und typische Fehler

Das Team muss die Datenbindung des Programmrahmens gut kennen, etwa wann sie einen Wert sofort und wann erst nach Verlassen des Feldes überträgt, und hängt von dieser Datenbindung ab. Ein Wechsel des Programmrahmens betrifft deshalb meist auch die ViewModels. Die Regel für die Anzeige im ViewModel und die verbindliche Regel im Model müssen übereinstimmen. Bei jeder Änderung muss das Team die Regel deshalb in ViewModel und Model pflegen.

Typische Fehler und woran man sie erkennt:

  • Nur in der Maske geprüft: Das Team verlässt sich auf den ausgegrauten Knopf und prüft die Freigabegrenze auf dem Server nicht. Ein verändertes Programm kann dann einen Schaden über 10.000 Euro allein freigeben. Erkennbar ist das an freigegebenen Schäden über der Freigabegrenze, zu denen keine zweite Freigabe vermerkt ist.
  • Unsichtbarer Bindungsfehler: Eine Datenbindung ist falsch eingestellt und überträgt nichts. Ein Beispiel ist eine Bindung an einen falsch geschriebenen Wertnamen: Der Hinweis ist an „HinweisSichtbr“ gebunden statt an „HinweisSichtbar“. Das ViewModel setzt den Wert „HinweisSichtbar“ richtig, aber die View erfährt davon nichts. Weil nicht im Code steht, wann welcher Wert kopiert wird, ist der Fehler schwer zu finden. Erkennbar ist das an einem Hinweis, der bei 12.000 Euro nicht erscheint, obwohl ein Test des ViewModels den richtigen Anzeigezustand liefert.
  • Fachliche Regeln im ViewModel: In großen Masken wächst das ViewModel und übernimmt nach und nach fachliche Regeln, die ins Model gehören. Ein Beispiel ist die Regel, welche Belege zu einem Schaden vorliegen müssen. Erkennbar ist das an ViewModels mit Hunderten Zeilen fachlicher Berechnungen und an Regeln, die nur in der Maske gelten.
  • Abweichende Grenze: Die Freigabegrenze wird nur im Model oder nur im ViewModel geändert. Die Versicherung erhöht zum Beispiel Frau Meiers Freigabegrenze auf 15.000 Euro, und das Team ändert nur das Model. Das ViewModel rechnet weiter mit 10.000 Euro und graut bei 12.000 Euro den Knopf „Allein freigeben“ aus, obwohl das Model die Freigabe annehmen würde. Erkennbar ist das an Freigaben, die die View erlaubt und das Model auf dem Server ablehnt, oder umgekehrt.
  • Träge Oberfläche: In einer großen Maske hängen zum Beispiel 200 Felder über Datenbindungen vom Betrag ab. Bei jedem Tastendruck im Betragsfeld berechnet das ViewModel alle 200 abhängigen Werte neu, und die Datenbindungen übertragen alle 200 Werte in die View. Die Oberfläche wird dadurch spürbar langsamer. Erkennbar ist das an verzögerter Anzeige der getippten Zeichen in großen Masken.

Weiterführend

Verwandte Ansätze

  • Separation of Concerns: der Grundsatz, jede Aufgabe in genau einem Programmteil zu erledigen. MVVM trennt die Anzeige, den Anzeigezustand und die fachlichen Regeln.
  • Layered Architecture: teilt eine Anwendung in übereinanderliegende Schichten. MVVM ordnet die oberste Schicht, die Oberfläche.

Werkzeuge und Umsetzungen

  • Avalonia: Programmrahmen für Oberflächen auf der Plattform .NET mit Datenbindung nach MVVM, der unter Windows, macOS und Linux läuft.
  • CommunityToolkit.Mvvm: Bibliothek, mit der sich ViewModels in .NET mit wenig Code schreiben lassen.
  • Windows Presentation Foundation: Oberflächentechnik für Windows, für die MVVM ursprünglich entworfen wurde. Windows Presentation Foundation ist heute Open Source.
  • Knockout: JavaScript-Bibliothek, die MVVM im Browser umsetzt. Neue Versionen erscheinen nur noch selten, zuletzt 3.5.3 im März 2026.

Quellen