Czy istnieje różnica między standardowym wzorcem „Model View Controller” a wzorcem Microsoft Model / View / ViewModel?
Czy istnieje różnica między standardowym wzorcem „Model View Controller” a wzorcem Microsoft Model / View / ViewModel?
Odpowiedzi:
Te dwa wzorce pojawiają się na różne sposoby, zarówno w rozwoju ASP.Net, jak i Silverlight / WPF.
W przypadku ASP.Net MVVM służy do dwukierunkowego wiązania danych w widokach. Zazwyczaj jest to implementacja po stronie klienta (np. Za pomocą Knockout.js). Z drugiej strony MVC jest sposobem na rozdzielenie problemów po stronie serwera .
W przypadku Silverlight i WPF wzorzec MVVM jest bardziej obejmujący i może wydawać się zastępować MVC (lub inne wzorce organizowania oprogramowania w oddzielne obowiązki). Jednym z założeń, które często wyszedł z tego wzoru, było to, że ViewModel
po prostu wymienić regulator w MVC
(jakby można po prostu zastąpić VM
na C
w akronimem i wszystko zostanie wybaczone) ...
Problem polega na tym, że aby być niezależnie testowalnym *, a szczególnie wielokrotnego użytku w razie potrzeby, model widoku nie ma pojęcia, jaki widok go wyświetla, ale co ważniejsze, nie ma pojęcia, skąd pochodzą jego dane .
* Uwaga: w praktyce Kontrolery usuwają większość logiki z ViewModel, która wymaga testów jednostkowych. Maszyna wirtualna staje się wówczas głupim kontenerem, który wymaga niewiele testów, o ile w ogóle je ma. To dobrze, ponieważ VM jest tylko pomostem między projektantem a programistą, dlatego należy zachować prostotę.
Nawet w MVVM kontrolery zwykle zawierają całą logikę przetwarzania i decydują, jakie dane wyświetlić, w których widokach, używając modeli widoków.
Z tego, co widzieliśmy do tej pory, główną zaletą wzorca ViewModel jest usunięcie kodu z kodu XAML z tyłu, aby edycja XAML była bardziej niezależnym zadaniem . Nadal tworzymy kontrolery, w razie potrzeby, w celu kontrolowania (bez zamierzonej gry słów) ogólnej logiki naszych aplikacji.
Zauważyliśmy również, że struktura kodu genów rzeźby implementuje MVVM i wzorzec podobny do Prism ORAZ, a także szeroko wykorzystuje kontrolery do oddzielenia całej logiki przypadków użycia.
Założyłem blog na ten temat, do którego dodam, kiedy i kiedy będę mógł . Występują problemy z łączeniem MVCVM ze zwykłymi systemami nawigacji, ponieważ większość systemów nawigacji korzysta tylko z widoków i maszyn wirtualnych, ale przejdę do tego w późniejszych artykułach.
Dodatkową zaletą korzystania z modelu MVCVM jest to, że tylko obiekty kontrolera muszą istnieć w pamięci przez cały okres użytkowania aplikacji, a kontrolery zawierają głównie kod i niewiele danych o stanie (tj. Niewielki narzut pamięci). To sprawia, że aplikacje zużywają dużo mniej pamięci niż rozwiązania, w których muszą być zachowane modele widoków i jest to idealne rozwiązanie dla niektórych rodzajów programowania urządzeń mobilnych (np. Windows Mobile przy użyciu Silverlight / Prism / MEF). Zależy to oczywiście od rodzaju aplikacji, ponieważ może być konieczne zachowanie sporadycznie buforowanych maszyn wirtualnych w celu zapewnienia czasu reakcji.
Uwaga: ten post był edytowany wiele razy i nie był specjalnie ukierunkowany na wąskie zadane pytanie, więc zaktualizowałem pierwszą część, aby teraz również to obejmować. Duża część dyskusji, w komentarzach poniżej, dotyczy tylko ASP.Net, a nie szerszego obrazu. Ten post miał na celu szersze zastosowanie MVVM w Silverlight, WPF i ASP.Net i starał się zniechęcić ludzi do zamiany kontrolerów na ViewModels.
Myślę, że najłatwiejszym sposobem na zrozumienie, co oznaczają te akronimy, jest chwilowe zapomnienie o nich. Zamiast tego pomyśl o oprogramowaniu, z którego pochodzą, o każdym z nich. To naprawdę sprowadza się do różnicy między wczesną siecią a komputerem.
Wraz ze wzrostem złożoności w połowie 2000 r. Wzorzec projektowania oprogramowania MVC - po raz pierwszy opisany w latach 70. XX wieku - zaczął być stosowany do aplikacji internetowych. Pomyśl między bazą danych, stronami HTML i kodem. Udoskonalmy to trochę, aby dotrzeć do MVC: dla »bazy danych« załóżmy bazę danych plus kod interfejsu. Dla »stron HTML« załóżmy szablony HTML plus kod przetwarzania szablonów. Dla »kodu pomiędzy« załóżmy, że użytkownik mapuje kod kliknięć użytkownika na działania, prawdopodobnie wpływając na bazę danych, zdecydowanie powodując wyświetlenie innego widoku. To wszystko, przynajmniej na potrzeby tego porównania.
Zachowajmy jedną cechę tych rzeczy, nie tak jak dzisiaj, ale tak jak istniała dziesięć lat temu, kiedy JavaScript był nędzną, nikczemną irytacją, której prawdziwi programiści dobrze unikali: strona HTML jest zasadniczo głupia i pasywna . Przeglądarka jest cienkim klientem lub, jeśli wolisz, słabym klientem. W przeglądarce nie ma inteligencji. Reguła przeładowania całej strony. „Widok” jest generowany za każdym razem od nowa.
Pamiętajmy, że ten internetowy sposób, mimo że jest wściekły, był okropnie zacofany w porównaniu do pulpitu. Aplikacje komputerowe to grubi klienci lub bogaci klienci, jeśli wolisz. (Nawet taki program jak Microsoft Word można uznać za pewnego rodzaju klienta, klienta dokumentów.) Są to klienci pełni inteligencji, wiedzy o swoich danych. Są stanowe. Przechowują w pamięci dane, które przetwarzają. Żadnych takich badziewi jak pełne przeładowanie strony.
I ten bogaty sposób pulpitu prawdopodobnie pochodzi od drugiego akronimu, MVVM. Nie daj się zwieść literom, pominięciu C. Kontrolery wciąż tam są. Muszą być. Nic nie zostanie usunięte. Dodajemy tylko jedną rzecz: stan, dane buforowane na kliencie (a wraz z nim inteligencja do obsługi tych danych). Te dane, zasadniczo pamięć podręczna klienta, są teraz nazywane »ViewModel«. To pozwala na bogatą interaktywność. I to wszystko.
Widzimy, że dzięki Flash, Silverlight i - co najważniejsze - JavaScript, Internet objął MVVM. Przeglądarek nie można już legalnie nazywać cienkimi klientami. Spójrz na ich programowalność. Spójrz na ich zużycie pamięci. Spójrz na całą interaktywność Javascript na nowoczesnych stronach internetowych.
Osobiście uważam tę teorię i akronim za łatwiejszy do zrozumienia, patrząc na to, do czego się odnosi w konkretnej rzeczywistości. Pojęcia abstrakcyjne są przydatne, zwłaszcza gdy są prezentowane na konkretnej materii, więc zrozumienie może zatoczyć koło.
MVVM Model-View ViewModel jest podobny do MVC, Model-View Controller
Kontroler zastąpiono ViewModel . ViewModel znajduje się poniżej warstwy interfejsu użytkownika. ViewModel udostępnia obiekty danych i poleceń, których potrzebuje widok. Możesz myśleć o tym jak o obiekcie kontenerowym, z którego widok pobiera dane i akcje. ViewModel pobiera dane z modelu.
Russel East prowadzi blog omawiający bardziej szczegółowo Dlaczego MVVM różni się od MVC
If you put ten software architects into a room and have them discuss what the Model-View-Controller pattern is, you will end up with twelve different opinions. …
Po pierwsze, MVVM jest postępem wzoru MVC, który używa XAML do obsługi wyświetlania. W tym artykule opisano niektóre aspekty tych dwóch aspektów.
Głównym założeniem architektury Model / View / ViewModel wydaje się być to, że na wierzchu danych („Model”) znajduje się kolejna warstwa komponentów niewizualnych („ViewModel”), które dokładniej odwzorowują pojęcia danych do koncepcji widoku danych („Widok”). Jest to ViewModel, z którym łączy się widok, a nie bezpośrednio model.
Microsoft podał tutaj wyjaśnienie Wzorca MVVM w środowisku Windows .
Oto kluczowa sekcja:
We wzorcu projektowym Model-View-ViewModel aplikacja składa się z trzech ogólnych komponentów.
Model : reprezentuje model danych używany przez aplikację. Na przykład w aplikacji do udostępniania zdjęć warstwa ta może reprezentować zestaw zdjęć dostępnych na urządzeniu oraz interfejs API używany do odczytu i zapisu w bibliotece obrazów.
Widok : aplikacja zazwyczaj składa się z wielu stron interfejsu użytkownika. Każda strona pokazana użytkownikowi jest widokiem w terminologii MVVM. Widok jest kodem XAML używanym do definiowania i stylizowania tego, co widzi użytkownik. Dane z modelu są wyświetlane użytkownikowi, a zadaniem ViewModel jest karmienie interfejsu użytkownika tymi danymi w oparciu o bieżący stan aplikacji. Na przykład w aplikacji do udostępniania zdjęć widokami będzie interfejs użytkownika, który pokazuje użytkownikowi listę albumów na urządzeniu, zdjęcia w albumie, a być może inny, który pokazuje użytkownikowi określone zdjęcie.
ViewModel : ViewModel łączy model danych lub po prostu model z interfejsem użytkownika lub widokami aplikacji. Zawiera logikę, za pomocą której można zarządzać danymi z modelu, i udostępnia dane jako zestaw właściwości, z którymi interfejs XAML lub widoki mogą się wiązać. Na przykład w aplikacji do udostępniania zdjęć ViewModel udostępnia listę albumów, a dla każdego albumu wyświetla listę zdjęć. Interfejs użytkownika jest niezależny od tego, skąd pochodzą zdjęcia i jak są one pobierane. Po prostu wie o zestawie zdjęć odsłoniętych przez ViewModel i pokazuje je użytkownikowi.
Pomyślałem, że jedną z głównych różnic jest to, że w MVC twoje V odczytuje bezpośrednio M i przechodzi przez C, aby manipulować danymi, podczas gdy w MVVM, twoja maszyna wirtualna działa jako proxy M, a także zapewnia ci dostępną funkcjonalność V.
Jeśli nie jestem pełen śmieci, jestem zaskoczony, że nikt nie stworzył hybrydy, w której maszyna wirtualna jest jedynie proxy M, a C zapewnia całą funkcjonalność.
MVC jest środowiskiem kontrolowanym, a MVVM jest środowiskiem reaktywnym.
W kontrolowanym środowisku powinieneś mieć mniej kodu i wspólne źródło logiki; które powinny zawsze znajdować się w kontrolerze. Jednak; w świecie internetowym MVC łatwo dzieli się na logikę tworzenia widoków i logikę dynamiczną. Kreacja żyje na serwerze, a dynamiczna na kliencie. Widać to bardzo często w przypadku ASP.NET MVC w połączeniu z AngularJS, podczas gdy serwer utworzy widok i przekaże model i wyśle go do klienta. Klient będzie wtedy wchodził w interakcję z widokiem, w którym to przypadku AngularJS wkracza jako lokalny kontroler. Po przesłaniu Model lub nowy Model jest przekazywany z powrotem do kontrolera serwera i obsługiwany. (Tak więc cykl trwa i istnieje wiele innych tłumaczeń tej obsługi podczas pracy z gniazdami, AJAX itp., Ale w całej architekturze jest identyczny.)
MVVM to środowisko reaktywne, co oznacza, że zwykle piszesz kod (np. Wyzwalacze), który aktywuje się na podstawie określonego zdarzenia. W XAML, gdzie rozwija się MVVM, wszystko to można łatwo zrobić za pomocą wbudowanego szkieletu wiązania danych, ALE, jak wspomniano, będzie działać na dowolnym systemie w dowolnym widoku z dowolnym językiem programowania. To nie jest specyficzne dla SM. ViewModel odpala (zwykle zdarzenie zmieniające właściwość), a View reaguje na to w oparciu o wszelkie utworzone przez Ciebie wyzwalacze. Może to stać się techniczne, ale sedno jest takie, że widok jest bezstanowy i bez logiki. Po prostu zmienia stan na podstawie wartości. Ponadto ViewModels są bezstanowe z bardzo małą logiką, a Modele są stanem o zasadniczo zerowej logice, ponieważ powinny jedynie utrzymywać stan. Opisuję to jako stan aplikacji (Model), translator stanu (ViewModel), a następnie stan wizualny / interakcja (Widok).
W aplikacji stacjonarnej lub klienckiej MVC powinieneś mieć Model, a Model powinien być używany przez Kontroler. W zależności od modelu kontroler zmodyfikuje widok. Widoki są zwykle powiązane z kontrolerami z interfejsami, dzięki czemu kontroler może pracować z różnymi widokami. W ASP.NET logika MVC jest nieco cofnięta na serwerze, ponieważ kontroler zarządza modelami i przekazuje modele do wybranego widoku. Widok jest następnie wypełniany danymi opartymi na modelu i ma własną logikę (zwykle inny zestaw MVC, taki jak zrobiony z AngularJS). Ludzie będą się kłócić i mylą to z aplikacją MVC i spróbują zrobić oba, w których utrzymanie projektu ostatecznie stanie się katastrofą. ZAWSZE umieszczaj logikę i sterowanie w jednym miejscu podczas korzystania z MVC. NIE zapisuj logiki View w kodzie za View (lub w View poprzez JS dla sieci), aby pomieścić dane sterownika lub modelu. Pozwól, aby kontroler zmienił widok. JEDYNA logika, która powinna istnieć w Widoku, to wszystko, czego potrzeba do utworzenia i uruchomienia za pomocą interfejsu, którego używa. Przykładem tego jest podanie nazwy użytkownika i hasła. Niezależnie od tego, czy jest to komputer stacjonarny czy strona internetowa (na kliencie), kontroler powinien obsłużyć proces wysyłania, ilekroć widok uruchamia akcję wysyłania. Jeśli zrobisz to poprawnie, zawsze możesz łatwo znaleźć drogę do sieci MVC lub aplikacji lokalnej. Niezależnie od tego, czy jest to komputer stacjonarny czy strona internetowa (na kliencie), kontroler powinien obsłużyć proces wysyłania, ilekroć widok uruchamia akcję wysyłania. Jeśli zrobisz to poprawnie, zawsze możesz łatwo znaleźć drogę do sieci MVC lub aplikacji lokalnej. Niezależnie od tego, czy jest to komputer stacjonarny czy strona internetowa (na kliencie), kontroler powinien obsłużyć proces wysyłania, ilekroć widok uruchamia akcję wysyłania. Jeśli zrobisz to poprawnie, zawsze możesz łatwo znaleźć drogę do sieci MVC lub aplikacji lokalnej.
MVVM jest osobiście moim ulubionym, ponieważ jest całkowicie reaktywny. Jeśli stan modelu zmienia się, ViewModel nasłuchuje i tłumaczy ten stan i to wszystko !!! Widok następnie nasłuchuje ViewModel w celu zmiany stanu, a także aktualizuje się na podstawie tłumaczenia z ViewModel. Niektórzy nazywają to czystym MVVM, ale tak naprawdę jest tylko jeden i nie obchodzi mnie, jak się z tym kłócisz, i zawsze jest to czysty MVVM, w którym widok nie zawiera absolutnie żadnej logiki.
Oto mały przykład: Powiedzmy, że chcesz, aby menu wsuwało się po naciśnięciu przycisku. W MVC będziesz mieć akcję MenuPressed w swoim interfejsie. Kontroler będzie wiedział, kiedy klikniesz przycisk Menu, a następnie powiesz widokowi, aby przesunął się w menu w oparciu o inną metodę interfejsu, taką jak SlideMenuIn. Z jakiego powodu podróż w obie strony? Incase Kontroler decyduje, że nie możesz lub chce zrobić coś innego, dlatego właśnie. Kontroler powinien być odpowiedzialny za Widok, gdy Widok nic nie robi, chyba że Administrator tak mówi. JEDNAK; w MVVM menu slajdów w animacji powinno być wbudowane i ogólne, a zamiast być poproszony o włączenie, zrobi to na podstawie pewnej wartości. Więc nasłuchuje ViewModel, a gdy ViewModel mówi, IsMenuActive = true (lub jakkolwiek) animacja, która ma miejsce. Teraz, Powiedziawszy to, chcę powiedzieć jeszcze raz, NAPRAWDĘ JASNE i PROSZĘ zwrócić uwagę. IsMenuActive jest prawdopodobnie BAD MVVM lub ViewModel. Projektując ViewModel, nigdy nie należy zakładać, że Widok będzie miał w ogóle jakieś funkcje i po prostu przekaże przetłumaczony stan modelu. W ten sposób, jeśli zdecydujesz się zmienić widok, aby usunąć menu i po prostu pokazać dane / opcje w inny sposób, ViewModel nie ma znaczenia. Jak więc zarządzałbyś menu? Kiedy dane mają sens, właśnie tak. Jednym ze sposobów jest udostępnienie Menu listy opcji (prawdopodobnie tablicy wewnętrznych modeli ViewModels). Jeśli ta lista zawiera dane, menu wie, że można otworzyć za pomocą wyzwalacza, jeśli nie, to wie, że można ukryć za pomocą wyzwalacza. Po prostu masz dane dla menu lub nie w ViewModel. NIE decyduj się na pokazywanie / ukrywanie tych danych w ViewModel. po prostu przetłumacz stan modelu. W ten sposób widok jest całkowicie reaktywny i ogólny i może być używany w wielu różnych sytuacjach.
Wszystko to prawdopodobnie nie ma absolutnie żadnego sensu, jeśli nie znasz już co najmniej architektury każdego z nich, a nauka może być bardzo myląca, ponieważ w sieci znajdziesz DUŻO ZŁEJ informacji.
Więc ... rzeczy, o których należy pamiętać, aby zrobić to dobrze. Zdecyduj z wyprzedzeniem, jak zaprojektować swoją aplikację i PRZYKLEJ.
Jeśli korzystasz z MVC, co jest świetne, upewnij się, że kontrolerem można zarządzać i mieć pełną kontrolę nad swoim widokiem. Jeśli masz duży widok, rozważ dodanie do niego elementów sterujących, które mają różne kontrolery. PO PROSTU NIE kaskaduj tych kontrolerów z różnymi kontrolerami. Bardzo frustrujące w utrzymaniu. Poświęć chwilę i zaprojektuj wszystko osobno w taki sposób, aby działało ono jako osobne komponenty ... I zawsze pozwól Kontrolerowi powiedzieć Modelowi, aby zatwierdził lub utrzymał pamięć. Idealną konfiguracją zależności dla MVC w jest Widok ← Kontroler → Model lub ASP.NET (nie zaczynaj mnie) Model ← Widok ↔ Kontroler → Model (gdzie Model może być taki sam lub zupełnie inny Model od Kontrolera do Widoku) ... oczywiście jedyną potrzebną wiedzą na temat Kontrolera w Widoku w tym momencie jest głównie odniesienie do punktu końcowego, aby wiedzieć, gdzie z powrotem przekazać model.
Jeśli wykonujesz MVVM, błogosławię twoją uprzejmą duszę, ale poświęć trochę czasu, aby zrobić to PRAWO! Nie używaj interfejsów dla jednego. Pozwól, aby Twój widok decydował o tym, jak będzie wyglądać na podstawie wartości. Graj z widokiem z próbnymi danymi. Jeśli w końcu zobaczysz widok, który pokazuje menu (jak w przykładzie), nawet jeśli nie chciałeś go wtedy, to DOBRY. Twój widok działa tak, jak powinien i reaguje w oparciu o wartości, jak powinien. Wystarczy dodać kilka dodatkowych wymagań do wyzwalacza, aby upewnić się, że tak się nie stanie, gdy ViewModel jest w konkretnym przetłumaczonym stanie lub wydać polecenie ViewModel, aby opróżnić ten stan. W swoim ViewModel NIE usuwaj tego z wewnętrzną logiką, tak jakbyś decydował stamtąd, czy widok powinien to zobaczyć. Pamiętaj, że nie możesz zakładać, że w ViewModel jest menu. I w końcu, Model powinien po prostu pozwalać na zmianę i najprawdopodobniej stan sklepu. To tutaj nastąpi walidacja i wszystko; na przykład, jeśli model nie może zmodyfikować stanu, po prostu oznaczy się jako brudny lub coś w tym rodzaju. Kiedy ViewModel zda sobie z tego sprawę, przetłumaczy to, co jest brudne, a następnie View zda sobie z tego sprawę i pokaże pewne informacje za pośrednictwem innego wyzwalacza. Wszystkie dane w Widoku można powiązać z ViewModel, więc wszystko może być dynamiczne tylko Model i ViewModel absolutnie nie ma pojęcia o tym, jak Widok zareaguje na powiązanie. W rzeczywistości Model nie ma też pojęcia o ViewModel. Podczas konfigurowania zależności powinny wskazywać tak i tylko tak t zmodyfikuj stan, a następnie oznaczy się jako brudny lub coś takiego. Kiedy ViewModel zda sobie z tego sprawę, przetłumaczy to, co jest brudne, a następnie View zda sobie z tego sprawę i pokaże pewne informacje za pośrednictwem innego wyzwalacza. Wszystkie dane w Widoku można powiązać z ViewModel, więc wszystko może być dynamiczne tylko Model i ViewModel absolutnie nie ma pojęcia o tym, jak Widok zareaguje na powiązanie. W rzeczywistości Model nie ma też pojęcia o ViewModel. Podczas konfigurowania zależności powinny wskazywać tak i tylko tak t zmodyfikuj stan, a następnie oznaczy się jako brudny lub coś takiego. Kiedy ViewModel zda sobie z tego sprawę, przetłumaczy to, co jest brudne, a następnie View zda sobie z tego sprawę i pokaże pewne informacje za pośrednictwem innego wyzwalacza. Wszystkie dane w Widoku można powiązać z ViewModel, więc wszystko może być dynamiczne tylko Model i ViewModel absolutnie nie ma pojęcia o tym, jak Widok zareaguje na powiązanie. W rzeczywistości Model nie ma też pojęcia o ViewModel. Podczas konfigurowania zależności powinny wskazywać tak i tylko tak Wszystkie dane w Widoku można powiązać z ViewModel, więc wszystko może być dynamiczne tylko Model i ViewModel absolutnie nie ma pojęcia o tym, jak Widok zareaguje na powiązanie. W rzeczywistości Model nie ma też pojęcia o ViewModel. Podczas konfigurowania zależności powinny wskazywać tak i tylko tak Wszystkie dane w Widoku można powiązać z ViewModel, więc wszystko może być dynamiczne tylko Model i ViewModel absolutnie nie ma pojęcia o tym, jak Widok zareaguje na powiązanie. W rzeczywistości Model nie ma też pojęcia o ViewModel. Podczas konfigurowania zależności powinny wskazywać tak i tylko takWidok → ViewModel → Model (i notatka boczna tutaj ... i to zapewne będzie również przedmiotem sporu, ale mnie to nie obchodzi ... NIE PRZEKAZAJ MODELU WIDOKU, chyba że MODEL jest niezmienny; w przeciwnym razie owiń go właściwy ViewModel. Widok nie powinien widzieć okresu modelowania. Szczurom daję znać, jakie demo widziałeś lub jak to zrobiłeś, to źle.)
Oto moja ostatnia wskazówka ... Spójrz na dobrze zaprojektowaną, ale bardzo prostą aplikację MVC i zrób to samo dla aplikacji MVVM. Jeden będzie miał większą kontrolę z ograniczoną do zera elastycznością, podczas gdy drugi nie będzie miał kontroli i nieograniczonej elastyczności.
Kontrolowane środowisko jest dobre do zarządzania całą aplikacją z zestawu kontrolerów lub (z jednego źródła), podczas gdy środowisko reaktywne można podzielić na osobne repozytoria, absolutnie nie mając pojęcia, co robi reszta aplikacji. Zarządzanie mikro a zarządzanie bezpłatne.
Jeśli nie pomyliłem cię wystarczająco, spróbuj się ze mną skontaktować ... Nie mam nic przeciwko omówieniu tego szczegółowo z ilustracjami i przykładami.
Pod koniec dnia wszyscy jesteśmy programistami i ta anarchia żyje w nas podczas kodowania ... Więc zasady zostaną złamane, teorie się zmienią, a wszystko to skończy się praniem świń ... Ale podczas pracy nad dużymi w projektach i w dużych zespołach naprawdę pomaga uzgodnić wzór projektowy i go egzekwować. Pewnego dnia małe dodatkowe kroki podjęte na początku staną się skokami i granicami oszczędności później.
Prosta różnica: (zainspirowany kursem Yaakova Coursera AngularJS)
MVC (kontroler widoku modelu)
MVVM (widok modelu Zobacz model)
ViewModel :
MVVM jest udoskonaleniem (dyskusyjnym) wzorca modelu prezentacji . Mówię, że można dyskutować, ponieważ jedyna różnica polega na tym, jak WPF zapewnia możliwość wiązania danych i obsługi poleceń.
Viewmodel jest „abstrakcyjnym” modelem elementów interfejsu użytkownika. Musi umożliwiać wykonywanie poleceń i działań w twoim widoku w sposób niewizualny (na przykład w celu przetestowania).
Jeśli pracowałeś z MVC, prawdopodobnie kiedyś przydało ci się tworzenie obiektów modelowych odzwierciedlających stan twojego widoku, na przykład do pokazywania i ukrywania niektórych okien dialogowych edycji itp. W takim przypadku używasz modelu widoku.
Wzorzec MVVM jest po prostu uogólnieniem tej praktyki na wszystkie elementy interfejsu użytkownika.
I nie jest to wzorzec Microsoft, ale dołącza się to, że powiązania danych WPF / Silverlight są szczególnie dobrze przystosowane do pracy z tym wzorcem. Ale nic nie stoi na przeszkodzie, aby na przykład używać go z twarzami serwera Java.
Inne odpowiedzi mogą nie być łatwe do zrozumienia dla osoby, która nie zna dobrze wzorów architektonicznych. Ktoś, kto jest nowy w architekturze aplikacji, może chcieć wiedzieć, w jaki sposób jego wybór może wpłynąć na jej aplikację w praktyce i o co tyle zamieszania w społecznościach.
Próbując rzucić nieco światła na powyższe, wymyśliłem ten scenariusz z udziałem MVVM, MVP i MVC. Historia zaczyna się od kliknięcia przez użytkownika przycisku „ZNAJDŹ” w wyszukiwarce filmów…:
Użytkownik: kliknij…
Zobacz : Kto to jest? [ MVVM | MVP | MVC ]
Użytkownik: Właśnie kliknąłem przycisk wyszukiwania…
Widok : Ok, poczekaj chwilę… [ MVVM | MVP | MVC ]
( Zobacz wywoływanie ViewModel | Prezenter | Kontroler …) [ MVVM | MVP | MVC ]
Widok : Hej ViewModel | Prezenter | Kontrolerze , użytkownik właśnie kliknął przycisk wyszukiwania, co mam zrobić? [ MVVM | MVP | MVC ]
ViewModel | Prezenter | Kontroler : Hey Zobacz , czy jest jakiś termin wyszukiwania na tej stronie? [ MVVM | MVP | MVC ]
Widok : Tak,… tutaj jest… „fortepian” [ MVVM | MVP | MVC ]
—— Jest to najważniejsza różnica między MVVM I MVP | MVC ———
Prezenter : Dzięki Widok ,… tymczasem szukam wyszukiwanego hasła w Modelu , pokaż mu pasek postępu [ MVP | MVC ]
( Prezenter | Kontroler dzwoni do modelu …) [ MVP | MVC ]
ViewController : Dzięki, sprawdzę wyszukiwane hasło w Modelu, ale nie zaktualizuję cię bezpośrednio. Zamiast tego wywołam zdarzenia w searchResultsListObservable, jeśli wystąpi jakikolwiek wynik. Więc lepiej to obserwuj. [ MVVM ]
(Obserwując dowolny wyzwalacz w searchResultsListObservable, widok uważa, że powinien pokazywać użytkownikowi pasek postępu, ponieważ ViewModel nie chce z nim rozmawiać)
—————————————————————————————
ViewModel | Prezenter | Kontroler : Hej, model , czy pasujesz do tego wyszukiwanego terminu ?: „piano” [ MVVM | MVP | MVC ]
Model : Hej ViewModel | Prezenter | Kontroler , pozwól mi sprawdzić… [ MVVM | MVP | MVC ]
( Model wykonuje zapytanie do bazy danych filmów…) [ MVVM | MVP | MVC ]
( Po chwili … )
———— To jest punkt rozbieżności między MVVM , MVP i MVC ————–
Model : Znalazłem dla ciebie listę, ViewModel | Prezenter , tutaj jest w JSON „[{„ name ”:„ Piano Teacher ”,„ year ”: 2001}, {„ name ”:„ Piano ”,„ year ”: 1993}]” [ MVVM | MVP ]
Model : Dostępne są wyniki, Kontroler. Utworzyłem zmienną pola w moim wystąpieniu i wypełniłem ją wynikiem. Nazywa się „searchResultsList” [ MVC ]
( Prezenter | Kontroler dziękuje Modelowi i wraca do Widoku ) [ MVP | MVC ]
Prezenter : Dzięki za czekanie. Widok , znalazłem dla ciebie listę pasujących wyników i uporządkowałem je w możliwym do przedstawienia formacie: [„Piano Teacher 2001 ″,” Piano 1993 ”]. Teraz też ukryj pasek postępu [ MVP ]
Kontroler : Dzięki za czekanie. Widok , poprosiłem model o zapytaniu. Mówi, że znalazł listę pasujących wyników i zapisał je w zmiennej o nazwie „searchResultsList” wewnątrz swojej instancji. Możesz go zdobyć stamtąd. Teraz też ukryj pasek postępu [ MVC ]
ViewModel : Każdy obserwator w searchResultsListObservable powinien zostać powiadomiony, że istnieje nowa lista w formacie do prezentacji: [„Piano Teacher 2001 ″,” Piano 1993 ”]. [ MVVM ]
Zobacz : Bardzo dziękuję Prezenterowi [ MVP ]
Widok : Dziękuję „ Kontroler ” [ MVC ] (teraz widok sam siebie zadaje pytanie: w jaki sposób mam przedstawić użytkownikowi wyniki uzyskane z modelu ? Czy rok produkcji filmu powinien być pierwszy czy ostatni…?)
Widok : Och, w searchResultsListObservable jest nowy wyzwalacz… dobrze, jest lista do zaprezentowania, teraz muszę tylko pokazać ją na liście. Powinienem też ukryć pasek postępu, skoro mam już wynik. [ MVVM ]
W przypadku zainteresowania, napisałem szereg artykułów tutaj , porównując MVVM, MVP i MVC poprzez wdrożenie film szukać Android app.
W tym modelu nie ma już kontaktu na poziomie HTTP z obiektami żądania lub odpowiedzi, ponieważ maszyna MVC MSFT ukrywa je przed nami.
W wyjaśnieniu do pkt 6 powyżej (na żądanie) ...
Załóżmy ViewModel w ten sposób:
public class myViewModel{
public string SelectedValue {get;set;}
public void Post(){
//due to MVC model binding the SelectedValue string above will be set by MVC model binding on post back.
//this allows you to do something with it.
DoSomeThingWith(SelectedValue);
SelectedValue = "Thanks for update!";
}
}
Metoda kontrolera posta będzie wyglądać następująco (patrz poniżej), zauważ, że wystąpienie mvm jest automatycznie inicjowane przez mechanizmy wiązania MVC. W rezultacie nigdy nie musisz zejść do warstwy ciągu zapytania! To jest MVC tworzący dla Ciebie ViewModel na podstawie ciągów zapytań!
[HTTPPOST]
public ActionResult MyPostBackMethod (myViewModel mvm){
if (ModelState.IsValid)
{
// Immediately call the only method needed in VM...
mvm.Post()
}
return View(mvm);
}
Pamiętaj, że aby powyższa metoda działania działała zgodnie z Twoimi zamierzeniami, musisz mieć zdefiniowany pusty CTOR, który zainicjalizuje rzeczy, które nie zostały zwrócone w poście. Zwrot musi również zaksięgować pary nazwa / wartość dla tych rzeczy, które uległy zmianie. Jeśli brakuje par nazwa-wartość, silnik wiązania MVC robi to, co jest po prostu niczym! Jeśli tak się zdarzy, możesz powiedzieć, że „tracę dane na postach”…
Zaletą tego wzorca jest to, że ViewModel wykonuje wszystkie „bałagany”, współpracując z logiką Model / Biznes, kontroler jest jedynie swego rodzaju routerem. To jest SOC w akcji.
MVVM dodaje model widoku do miksu. Jest to ważne, ponieważ pozwala na zastosowanie wielu wiążących podejść WPF, bez umieszczania wszystkich elementów specyficznych dla interfejsu użytkownika w zwykłym modelu.
Mogę się mylić, ale nie jestem pewien, czy MVVM naprawdę zmusza kontroler do miksu. Uważam, że koncepcja jest bardziej zgodna z: http://martinfowler.com/eaaDev/PresentationModel.html . Myślę, że ludzie decydują się na połączenie go z MVC, nie dlatego, że jest to wbudowane we wzór.
Z tego, co mogę powiedzieć, MVVM odwzorowuje na MV MVC - co oznacza, że w tradycyjnym wzorze MVC V nie komunikuje się bezpośrednio z M. W drugiej wersji MVC istnieje bezpośrednie połączenie między M i V. MVVM wydaje się brać wszystkie zadania związane z komunikacją M i V i łączyć je w celu oddzielenia od C. W efekcie nadal istnieje przepływ pracy aplikacji o większym zakresie (lub implementacja scenariuszy użytkowania), które nie są w pełni uwzględnione w MVVM. To jest rola kontrolera. Usuwając te aspekty niższego poziomu z kontrolerów, są one czystsze i ułatwiają modyfikowanie scenariusza użytkowania aplikacji i logiki biznesowej, dzięki czemu kontrolery są bardziej przydatne do ponownego użycia.
Zaskakuje mnie, że to głosowanie, na które głosowano, nie wspominając o pochodzeniu MVVM. MVVM jest popularnym terminem używanym w społeczności Microsoft i pochodzi z modelu prezentacji Martina Fowlera . Aby zrozumieć motyw wzoru i różnice z innymi, najpierw należy przeczytać oryginalny artykuł o wzorze.
Cóż, ogólnie MVC jest używany do tworzenia stron internetowych, a MVVM jest najbardziej popularny w rozwoju WPF / Silverlight. Czasami jednak architekt WWW może mieć mieszankę MVC i MVVM.
Na przykład: możesz użyć knockout.js iw tym przypadku będziesz mieć MVVM po stronie klienta. Po stronie serwera MVC można również zmienić. W złożonych aplikacjach nikt nie używa czystego Modelu. Może mieć sens użycie ViewModel jako „Modelu” MVC, a twój prawdziwy model będzie w zasadzie częścią tej maszyny wirtualnej. Daje to dodatkową warstwę abstrakcji.
MVVMC, a może MVC +, wydaje się być realnym podejściem zarówno dla przedsiębiorstw, jak i szybkiego opracowywania aplikacji. Chociaż miło jest oddzielić interfejs użytkownika od logiki biznesowej i interakcji, „czysty” wzorzec MVVM i większość dostępnych przykładów najlepiej działa w pojedynczych widokach.
Nie jestem pewien co do twoich projektów, ale większość moich aplikacji zawiera jednak strony i kilka (wielokrotnego użytku) widoków, dlatego też ViewModels muszą do pewnego stopnia współdziałać. Użycie strony jako kontrolera całkowicie zniweczyłoby cel MVVM, więc niestosowanie podejścia „VM-C” dla logiki leżącej u jej podstaw może spowodować… no cóż… trudne konstrukcje w miarę dojrzewania aplikacji. Nawet w VB-6 większość z nas prawdopodobnie przestała kodować logikę biznesową w zdarzeniu Button i zaczęła „przekazywać” polecenia do kontrolera, prawda? Niedawno przyjrzałem się wielu nowym ramkom na ten temat; moim ulubionym jest wyraźnie podejście Magellana (w codeplex). Miłego kodowania!
http://en.wikipedia.org/wiki/Model_View_ViewModel#References
Kontroler nie jest zastępowany przez ViewModel w MVVM, ponieważ ViewModel ma zupełnie inną funkcjonalność niż kontroler. Nadal potrzebujesz kontrolera, ponieważ bez kontrolera Twój model, ViewModel i View nie zrobią wiele ... W MVVM masz również kontroler, nazwa MVVM jest po prostu myląca.
MVVMC to poprawne imię w mojej skromnej opinii.
Jak widać ViewModel jest tylko dodatkiem do wzoru MVC. Przenosi logikę konwersji (na przykład konwersję obiektu na ciąg) z kontrolera do ViewModel.
Zrobiłem w tym celu artykuł Medium.
MVVM
Zobacz ➡ ViewModel ➡ Model
Jeśli używasz kontrolera, może on mieć odniesienie do widoków i modeli ViewModels , chociaż kontroler nie zawsze jest konieczny, jak pokazano w SwiftUI .
class CustomView: UIView {
var viewModel = MyViewModel {
didSet {
self.color = viewModel.color
}
}
convenience init(viewModel: MyViewModel) {
self.viewModel = viewModel
}
}
struct MyViewModel {
var viewColor: UIColor {
didSet {
colorChanged?() // This is where the binding magic happens.
}
}
var colorChanged: ((UIColor) -> Void)?
}
class MyViewController: UIViewController {
let myViewModel = MyViewModel(viewColor: .green)
let customView: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
// This is where the binder is assigned.
myViewModel.colorChanged = { [weak self] color in
print("wow the color changed")
}
customView = CustomView(viewModel: myViewModel)
self.view = customView
}
}
różnice w konfiguracji
Wspólne cechy
Zalety MVVM
Zalety MVC
Z praktycznego punktu widzenia MVC (Model-View-Controller) jest wzorem. Jednak MVC, gdy jest używany jako ASP.net MVC, w połączeniu z Entity Framework (EF) i „elektronarzędziami” jest bardzo potężnym, częściowo zautomatyzowanym podejściem do przenoszenia baz danych, tabel i kolumn na stronę internetową, zarówno w celu pełnego Tylko operacje CRUD lub R (pobieranie lub odczyt). Przynajmniej gdy korzystałem z MVVM, modele widoków współdziałały z modelami zależnymi od obiektów biznesowych, które z kolei były „ręcznie robione” i po wielu wysiłkach udało się uzyskać modele tak dobre, jak EF daje ”. -of-the-box ”. Z praktycznego punktu widzenia programowania MVC wydaje się dobrym wyborem, ponieważ daje wiele gotowych narzędzi, ale wciąż istnieje możliwość dodania dzwonków i gwizdków.
Uzupełniając wiele udzielonych odpowiedzi, chciałem dodać trochę dodatkowej perspektywy z punktu widzenia nowoczesnej strony internetowej po stronie klienta - lub z perspektywy bogatej aplikacji internetowej .
Rzeczywiście, w dzisiejszych czasach proste strony internetowe i większe aplikacje internetowe są zwykle budowane z wieloma popularnymi bibliotekami, takimi jak Bootstrap. Zbudowany przez Steve'a Sandersona Knockout zapewnia obsługę wzorca MVVM, który naśladuje jedno z najważniejszych zachowań we wzorcu: wiązanie danych za pośrednictwem modelu widoku. Przy odrobinie JavaScript można zaimplementować dane i logikę, które można następnie dodać do elementów strony za pomocą prostych data-bind
atrybutów HTML, podobnie jak przy użyciu wielu funkcji Bootstrap . Razem te dwie biblioteki same oferują interaktywne treści; a w połączeniu z routingiem takie podejście może dać proste, ale potężne podejście do budowania aplikacji jednostronicowej .
Podobnie nowoczesne frameworki po stronie klienta, takie jak Angular, zgodnie z konwencją wzorują się na wzorcu MVC, ale dodają także usługę. Co ciekawe, jest reklamowany jako Model-View-Whthing (MVW). (Zobacz ten post na temat przepełnienia stosu .)
Ponadto wraz z pojawieniem się progresywnych frameworków internetowych, takich jak Angular 2, obserwujemy zmianę terminologii i być może nowy wzorzec architektoniczny, w którym Komponenty składają się z Widoku lub Szablonu i wchodzą w interakcję z Usługą - z których wszystkie mogą być zawarte w Moduł; i seria modułów składa się na aplikację.
Kiedyś myślałem, że MVC i MVVM są takie same. Teraz, dzięki istnieniu Fluxa, mogę odróżnić:
W MVC dla każdego widoku w aplikacji masz model i kontroler, więc nazwałbym to widokiem, widokiem modelu, kontrolerem widoku. Wzór nie mówi, w jaki sposób jeden widok może komunikować się z innym. Dlatego w różnych ramach istnieją różne implementacje. Na przykład istnieją implementacje, w których kontrolery rozmawiają ze sobą, podczas gdy w innych implementacjach występuje inny komponent, który pośredniczy między nimi. Istnieją nawet implementacje, w których modele widoku komunikują się ze sobą, co jest zerwaniem ze wzorem MVC, ponieważ dostęp do modelu widoku powinien uzyskać wyłącznie kontroler widoku.
W MVVM masz również model widoku dla każdego komponentu. Wzorzec nie określa, w jaki sposób, do cholery, widok powinien wpływać na model widoku, dlatego zwykle większość ram tylko zawiera funkcje kontrolera w modelu widoku. Jednak MVVM mówi, że dane modelu widoku powinny pochodzić z modelu, który jest całym modelem, który nie jest świadomy lub niestandardowy dla konkretnego widoku.
Aby zademonstrować różnicę, weźmy wzór Flux. Wzorzec strumienia mówi, jak różne widoki w aplikacji powinny się komunikować. Każdy widok nasłuchuje w sklepie i uruchamia akcje za pomocą programu rozsyłającego. Dyspozytor z kolei informuje wszystkie sklepy o właśnie wykonanej akcji, a sklepy same się aktualizują. Magazyn w Flux odpowiada (ogólnemu) modelowi w MVVM. nie jest niestandardowe dla żadnego konkretnego widoku. Tak więc zwykle, gdy ludzie używają React i Flux, każdy komponent React faktycznie implementuje wzorzec MVVM. Kiedy występuje akcja, model widoku wywołuje dyspozytora, a na koniec jest aktualizowany zgodnie ze zmianami w sklepie, którym jest model. Nie można powiedzieć, że każdy komponent implementuje MVC, ponieważ w MVC tylko kontroler może aktualizować model widoku.
mvc jest po stronie serwera, a mvvm po stronie klienta (przeglądarki) podczas tworzenia stron internetowych.
przez większość czasu javascript jest używany do mvvm w przeglądarce. istnieje wiele technologii po stronie serwera dla mvc.
W skrócie - w MVC Controler jest świadomy widoku (kontroli), podczas gdy w MVVM ViewModel nie wie, kto go używa. ViewModel udostępnia swoje obserwowalne właściwości i działania każdemu, kto może być zainteresowany jego użyciem. Ten fakt ułatwia testowanie, ponieważ w ViewModel nie ma odniesienia do interfejsu użytkownika.
Model – Widok – Kontroler (zwykle znany jako MVC ) to wzorzec projektowy oprogramowania powszechnie stosowany do opracowywania interfejsów użytkownika, które dzielą logikę programu na trzy połączone ze sobą elementy. Odbywa się to w celu oddzielenia wewnętrznych reprezentacji informacji od sposobu, w jaki informacje są przedstawiane i akceptowane przez użytkownika. Zgodnie z wzorcem architektonicznym MVC oddziela te główne komponenty, umożliwiając ponowne użycie kodu i równoległe opracowywanie.
Tradycyjnie stosowany w graficznych interfejsach użytkownika (GUI), wzór ten stał się popularny przy projektowaniu aplikacji internetowych. Popularne języki programowania, takie jak JavaScript, Python, Ruby, PHP, Java i C # mają frameworki MVC, które są używane do tworzenia aplikacji internetowych od razu po wyjęciu z pudełka.
Model
Centralny element wzoru. Jest to dynamiczna struktura danych aplikacji, niezależna od interfejsu użytkownika. Bezpośrednio zarządza danymi, logiką i regułami aplikacji.
Widok
Wszelkie przedstawienie informacji, takich jak wykres, diagram lub tabela. Możliwych jest wiele widoków tej samej informacji, takich jak wykres słupkowy do zarządzania i widok tabelaryczny dla księgowych.
Kontroler
Akceptuje dane wejściowe i konwertuje je na polecenia modelu lub widoku.
Oprócz podziału aplikacji na te komponenty, projekt model-widok-kontroler definiuje interakcje między nimi.
Model odpowiada za zarządzanie danymi aplikacji. Odbiera dane wejściowe od kontrolera.
Widok oznacza prezentację modelu w określonym formacie.
Kontroler reaguje na dane wejściowe użytkownika i wykonuje interakcje na obiektach modelu danych. Sterownik odbiera dane wejściowe, opcjonalnie je weryfikuje, a następnie przekazuje dane wejściowe do modelu.
Model – View – ViewModel (MVVM) to wzorzec architektury oprogramowania.
MVVM ułatwia oddzielenie rozwoju graficznego interfejsu użytkownika - czy to za pomocą języka znaczników lub kodu GUI - od rozwoju logiki biznesowej lub logiki zaplecza (modelu danych). Model widoku MVVM jest konwerterem wartości, co oznacza, że model widoku jest odpowiedzialny za eksponowanie (konwersję) obiektów danych z modelu w taki sposób, aby obiekty były łatwo zarządzane i prezentowane. Pod tym względem model widoku jest bardziej modelowy niż widok i obsługuje większość, jeśli nie całą logikę wyświetlania widoku. Model widoku może implementować wzorzec mediatora, organizując dostęp do logiki zaplecza wokół zestawu przypadków użycia obsługiwanych przez widok.
MVVM jest odmianą wzorca projektowego modelu prezentacji Martina Fowlera. MVVM wyodrębnia stan i zachowanie widoku w ten sam sposób, ale Model prezentacji wyodrębnia widok (tworzy model widoku) w sposób niezależny od konkretnej platformy interfejsu użytkownika.
MVVM został wymyślony przez architektów Microsoft Kena Coopera i Teda Petersa specjalnie w celu uproszczenia programowania interfejsów użytkownika na podstawie zdarzeń. Wzorzec został włączony do Windows Presentation Foundation (WPF) (system graficzny Microsoft .NET) i Silverlight (pochodna aplikacji internetowej WPF). John Gossman, jeden z architektów Microsoft WPF i Silverlight, ogłosił MVVM na swoim blogu w 2005 roku.
Model – Widok – ViewModel jest również nazywany segregatorem modelu, szczególnie w implementacjach nieobsługujących platformy .NET. ZK (framework aplikacji WWW napisany w Javie) i KnockoutJS (biblioteka JavaScript) używają spoiwa model-view-binder.