2025-05-12

MVVM als komplementäres Muster für Clean Architecture Anwendungen

Software Engineering
Learning & Growth
Project & Product
showing a profile picture of Marc

GESCHRIEBEN VON

Marc

INHALT

Das Clean Architecture Muster bietet ein robustes Framework für die Entwicklung von Software, die wartbar, testbar und hochgradig anpassungsfähig ist. Das Muster stellt sicher, dass die Kerngeschäftslogik von externen Änderungen und Abhängigkeiten unberührt bleibt. Die Trennung der Verantwortlichkeiten über verschiedene Schichten vereinfacht die Wartung und das Testen und erhöht die Flexibilität des Systems, was eine einfachere Integration neuer Technologien oder Anpassungen zur Erfüllung sich ändernder Anforderungen ermöglicht.

Durch die Befolgung des Clean Architecture Musters können wir verschiedene Probleme lösen, die während der Softwareentwicklung oder im Lebenszyklus einer Anwendung auftreten können, wie Codeduplizierung, enge Kopplung, Skalierbarkeitsherausforderungen und Testkomplexität. Die Anwendung von Clean Architecture führt zu Software, die einfacher zu verwalten und weiterzuentwickeln ist und widerstandsfähiger gegenüber sich ändernden Anforderungen ist.

Um ein detailliertes Verständnis von Clean Architecture zu erhalten, empfehle ich einen Blick auf unseren Blogbeitrag: Clean Architecture: Ein tiefer Einblick in strukturiertes Software-Design. Unser Beitrag Wie Clean Architecture häufige Herausforderungen bei der Softwareentwicklung löst ist eine ausgezeichnete Ergänzung dazu, da er erklärt, wie Clean Architecture uns helfen kann, häufige Probleme in der Softwareentwicklung zu lösen.

Während Clean Architecture eine solide Grundlage für die Strukturierung einer Anwendung bietet, profitiert die effektive Implementierung oft von komplementären Mustern, die spezifische Aspekte des Anwendungsdesigns adressieren. Eine solche Ergänzung ist das MVVM (Model-View-ViewModel) Muster, das Frontend- und UI-lastige Anwendungen begünstigt. Das MVVM-Muster kann eine Clean Architecture-Implementierung verbessern, indem es klare Richtlinien für die Trennung von UI-Belangen von der Geschäftslogik bereitstellt. Dies macht das Zustandsmanagement wartbarer und verbessert die Testbarkeit von UI-Komponenten.

Dieser Blogbeitrag wird untersuchen, wie MVVM Clean Architecture-Implementierungen ergänzen und verbessern kann. Zunächst betrachten wir die MV* Muster im Allgemeinen, um ihre gemeinsamen Merkmale zu verstehen. Anschließend konzentrieren wir uns auf das MVVM-Muster und wie es mit Clean Architecture-Prinzipien integriert werden kann, um wartbarere und besser testbare Anwendungen zu schaffen.

Dieses Thema war auch Teil eines Vortrags, den ich 2023 auf der [code.talks] Konferenz gehalten habe. Der Vortrag ist als Video auf YouTube verfügbar. Wenn Sie interessiert sind, können Sie diesem Link folgen: YouTube.


MV* Patterns Überblick

Die MV* Muster sind eine Familie von Architekturmustern mit einem gemeinsamen Ziel: die Verbesserung der Wartbarkeit und Testbarkeit durch Trennung der Anwendungsbelange in verschiedene Komponenten. Die bekanntesten Muster in dieser Familie umfassen Model-View-Controller (MVC), Model-View-ViewModel (MVVM) und Model-View-Presenter (MVP). Alle diese Muster teilen die Anwendung mindestens in zwei Hauptkomponenten auf: das Model und die View. Das Sternchen in MV* steht für die dritte Komponente, die über verschiedene Muster hinweg variiert (Controller, Presenter, or ViewModel).

Das Diagramm illustriert die allgemeine Struktur von MV* Mustern. Jedes Muster teilt die Anwendung in drei Schlüsselkomponenten:

  • Model: Behandelt Datenverwaltung, Geschäftslogik und Zustand.
  • View: Rendert UI-Elemente und erfasst Benutzereingaben.
  • Mediator: Koordiniert Interaktionen zwischen dem Model und der View. Je nach Muster kann dieser Vermittler ein ControllerPresenter, oder ViewModel sein.

Unterschiede in der Kopplung zwischen MV* Mustern

Während alle MV* Muster darauf abzielen, Verantwortlichkeiten zu trennen, variiert ihre Effektivität bei der Erreichung loser Kopplung:

MVC:

  • Im MVC beobachtet die View direkt Änderungen im Model. Diese enge Kopplung zwischen View und Model kann das Testen erschweren, besonders wenn Drittanbieterbibliotheken beteiligt sind (z. B. UI-Frameworks).
  • Der Controller fungiert als Vermittler, ist jedoch oft eng sowohl mit der View als auch dem Model gekoppelt, was das Testen und die Wartung weiter erschwert.

MVP:

  • MVP verbessert das MVC-Muster durch die Einführung eines Presenter, der die View vom Model entkoppelt. Der Presenter behandelt alle Interaktionen zwischen diesen Komponenten, was eine bessere Modularität und einfacheres Testen ermöglicht.

MVVM:

  • Das MVVM-Muster treibt die Trennung noch weiter, indem es ein ViewModel einführt. Im Gegensatz zu MVC oder MVP hat das ViewModel keine direkte Referenz zur View. Stattdessen verwendet es Datenbindungsmechanismen, um UI-Elemente (View) mit Daten (Model) zu verbinden. Dies stellt eine vollständige Entkopplung zwischen der UI und der Geschäftslogik sicher, was das Testen erleichtert und die Wartbarkeit verbessert.

Erreichen von loser Kopplung mit Clean Architecture-Prinzipien

Bitte beachten Sie, dass die MV* Muster allein keine lose Kopplung garantieren. Konkrete Implementierungen können ohne angemessene Abstraktionsschichten oder Schnittstellen immer noch zu Kompilierungsabhängigkeiten zwischen Komponenten führen.

In Kombination mit Clean Architecture-Prinzipien, wie dem Dependency Inversion Principle und Schichtgrenzen, können MV* Muster jedoch eine solide Grundlage für die Erstellung wartbarer und testbarer Systeme bieten.


Das MVC-Muster

Das älteste und am weitesten verbreitete Muster der Gruppe ist das MVC-Muster, das in den 1970er Jahren eingeführt wurde. Es trennt ein System in drei verschiedene Komponenten:

Dieses Diagramm zeigt das MVC-Muster und seinen Kommunikationsfluss. Die View sendet Benutzeraktionen an den Controller, der denn das Model aktualisiert. Das Model benachrichtigt die View über Änderungen, oft durch ein Observer-Muster. Dies erzeugt eine Beziehung, bei der die View das Model direkt auf Updates beobachtet. Dieser direkte Beobachtungsmechanismus erzeugt eine enge Kopplung zwischen der View und dem Model, was einer der Hauptnachteile des MVC-Musters ist.

Zusammenfassung der Komponenten:

  • Model: Das Model repräsentiert die Daten und die Geschäftslogik des Systems. Es ist verantwortlich für das Speichern, Abrufen und Verarbeiten von Daten, die Implementierung von Geschäftsregeln und die Benachrichtigung der View über Änderungen.

  • View: Die View zeigt die Daten aus dem Model dem Benutzer an. Sie rendert die Benutzeroberfläche und leitet Benutzerinteraktionen an den Controller weiter.

  • Controller: Der Controller behandelt die Benutzereingabe und aktualisiert das Model und die View entsprechend. Er fungiert als Vermittler zwischen dem Model und der View, verarbeitet Benutzeranfragen, aktualisiert das Model und wählt die entsprechende View aus.

Während das MVC-Muster eine gewisse Trennung der Belange bietet, führt seine Implementierung oft zu mehreren Herausforderungen:

  • Enge Kopplung zwischen View und Model: Die direkte Abhängigkeit zwischen der View und dem Model erschwert die Modifikation des einen ohne Beeinflussung des anderen. Dies kann zu engen Abhängigkeiten führen.

  • Testschwierigkeiten: Da die View und das Model eng gekoppelt sind, wird das Testen schwieriger. Unit-Tests der View in Isolation sind komplex, da sie das Model direkt beobachtet.

  • Komplexe Controller-Logik: Mit dem Wachstum von Anwendungen werden Controller oft mit sowohl UI- als auch Geschäftslogik überladen.

Diese Einschränkungen werden deutlicher beim Vergleich von MVC mit anderen MV* Mustern. Während MVC bei seiner Einführung innovativ war, erfordert die moderne Anwendungsentwicklung oft Muster mit saubererer Trennung zwischen Komponenten, besonders für komplexe UIs und bei der Befolgung von Prinzipien wie denen in Clean Architecture.


Das MVVM-Muster

Das MVVM-Muster ist eine neuere Ergänzung zu den MV* Mustern. Microsoft führte es in den frühen 2000er Jahren als Teil ihres Windows Presentation Foundation (WPF) Frameworks ein. Es ist eine Weiterentwicklung des MVC-Musters, das den Controller durch eine neue ViewModel-Komponente ersetzt. Das ViewModel bietet eine sauberere Trennung zwischen UI und Geschäftslogik. Dieses Entwurfsmuster besteht aus drei Hauptkomponenten: ModelView und ViewModel.

Das Diagramm veranschaulicht die Struktur und den Kommunikationsfluss des MVVM-Musters. Im Gegensatz zu MVC verwendet MVVM Datenbindung, um die View und das ViewModel zu verbinden. Dies schafft eine vollständige Trennung, da die View keine Kenntnis vom Model hat und das ViewModel unabhängig von einer spezifischen View arbeitet. Das ViewModel referenziert oder hängt nicht von der View ab, was es verschiedenen Views ermöglicht, dasselbe ViewModel zu verwenden, ohne Änderungen an seiner Implementierung zu erfordern. Das ViewModel fungiert als Vermittler, der Daten aus dem Model in ein für die View geeignetes Format transformiert und Benutzerinteraktionen aus der View verarbeitet.

Zusammenfassung der Komponenten:

  • Model: Das Model repräsentiert die Daten und die Geschäftslogik des Systems. Es ist verantwortlich für das Speichern und Verwalten der Daten, die Implementierung von Geschäftsregeln und die Bereitstellung von Datenvalidierung und -persistenz.

  • View: Die View ist verantwortlich für die Anzeige der Daten für den Benutzer und das Zurücksenden von Benutzereingaben an das ViewModel. Sie definiert die Struktur, das Layout und das Erscheinungsbild dessen, was der Benutzer auf dem Bildschirm sieht.

  • ViewModel: Das ViewModel dient als Brücke zwischen dem Model und der View. Es stellt die Daten aus dem Model für die View bereit, behandelt Benutzerinteraktionen und verarbeitet sie zu Aktionen auf dem Model. Das ViewModel hat keine direkte Referenz zur View, was es ermöglicht, das ViewModel unabhängig von der View zu testen.

Das wichtigste Merkmal von MVVM ist, dass es Datenbindungen verwendet, um die View und das ViewModel zu verbinden. Datenbindungen bieten eine Möglichkeit, die Benutzeroberflächenelemente in der View mit den Daten im ViewModel zu verbinden. Wenn sich die Daten im ViewModel ändern, aktualisiert sich die UI automatisch, um diese Änderungen widerzuspiegeln. Ebenso können Benutzerinteraktionen mit der UI automatisch die Daten im ViewModel aktualisieren. Dies ermöglicht eine saubere Trennung zwischen UI-Design und Geschäftslogik.

Ein weiteres Merkmal des MVVM-Musters ist die Verwendung von Event-Handlern. Diese kapseln die Logik für die Reaktion auf Benutzerinteraktionen ein und ermöglichen es der View, Geschäftslogik auszulösen, ohne die Implementierungsdetails zu kennen.

Im Vergleich zum MVC-Muster bietet MVVM mehrere Schlüsselvorteile, die es besonders gut für eine Clean Architecture-Implementierung geeignet machen:

Kommunikationsfluss:

  • In MVC sendet die View Benutzeraktionen an den Controller, der das Model aktualisiert. Das Model benachrichtigt dann die View direkt über Änderungen, was zu einer engen Kopplung führt.
  • Bei MVVM sind die View und das ViewModel durch Datenbindung verbunden, was einen automatischeren und bidirektionalen Datenfluss ohne direkte Abhängigkeiten ermöglicht

View-Model-Beziehung:

  • Bei MVC beobachtet die View oft direkt das Model auf Änderungen, was zu einer engen Kopplung führt.
  • Bei MVVM hat die View keine direkte Kenntnis vom Model; sie interagiert nur mit dem ViewModel durch Datenbindung, wodurch eine lose Kopplung aufrechterhalten wird.

Testbarkeit:

  • MVVM bietet eine deutlich bessere Testbarkeit, da das ViewModel keine Abhängigkeit von der View hat, was es einfacher macht, es isoliert zu testen.
  • Der Controller von MVC ist eng mit sowohl der View als auch dem Model gekoppelt, was das Testen schwieriger macht.

UI-Logik:

  • Bei MVVM wird die Präsentationslogik im ViewModel platziert, wodurch die View sich rein auf das UI-Rendering konzentrieren kann.
  • Bei MVC behandelt der Controller Benutzereingaben, aber einige UI-Logik kann in der View enden.

Warum MVVM Clean Architecture ergänzt

Sie fragen sich nun vielleicht, wie das MVVM-Muster eine Clean Architecture-Implementierung ergänzt und welche Vorteile diese Kombination bietet. Lassen Sie uns untersuchen, wie diese beiden architektonischen Ansätze zusammenarbeiten:

Dieses Diagramm veranschaulicht, wie MVVM-Komponenten mit Clean Architecture-Schichten übereinstimmen. Das Diagramm enthält kurze Beschreibungen für jede Clean Architecture-Schicht, um Ihnen ein grundlegendes Verständnis der Verantwortlichkeit jeder Schicht zu vermitteln. Eine ausführliche Erklärung der einzelnen Schichten finden Sie in unserem Blogbeitrag Clean Architecture: Ein tiefer Einblick in strukturiertes Software-Design. Die Zuordnung zeigt:

  • Die Model Komponente von MVVM erstreckt sich sowohl über die Entities als auch die Use Cases Schichten und behandelt Domainobjekte und Geschäftsoperationen.
  • Das ViewModel dient als Interface Adapter, der Daten zwischen der Kerngeschäftslogik und der UI transformiert.
  • Die View Komponente ist auf die Frameworks & Drivers Schicht beschränkt.

Diese Ausrichtung schafft ein Design, bei dem die Trennung der Belange von MVVM die Schichtgrenzen von Clean Architecture ergänzt.

MVVM bietet mehrere Vorteile bei der Implementierung von Clean Architecture-Prinzipien:

  • Verbesserte Trennung der Belange

    MVVM fördert eine klare Trennung zwischen UI (View), Präsentationslogik (ViewModel) und zugrunde liegenden Daten und Geschäftsregeln (Model). Diese Trennung macht den Code modularer und einfacher zu warten, was mit Clean Architecture's Betonung auf der Trennung von Belangen über verschiedene Schichten hinweg übereinstimmt.

  • Verbesserte Testbarkeit

    Die Entkopplung von Komponenten in MVVM erleichtert das Testen in Isolation. Das ViewModel kann ohne die View getestet werden, und das Model kann unabhängig von beiden getestet werden. Dies unterstützt das Ziel von Clean Architecture, ein System zu schaffen, in dem einzelne Komponenten unabhängig entwickelt, getestet und gewartet werden können, ohne die gesamte Anwendung zu beeinflussen.

  • Zentralisiertes Zustandsmanagement

    Das ViewModel zentralisiert die Präsentationslogik und das UI-Zustandsmanagement und bietet eine einzige Quelle der Wahrheit für die UI. Auf den ersten Blick mag dies seiner Rolle als Interface Adapter zu widersprechen scheinen, aber diese Rollen ergänzen sich.

    Als Interface Adapter transformiert das ViewModel Domänendaten aus dem Model in UI-freundliche Formate. Dieser Transformationsprozess ist der erste Schritt im UI-Zustandsmanagement: die Erstellung einer präsentationsbereiten Darstellung aus Domänendaten. Das ViewModel behält diese transformierte Darstellung bei und verwaltet Zustandsübergänge, die durch Benutzerinteraktionen ausgelöst werden.

    Diese Grenzposition zwischen Geschäftslogik und UI ist ideal für das UI-Zustandsmanagement, weil:

    • Es UI-Zustandsbelange von der Domänenlogik isoliert
    • Es verhindert, dass UI-Zustandsimplementierungsdetails in Kerngeschäftsregeln eindringen
    • Es schafft eine klare Grenze, an der Daten von der Domänendarstellung zur Präsentationsdarstellung übergehen

    In Clean Architecture wird der Zustand auf verschiedenen Ebenen mit einer klaren Trennung der Belange verwaltet:

    • Domänenzustand wird innerhalb der Schichten Use Cases und Entities verwaltet
    • UI-Zustand wird an der Grenze in der Schicht Interface Adapters verwaltet (durch Komponenten wie ViewModels)

    Das ViewModel verwaltet nicht den Domänenzustand (der die Verantwortung der inneren Schichten bleibt), sondern es verwaltet, wie Domänendaten den Benutzern präsentiert werden und wie Benutzerinteraktionen die Präsentation beeinflussen.

  • Kompatibilität mit Dependency Inversion

    Obwohl es kein Merkmal von MVVM ist, macht die Struktur des Musters es kompatibel mit Dependency Injection-Praktiken. ViewModels können leicht Services, Repositories und Use Cases als Abhängigkeiten erhalten, ohne enge Kopplung zu spezifischen Implementierungen zu erzeugen. Diese Kompatibilität ermöglicht es Entwicklern, Clean Architecture's Dependency Inversion Principle anzuwenden, bei dem Hochlevel-Module und Lowlevel-Module von Abstraktionen abhängen, anstatt von konkreten Implementierungen.

  • Framework-Unabhängigkeit

    Die ViewModel und Model-Komponenten von MVVM sind unabhängig von UI-Frameworks, was mit dem Ziel von Clean Architecture übereinstimmt, Systeme zu schaffen, in denen die Geschäftslogik von externen Abhängigkeiten isoliert ist. Diese Unabhängigkeit macht es einfacher, sich an ändernde UI-Technologien anzupassen, ohne die Kerngeschäftslogik zu beeinflussen.

Bei der Zuordnung von MVVM zu Clean Architecture-Schichten:

  • Entities Layer: Enthält die Kerngeschäftsobjekte und Geschäftsregeln. In MVVM werden diese Elemente in die Model Komponente integriert, die die wesentlichen Datenstrukturen und Verhaltensweisen der Domäne repräsentiert.
  • Use Cases Layer: Enthält anwendungsspezifische Geschäftsregeln. In MVVM würden diese ebenfalls Teil der Model Komponente sein, mit Fokus auf Geschäftsoperationen und Orchestrierung.
  • Interface Adapters Layer: Konvertiert Daten zwischen Formaten, transformiert von der Struktur, die von der Kerngeschäftslogik (Entities und Use Cases) verwendet wird, in Formate, die für die Anzeige oder externe Systeme optimiert sind. Das ViewModel in MVVM dient diesem Zweck, indem es Rohdaten aus dem Model in ein präsentationsbereites Format verarbeitet, das die View leicht konsumieren und anzeigen kann.
  • Frameworks & Drivers Layer: Enthält Frameworks und Tools wie die UI, Datenbanken und externe Schnittstellen. Die View Komponente von MVVM gehört in diese Schicht und behandelt UI-Rendering und Benutzereingaben.

Durch die Verwendung von MVVM neben Clean Architecture schaffen Sie einen umfassenderen Ansatz für die Frontend-Entwicklung. Clean Architecture bietet die Gesamtstruktur und Prinzipien für die Organisation der Anwendungsschichten und -abhängigkeiten. MVVM hingegen bietet spezifische Richtlinien für den Umgang mit der Präsentationsschicht und Benutzeroberflächen-Belangen.

Speziell bietet MVVM:

  1. Eine klare Trennung zwischen UI (View) und Geschäftslogik (Model)
  2. Eine dedizierte Komponente (ViewModel) für die Verwaltung des UI-Zustands und der Präsentationslogik
  3. Einen Mechanismus (Datenbindung) für die effiziente Aktualisierung der UI basierend auf Änderungen in den zugrunde liegenden Daten

Diese MVVM-Konzepte stimmen gut mit Clean Architecture-Prinzipien überein und bieten gleichzeitig konkrete Muster für die Implementierung der Benutzeroberflächen-Schicht. Diese Kombination ermöglicht es Entwicklern, die Kernideen von Clean Architecture bezüglich der Trennung von Belangen und der Unabhängigkeit der Kerngeschäftslogik beizubehalten und gleichzeitig eine klare Struktur für die Organisation und Implementierung komplexen UI-bezogenen Codes in modernen Anwendungen zu haben.

Für ein praktisches Implementierungsbeispiel können Sie sich auf unseren kommenden Blogbeitrag, "Entwicklung einer von Clean Architecture inspirierten React-Anwendung mit MVVM", freuen, der Sie Schritt für Schritt durch die Erstellung einer solchen Anwendung führt.


Fazit

Das MVVM-Muster ist komplementär bei der Implementierung von Clean Architecture-Prinzipien, insbesondere für Frontend- und UI-lastige Anwendungen. Seine Betonung auf der Trennung von Belangen stimmt gut mit dem Ziel von Clean Architecture überein, Software zu erstellen, die wartbar, testbar und anpassungsfähig an Veränderungen ist. Durch die Aufteilung einer Anwendung in ModelView und ViewModel ermöglicht MVVM ein modulares Design, bei dem jede Komponente isoliert entwickelt und getestet werden kann, was die Gesamtqualität und Robustheit der Anwendung verbessert.

Das ViewModel, das die View und das Model verbindet, zentralisiert die Präsentationslogik und stellt sicher, dass die UI (View) von der Geschäftslogik und den Daten (Model) entkoppelt bleibt. Diese Trennung trägt zu einer einfacheren Wartung bei und ermöglicht eine größere Flexibilität bei der Integration neuer Technologien oder der Anpassung an sich entwickelnde Anforderungen.

Zu den wichtigsten Vorteilen der Verwendung von MVVM neben Clean Architecture gehören:

  1. Verbesserte Trennung von UI-Belangen: MVVM bietet klare Richtlinien für die Trennung von UI-Rendering von Präsentationslogik und Geschäftsregeln.
  2. Verbesserte Testbarkeit: Die Entkopplung von Komponenten erleichtert das Testen jedes Teils in Isolation, insbesondere des ViewModel, das den Großteil der Präsentationslogik enthält.
  3. Zentralisiertes Zustandsmanagement: Das ViewModel bietet eine einzige Quelle der Wahrheit für den UI-Zustand, was Anwendungen vorhersehbarer und leichter zu debuggen macht.
  4. Framework-Unabhängigkeit: Die Kerngeschäftslogik bleibt von UI-Frameworks isoliert, was es ermöglicht, UI-Technologien mit minimalen Auswirkungen auf den Kern Ihrer Anwendung zu ändern.

Bei der Implementierung von Clean Architecture ist MVVM keine Anforderung, kann aber ein wertvolles Werkzeug sein, das uns hilft, saubere Grenzen zu wahren, insbesondere in der Präsentationsschicht. Durch das Verständnis, wie MVVM-Komponenten auf Clean Architecture-Schichten abgebildet werden, können wir Anwendungen erstellen, die nicht nur kurzzeitig funktional sind, sondern auch nachhaltig und anpassungsfähig an zukünftige Bedürfnisse.