Wyjaśnienie MVVM


15

Za chwilę napisamy naszą pierwszą aplikację WPF i zapoznamy się ze wzorem MVVM. Zbudowaliśmy wiele aplikacji Winform i mamy architekturę, która była dla nas bardzo udana. Mamy trochę problemów z tłumaczeniem tej architektury lub określeniem, gdzie pewne elementy naszej architektury pasują do modelu MVVM.

Historycznie mamy GUI (główny exe), który następnie komunikuje się z biblioteką DLL BusinessLogic. BusinessLogic komunikuje się z biblioteką DAL za pośrednictwem usługi internetowej, a DAL współdziała z bazą danych. DAL, BusinessLogic i GUI odwołują się do tej samej biblioteki DLL BusinessObjects.

Architektura AsIs

Część przejścia na MVVM jest dość prosta. Nasze GUI nadal będą zawierać widoki, nasze BusinessOjbects będą nadal zawierać model, a nasz DAL będzie nadal oddziaływać z DB (chociaż technologia ich wdrażania może się zmienić).

To, czego nie jesteśmy pewni, to nasz komponent BusinessLogic. Historycznie zapewniałoby to funkcje, które GUI może wywoływać, a następnie wypełniać kontrolki w widokach (tj. GetCustomerList, który zwróciłby listę obiektów Customer lub typowe funkcje CRUD).

Główne zawieszenie, jakie mamy, to to, czy wzorzec MVVM będzie wymagał dodatkowego komponentu do przechowywania ViewModels, czy też po prostu zmienimy sposób myślenia i przeprowadzimy migrację tego, co wykorzystaliśmy jako komponent BusinessLogic do ViewModels?

Czy nasz składnik BusinessLogic reprezentuje ViewModels?


Brzmi to trochę jak rozwiązanie problemu. Czy istnieje ważny powód, dla którego przeprowadzasz się do MVVM? Jestem fanem tego wzoru, ale czy poprzednie rozwiązanie nie działało? Model widoku przypomina nadzorującego prezentera. Zawiera logikę prezentacji i wyświetla dane poprzez powiązanie danych. Powinien wiedzieć o logice biznesowej i być w stanie dotrzeć do tego poziomu, ale nie zawaliłbym logiki biznesowej do samego modelu widoku.
Jeremy Likness

Odpowiedzi:


19

Zasadniczo nie umieszczałbym logiki biznesowej w warstwie modelu widoku. Ale termin „logika biznesowa” wprowadza w błąd.

Eric Evans stosuje model, w którym logika biznesowa jest podzielona na dwie kategorie

  • Logika domeny - logika związana z rzeczywistą domeną problemu, którą rozwiązujesz
  • Logika aplikacji - logika związana z budowaniem aplikacji

Wymienia przykład aplikacji księgowej. Reguły dotyczące kont, postów, kont podatkowych itp. To reguły dotyczące domen, reguły dotyczące domeny rachunkowości. Logika importu / eksportu CSV nie ma nic wspólnego z dziedziną rachunkowości. Te zasady istnieją wyłącznie dlatego, że budujemy aplikację. To są przykłady logiki aplikacji.

Reguły domeny NIGDY nie powinny wchodzić w warstwę modelu widoku. Jeśli podążasz za wzorcem MVVM, reguły domeny idą bez wątpienia do warstwy modelowej.

Reguły aplikacji, takie jak import / eksport CSV, mogą iść w warstwie modelu widoku. Ale osobiście wolałbym rozdzielić to na osobną warstwę logiczną aplikacji.

Model widoku powinien być bardzo prosty. Wyszukiwanie danych potrzebnych do widoku w odpowiednim modelu, aktualizowanie modelu, gdy widok się zmienia, nasłuchiwanie zdarzeń w modelu i propagowanie tych zdarzeń do widoku, umożliwiając aktualizację widoku, gdy model jest aktualizowany za sceną (jeśli dotyczy).

Osobiście upewniłbym się, że warstwa modelu widoku zawiera tylko jeden typ logiki, logikę prezentacji.


1
Doskonała odpowiedź. Podoba mi się to, żeby upewnić się, że ViewModel zawiera tylko logikę prezentacji. Czy możesz dodać link związany z punktem Erica Evansa?
user7676

Wątpię, czy mogę znaleźć link, ponieważ uważam, że dostałem go z jego książki, Domain-Driven Design. W każdym razie uważam, że jest to doskonały przykład różnicy między logiką domeny i aplikacji. Więcej o książce tutaj books.google.dk/books/about/…
Pete

5

Tak.

Warstwa logiki biznesowej jest reprezentowana przez warstwę maszyny wirtualnej. Po prostu migruj swój model mentalny.

Aby pomóc w migracji modelu mentalnego, jednym niewielkim niuansem jest to, że obiekty GUI (widok) powinny być powiązane z obiektami w warstwie maszyny wirtualnej. To wiązanie przekłada się na | oznacza, że ​​widok nie jest już warstwą, która „wykonuje połączenie” w celu odzyskania czegoś innego. Zamiast tego wezwanie do pobierania danych będzie pochodziło z maszyny wirtualnej.

Aby lepiej wyjaśnić: Tak, obiekt w Widoku będzie musiał się zmienić, aby uruchomić sekwencję rzeczy, które wykonają połączenie. Ale widok nie wykonuje samego połączenia. I w tym przypadku uważam, że kliknięcie przycisku jest równoważne zmianie w widoku, ale nadal nie wykonuje połączenia.

W pierwszym przypadku ten obiekt View zostanie powiązany z obiektem VM. Maszyna wirtualna powinna nasłuchiwać zdarzenia zmienionego właściwości na powiązanym obiekcie. Zdarzenie zmiany obiektu można następnie połączyć z funkcją maszyny wirtualnej, aby wykonać wywołanie modelu.

W drugim przypadku (zdarzenie kliknięcia przycisku) zdarzenie zmiany (kliknięcia) można połączyć z wywołaniem funkcji ujawnionym przez maszynę wirtualną.

Tak czy inaczej, zawsze jest to zdarzenie sekwencyjne w maszynie wirtualnej, która następnie wywołuje model, który z kolei wywołuje DAL / DB.

Mówię o tym, ponieważ część kodu WinForm jest używana do wywoływania warstwy DB bezpośrednio z kodu GUI WinForm. Takie podejście przerywa separację zapewnianą przez MVVM.


Dziękuję za potwierdzenie. Rozumiemy niuans tego, w jaki sposób widok wchodzi w interakcję z ViewModel i będziemy trzymać się modelu powiązania i porzucić „wywołanie”.
user7676,

Zauważyłem, że ta odpowiedź straciła głos. Byłbym ciekawy, czy downvoter skomentuje dlaczego? A może dodaj własną odpowiedź, jeśli nie podzielają tego punktu widzenia.
user7676,

1
Zgadzam się, że warstwa logiki biznesowej jest reprezentowana przez warstwę maszyny wirtualnej, jednak myślę, że niektóre części odpowiedzi mogą być mylące. ViewWarstwa ma być wizualnym przedstawieniem ViewModel lub modelu, więc zamiast mówić zdarzenie click jest podłączony do wywołania funkcji na VM, lepsza definicja byłoby powiedzieć komendę w VM pobiera renderowane jako przycisk warstwa Widok. Także, ja zazwyczaj nie lubią mojego warstwy modelu jest w stanie uzyskać dostęp do DAL bezpośrednio, więc mój flow aplikacja typowo iść VM -> DAL -> DB, gdzie VMi DALużywają równinie Modelobiektów danych.
Rachel

4
Nie zgadzam się z tą odpowiedzią. ViewModel jest modelem widoku, zawiera logikę widoku, a nie logikę biznesową. ViewModels są częścią warstwy prezentacji
simoraman

1
@simoraman - Wzorzec MVPVM jest zgodny z tym, co sugerujesz. Myślę, że MVPVM to dobry wzór, ale trochę cięższy dla mniejszych aplikacji. Naprawdę zachęciłbym was do odpowiedzi na swoje pytania i przyczynienia się do tego pytania.

5

Masz rację, że zasadniczo zastąpiłbyś swoją bibliotekę DLL BusinessLogic warstwą ViewModel, jednak myślę, że największą różnicą, na którą napotkasz, jest interakcja warstwy View / UI z warstwą ViewModel / BusinessLogic.

W WinForms GUI jest twoją aplikacją i odpowiada za przepływ aplikacji. W WPF / MVVM twoje ViewModels to Twoja aplikacja, a GUI staje się tylko przyjaznym interfejsem do interakcji z ViewModels.

Na przykład w WinForms możesz mieć DataGrid i Button, a po kliknięciu tego przycisku wywołujesz BusinessLogicLayer.GetProducts()i ładujesz wynikowe obiekty Product do DataGrid.

W przypadku WPF, miałbyś ViewModel, który zawiera ObservableCollection<Products>i ICommand GetProducts, a wykonanie polecenia wywołuje DAL i ładuje kolekcję produktów. Aby jednak zapewnić interfejs przyjazny dla użytkownika, należy utworzyć widok, który renderuje Twój model ViewModel przy użyciu DataGrid dla kolekcji Products oraz przycisku dla polecenia GetProducts.

Napisałem całkiem nowy post na moim blogu o zmianie sposobu myślenia podczas przechodzenia z Winforms do WPF na moim blogu i myślę, że najlepszym sposobem na podsumowanie różnicy są te zdjęcia:


1
Zgadzam się z GlenH7, to dobra odpowiedź dla osób rozpoczynających pracę z WPF. Otrzymujemy zmianę paradygmatu interakcji między View a ViewModel, więc to nie było tak naprawdę na zadane pytanie.
user7676,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.