MVVM-Klarstellung

14

Wir stehen kurz vor der Erstellung unserer ersten WPF-Anwendung und machen uns mit dem MVVM-Muster vertraut. Wir haben viele Winform-Anwendungen erstellt und verfügen über eine Architektur, die für uns sehr erfolgreich war. Wir haben ein bisschen Probleme, diese Architektur zu übersetzen oder festzustellen, wo bestimmte Teile unserer Architektur in das MVVM-Modell passen.

Historisch gesehen haben wir eine Gui (die Haupt-Exe), die dann mit einer BusinessLogic-DLL kommuniziert. Die BusinessLogic kommuniziert über einen Webdienst mit einer DAL-DLL, und die DAL interagiert mit der DB. DAL, BusinessLogic und GUI verweisen alle auf dieselbe BusinessObjects-DLL.

AsIs Architektur

Ein Teil des Übergangs zu MVVM ist recht unkompliziert. Unsere Benutzeroberfläche enthält weiterhin die Ansichten, unsere BusinessOjbects enthalten weiterhin das Modell und unser DAL interagiert weiterhin mit der Datenbank (obwohl sich die Technologie zu deren Implementierung möglicherweise ändert).

Was uns nicht sicher ist, ist unsere BusinessLogic-Komponente. Historisch gesehen würde dies Funktionen für die GUI bereitstellen, um dann Steuerelemente in den Ansichten aufzufüllen (dh GetCustomerList, die eine Liste von Kundenobjekten oder die typischen CRUD-Funktionen zurückgeben würden).

Das Hauptproblem ist, ob das MVVM-Muster eine zusätzliche Komponente zur Aufnahme der ViewModels erfordern würde oder ob wir nur unser Denken ändern und das, was wir als BusinessLogic-Komponente verwendet haben, auf die ViewModels migrieren?

Stellt unsere BusinessLogic-Komponente die ViewModels dar?

user7676
quelle
Das klingt ein bisschen wie eine Lösung, die nach einem Problem sucht. Gibt es einen zwingenden Grund, warum Sie zu MVVM wechseln? Ich bin ein Fan des Musters, aber hat Ihre vorherige Lösung nicht funktioniert? Das Ansichtsmodell ist wie ein überwachender Moderator. Es enthält Präsentationslogik und Oberflächendaten durch Datenbindung. Es sollte über Ihre Geschäftslogik Bescheid wissen und in der Lage sein, diese Ebene zu erreichen, aber ich würde die Geschäftslogik nicht in das Ansichtsmodell selbst integrieren.
Jeremy Likness

Antworten:

18

Im Allgemeinen würde ich keine Geschäftslogik in die Ansichtsmodellebene einfügen. Der Begriff "Geschäftslogik" ist jedoch irreführend.

Eric Evans verwendet ein Modell, bei dem die Geschäftslogik in zwei Kategorien unterteilt ist

  • Domänenlogik - Logik für die eigentliche Problemdomäne, die Sie lösen
  • Anwendungslogik - Logik, die sich auf die Tatsache bezieht, dass Sie eine Anwendung erstellen

Er nennt das Beispiel einer Buchhaltungsanwendung. Regeln über Konten, Posten, Steuerkonten usw. sind Domänenregeln, Regeln, die sich auf die Domäne der Buchhaltung beziehen. Die Logik des CSV-Imports / -Exports hat nichts mit der Domäne des Rechnungswesens zu tun. Diese Regeln existieren nur, weil wir eine Softwareanwendung erstellen. Dies sind Beispiele für Anwendungslogik.

Domänenregeln sollten NIEMALS in die Ansichtsmodellebene aufgenommen werden. Wenn Sie dem MVVM-Muster folgen, werden die Domänenregeln ohne Frage in die Modellschicht übernommen.

Anwendungsregeln, wie z. B. CSV-Import / Export, können in die Ansichtsmodellebene eingefügt werden. Aber ich persönlich würde es vorziehen, das in eine separate Anwendungslogikebene aufzuteilen.

Das Ansichtsmodell sollte sehr einfach sein. Nachschlagen der für die Ansicht im entsprechenden Modell erforderlichen Daten, Aktualisieren des Modells bei Änderungen der Ansicht, Abhören von Ereignissen im Modell und Übertragen dieser Ereignisse in die Ansicht, sodass die Ansicht aktualisiert werden kann, wenn das Modell im Hintergrund aktualisiert wird (wenn anwendbar).

Persönlich würde ich sicherstellen, dass der Ansichtsmodell-Layer nur eine Art von Logik enthält, die Präsentationslogik.

Pete
quelle
1
Hervorragende Antwort. Ich mag es, sicherzustellen, dass das ViewModel nur Präsentationslogik enthält. Können Sie einen Link zu Ihrem Eric Evans-Punkt hinzufügen?
user7676
Ich bezweifle, dass ich einen Link finden kann, weil ich glaube, dass er aus seinem Buch Domain-Driven Design stammt. Ich denke, es ist ein hervorragendes Beispiel für den Unterschied zwischen Domänen- und Anwendungslogik. Mehr zum Buch hier books.google.dk/books/about/…
Pete
5

Ja.

Die Geschäftslogikschicht wird durch die VM-Schicht dargestellt. Migrieren Sie einfach Ihr mentales Modell.

Eine kleine Nuance bei der mentalen Modellmigration ist, dass die GUI (View) -Objekte an Objekte innerhalb der VM-Ebene gebunden werden sollten. Diese Bindung übersetzt in impliziert, dass die Ansicht nicht länger die Ebene ist, die "den Anruf tätigt", um etwas anderes abzurufen. Der Aufruf zum Abrufen von Daten erfolgt stattdessen über die VM.

Zur besseren Erklärung: Ja, ein Objekt in der Ansicht muss geändert werden, um die Abfolge der Dinge auszulösen, die den Aufruf auslösen. Die Ansicht ruft jedoch nicht selbst an. In diesem Fall sehe ich einen Klick auf eine Schaltfläche als äquivalent zu einer Änderung in der Ansicht an, die den Anruf jedoch nicht tätigt.

Im ersten Fall wird dieses View-Objekt an ein VM-Objekt gebunden. Die VM sollte auf ein Ereignis mit geänderten Eigenschaften für das gebundene Objekt warten. Das Objektänderungsereignis kann dann mit einer VM-Funktion verbunden werden, um den Model-Aufruf durchzuführen.

Im zweiten Fall (Tastenklickereignis) kann das Änderungsereignis (Klickereignis) mit einem Funktionsaufruf verknüpft werden, der von der VM verfügbar gemacht wird.

In beiden Fällen handelt es sich immer um ein Ereignis, das in die VM eingeht und dann das Modell aufruft, das wiederum die DAL / DB aufruft.

Ich rufe es auf, weil WinForm-Code verwendet wird, um den DB-Layer direkt vom Code-Behind der WinForm-GUI aufzurufen. Dieser Ansatz unterbricht die Trennung, die MVVM bietet.


quelle
Danke für die Bestätigung. Wir verstehen die Nuance der Interaktion der Ansicht mit dem ViewModel und werden das Bindungsmodell beibehalten und den "Aufruf" verwerfen.
user7676
Mir ist aufgefallen, dass diese Antwort eine hohe Stimme verloren hat. Ich wäre neugierig, wenn der Downvoter kommentieren würde, warum? Oder fügen Sie eine eigene Antwort hinzu, wenn Sie diesen Standpunkt nicht teilen.
user7676
1
Ich bin damit einverstanden, dass die Business-Logik-Schicht durch die VM-Schicht repräsentiert wird. Ich denke jedoch, dass Teile Ihrer Antwort verwirrend sein können. Die ViewEbene soll eine visuelle Darstellung des ViewModel oder Modells sein. Anstatt zu sagen, dass das Klickereignis mit einem Funktionsaufruf auf der VM verbunden ist, ist es eine bessere Definition, zu sagen, dass der Befehl in der VM als Button in gerendert wird die Ansichtsebene. Außerdem gefällt es mir normalerweise nicht, dass mein Model-Layer direkt auf die DAL zugreifen kann, sodass mein Anwendungsfluss normalerweise dahin geht VM -> DAL -> DB, wo die VMund DALbeide die einfachen ModelDatenobjekte verwenden.
Rachel
4
Ich bin mit dieser Antwort nicht einverstanden. ViewModel ist ein Modell der Ansicht. Es enthält Ansichtslogik und keine Geschäftslogik. ViewModels sind Teil der Präsentationsebene
Simoraman
1
@simoraman - Das MVPVM-Muster stimmt mit dem überein, was Sie vorschlagen. Ich denke, MVPVM ist ein gutes Muster, aber für kleinere Apps etwas schwer. Ich möchte Sie wirklich ermutigen, Ihre Gedanken zu beantworten und zu dieser Frage beizutragen.
5

Sie haben Recht, dass Sie Ihre BusinessLogic-DLL im Wesentlichen durch Ihren ViewModel-Layer ersetzen würden. Der größte Unterschied besteht jedoch darin, wie der View / UI-Layer mit Ihrem ViewModel / BusinessLogic-Layer interagiert.

In WinForms ist die GUI Ihre Anwendung und für den Anwendungsfluss verantwortlich. In WPF / MVVM sind Ihre ViewModels Ihre Anwendung, und die GUI wird zu einer benutzerfreundlichen Oberfläche für die Interaktion mit den ViewModels.

Mit WinForms verfügen Sie beispielsweise möglicherweise über ein DataGrid und eine Schaltfläche. Wenn Sie auf diese Schaltfläche klicken, rufen Sie BusinessLogicLayer.GetProducts()die resultierenden Product-Objekte auf und laden sie in das DataGrid.

Mit WPF hätten Sie ein ViewModel, das ein ObservableCollection<Products>und ein enthält. ICommand GetProductsWenn Sie den Befehl ausführen, wird die DAL aufgerufen und die Auflistung der Produkte geladen. Um jedoch eine benutzerfreundliche Oberfläche bereitzustellen, müssen Sie eine Ansicht erstellen, in der Ihr ViewModel mit einem DataGrid für die Products-Auflistung und einer Schaltfläche für den GetProducts-Befehl gerendert wird.

Ich habe kürzlich in meinem Blog einen Beitrag über die veränderte Denkweise beim Wechsel von Winforms zu WPF in meinem Blog verfasst , und ich denke, der beste Weg, um den Unterschied zusammenzufassen, sind die folgenden Bilder:

Rachel
quelle
1
Ich stimme GlenH7 zu, dies ist eine gute Antwort für jemanden, der mit WPF anfängt. Wir bekommen den Paradigmenwechsel der Interaktion zwischen dem View und dem ViewModel, so dass dies nicht wirklich zum Thema der von mir gestellten Frage gehörte.
user7676