Czy widok i model powinny się komunikować, czy nie?
33
Według strony Wikipedii dotyczącej architektury MVC widok może być powiadamiany przez model, a także ma możliwość zapytania modelu o jego bieżący stan. Jednak zgodnie z kursem Paula Hegarty'ego na iOS 5 w Stanford, wykład 1, strona 18 cała interakcja musi przejść przez kontroler, a Model i Widok nigdy się nie znają. Nie jest dla mnie jasne, czy wypowiedź Hegarty'ego ma być uproszczeniem kursu, ale kusi mnie, aby powiedzieć, że zamierza on sam projektować.
Jak wytłumaczysz te dwa przeciwne punkty widzenia?
Jest to kontrowersyjny temat w MVC / MVVM. Niektórzy twierdzą, że widok może mieć bezpośredni dostęp do modeli, inni twierdzą, że należy owinąć modele w ViewModels, aby oddzielić je od widoku. Osobiście nie jestem fanem żadnego z tych podejść.
Jednym z głównych celów MVC / MVVM jest oddzielenie interfejsu użytkownika, logiki biznesowej i danych. Mając to na uwadze, umożliwienie widoku bezpośredniego dostępu do modeli stwarza zależność, której możesz nie chcieć mieć. Z drugiej strony, zawijanie modeli w ViewModels jest często uciążliwe i mało przydatne, ponieważ ViewModels mają tendencję do po prostu przechodzenia do modeli.
Podoba mi się podejście polegające na tym, że Twoje Modele implementują określony interfejs, nazwijmy go IModel. Twoja klasa ViewModel może następnie oferować instancje obiektów, które implementują IModel do konsumpcji View. Widok po prostu wie, że działa z obiektami IModel, które otrzymuje z ViewModel. To usuwa zewnętrzny kod opakowania ViewModel, a także ukrywa konkretną implementację IModel w widoku. Później możesz zamienić jedną implementację IModel na inną bez wpływu na widok.
W odniesieniu do żmudnych aspektów mapowania modelu na model widoku należy zauważyć, że dostępne są narzędzia, które mogą złagodzić ból związany z mapowaniem. EG: (.NET AutoMapper) (JAVA modelmapper)
Jesse
+1 Świetna odpowiedź! Jest to świetne podejście w zależności od złożoności modelu, ale większość współczesnych modeli jest typu anemicznego . Elementy modelu, będąc niewiele więcej niż obiektami danych bez zachowania, nie widzę potrzeby takiej abstrakcji ani niebezpieczeństwa, pozwalając Twojemu Widokowi na bezpośredni dostęp do Twojego Modelu.
wałek klonowy
2
Słyszę, co mówisz; większość interfejsów IModel zawierałaby po prostu kilka deklaracji właściwości i kilka (jeśli w ogóle) deklaracji metod. Ale nawet jeśli Modele są anemiczne, interfejs nadal oddziela Widok od ich konkretnej implementacji. Ta separacja może nie być konieczna dla każdego projektu, ale zawsze dobrym pomysłem jest pozostawienie otwartych opcji.
Raymond Saltrelli
1
Jestem zdezorientowany, jeśli masz kilka zupełnie odmiennych poglądów, jak możesz polegać na interfejsie bez zaśmiecania go? Myślę, że widok modeli jest fantastyczny. Tworzysz modele, które są na tyle ogólne, że można z nich korzystać w całej aplikacji, i tworzysz modele widoków, aby zużywać jeden lub więcej modeli i dodatkowo implementować operacje, które byłyby używane tylko przez ten widok.
The Muffin Man
12
W sieci wszyscy nazywają swoje odsprzęganie MVC.
Niektóre technologie, takie jak C #, używają MVVM, ponieważ nie ma połączenia między Widokiem a innymi, wszystko przechodzi przez lokalizator usług, wiążąc zmienne.
W przypadku czystego MVC widok rozmawia bezpośrednio z modelem i odwrotnie. Kontroler jest dostępny tylko wtedy, gdy pojawi się jakakolwiek zmiana.
A potem jest ten o nazwie PAC (Presentation Abstraction Control). W tej architekturze widok i model nie rozmawiają ze sobą. Kontroler jest jedynym, który może robić cokolwiek z Widokiem lub Modelem. Ludzie często mylą to z MVC.
Dla mnie podstawowym celem architektury jest to, aby nie utrudniała przyszłych prób refaktoryzacji. Zazwyczaj widoki wchodzące w interakcję bezpośrednio z modelami jives z tym wymogiem i jest stosunkowo jasne, gdy nie spełnia.
Kiedy widok staje się zbyt intymny z modelem, ViewModel może być piękną rzeczą, ale zwykle zdarza się, że przypadki, w których jest on wywoływany, są w mniejszości.
W MVC Paul Hegarty się myli. Kontroler dotyczy zdarzeń użytkownika, a nie komunikacji między modelami. W klasycznym MVC widok (y) obserwują model (wzorzec obserwatora).
Z facetem pomiędzy mediacją wzór należy nazwać MVP , a właściwie większość tego, co obecnie przedstawia się jako MVC, jest w rzeczywistości bliższa MVP.
Potem jest MVVM, który jest podobny do obu, a jednak nieco inny, i istniał dawno temu ... najlepiej widzieć to jako dwa MVC / MVP połączone razem przez obiekt viewmodel - „klient” MVC ma viewmodel jako jego model, a „serwerowy” MVC ma viewmodel jako widok.
Dzisiaj (na początku 2014 r.), Dla mnie (z moim węzłem i stosem kątowym) to rozróżnienie na MVC „klienta” i MVC „serwera” wydaje się bardzo istotne i jakoś pouczające. (dziękuję)
slacktracer
4
Ponieważ pytasz o materiał w szczególności podczas tych wykładów Stanforda, warto rozważyć dwie rzeczy na temat stanowiska Hegarty'ego:
Jak już wspomniałeś, wykłada kurs Sci Komputerowego na 100 poziomie. W jego wykładach jest wiele miejsc, w których upraszcza, rozmyśla o szczegółach lub mówi „po prostu zrób to w ten sposób”, jak zapewne trzeba, ucząc podstaw, tzn. Musisz opanować reguły, zanim je złamiesz.
Moje doświadczenie z iOS SDK polega na tym, że tam, gdzie nie wymusza ścisłej separacji między Widokiem a Modelem, jest mocno ukierunkowane na ten wzorzec. Zwłaszcza przy pisaniu aplikacji na iOS przestrzeganie separacji widoków modelu pomaga pisać kod zgodny z oczekiwaniami frameworka. Wahałbym się uogólnić stwierdzenia Hegarty'ego na rozwój na innych platformach lub ogólnie.
Zgadzam się z Paulem Hegarty i uważam, że Widok nie może wiedzieć o Modelu. Nie jest to trudne do osiągnięcia, ale zapewnia dodatkowe korzyści dla twojego projektu i przyszłej elastyczności.
W małych aplikacjach (zazwyczaj stacjonarnych), w których chciałbym uniknąć „fałszywych” klas ViewModel i uprościć sprawę, używam również interfejsu IModel (patrz odpowiedź powyżej) i dbam o to, aby Model nie miał pojęcia o widoku (korzystał z subskrybentów jak w klasycznym MVC).
Również w tym przypadku kontroler okazuje się być dość sprzężony z widokiem i dla uproszczenia nie zawsze wyraźnie je rozdzielam.
Drugie „uproszczone” podejście jest OK, jeśli możesz mieć kilka widoków dla tego samego modelu, ale nie poleciłbym tego, jeśli chcesz użyć tego samego widoku dla różnych modeli. W ramach różnych mam na myśli naprawdę różne z natury, a nie tylko klasy testowe JUnit, które „podążają” za głównym modelem.
Wierzę, że nie ma na to twardej i szybkiej reguły, zależy to całkowicie od twoich potrzeb.
Znajdziesz ludzi o różnych przekonaniach. Architektury to koncepcje pomagające projektować lepsze rozwiązania.
Oprócz komunikacji w widoku modelu istnieje jeszcze jedna sprzeczność w logice biznesowej w MVC. Wiele osób uważa, że cała logika biznesowa powinna być jednym modelem (patrz to pytanie SO ), z drugiej strony link udostępniony przez Floriana (w jego odpowiedzi) mówi, że logika biznesowa powinna być kontrolerem.
Oprócz tego istnieje możliwość podzielenia logiki biznesowej na logikę aplikacji (umieść ją na kontrolerze) i login domeny (włóż ją do modelu).
Morał tej historii jest taki, że MVC oznacza, że model, widok i kontroler powinny być oddzielne. Poza tym, cokolwiek najbardziej ci odpowiada.
Jestem z obozem, który mówi, że widok nigdy nie powinien komunikować się z modelem. Kontroler zawsze musi być głównym pomocnikiem we wszystkim, a następnie decyduje, co zrobić (sprawdzić poprawność, poprosić o dane z modelu itp.).
Uważam to raczej za kwestię organizacyjną niż cokolwiek innego.
Jak wielu sugeruje, dlaczego i jak widok i model powinny swobodnie współdziałać w różnych kontekstach, ale głównym powodem, dla którego iOS tworzy Kontroler jest pośrednikiem między nimi, jest unikanie zależności Model i Widok w bazie kodu i umożliwienie nam ponownego użycia model lub widok zgodnie z wymaganiami wraz z ewolucją systemu iOS.
Ponieważ być może będziemy musieli przechowywać aktualizacje naszych aplikacji w interfejsie użytkownika / UX lub modelu, lub czasami w obu, nie powinno to generować kodu zależności trybu między modelem a widokiem. Jeśli chcesz zmienić warstwę prezentacji aplikacji, po prostu przejdź zmień go, możesz nadal używać tego samego modelu i odwrotnie.
Chociaż zgadzam się, że MVC w iOS produkuje gigantyczne ViewControllery z wieloma różnymi logikami i obsługującymi wszelkiego rodzaju rzeczy inne niż te, do których są przeznaczone, więc lepiej jest używać MVVM lub elementów sterujących prezentacji, aby uczynić bazę kodu bardziej elastyczną, łatwą do odczytu i konserwacji za pomocą mniejszych ViewControllerów.
Może to pomóc tym, którzy szukają mniejszych ViewControllerów w iOS:
W sieci wszyscy nazywają swoje odsprzęganie MVC.
Niektóre technologie, takie jak C #, używają MVVM, ponieważ nie ma połączenia między Widokiem a innymi, wszystko przechodzi przez lokalizator usług, wiążąc zmienne.
W przypadku czystego MVC widok rozmawia bezpośrednio z modelem i odwrotnie. Kontroler jest dostępny tylko wtedy, gdy pojawi się jakakolwiek zmiana.
A potem jest ten o nazwie PAC (Presentation Abstraction Control). W tej architekturze widok i model nie rozmawiają ze sobą. Kontroler jest jedynym, który może robić cokolwiek z Widokiem lub Modelem. Ludzie często mylą to z MVC.
Zobaczysz o wiele lepsze wyjaśnienie tutaj: http://www.garfieldtech.com/blog/mvc-vs-pac
źródło
Dla mnie podstawowym celem architektury jest to, aby nie utrudniała przyszłych prób refaktoryzacji. Zazwyczaj widoki wchodzące w interakcję bezpośrednio z modelami jives z tym wymogiem i jest stosunkowo jasne, gdy nie spełnia.
Kiedy widok staje się zbyt intymny z modelem, ViewModel może być piękną rzeczą, ale zwykle zdarza się, że przypadki, w których jest on wywoływany, są w mniejszości.
źródło
W MVC Paul Hegarty się myli. Kontroler dotyczy zdarzeń użytkownika, a nie komunikacji między modelami. W klasycznym MVC widok (y) obserwują model (wzorzec obserwatora).
Z facetem pomiędzy mediacją wzór należy nazwać MVP , a właściwie większość tego, co obecnie przedstawia się jako MVC, jest w rzeczywistości bliższa MVP.
Potem jest MVVM, który jest podobny do obu, a jednak nieco inny, i istniał dawno temu ... najlepiej widzieć to jako dwa MVC / MVP połączone razem przez obiekt viewmodel - „klient” MVC ma viewmodel jako jego model, a „serwerowy” MVC ma viewmodel jako widok.
źródło
Ponieważ pytasz o materiał w szczególności podczas tych wykładów Stanforda, warto rozważyć dwie rzeczy na temat stanowiska Hegarty'ego:
źródło
Zgadzam się z Paulem Hegarty i uważam, że Widok nie może wiedzieć o Modelu. Nie jest to trudne do osiągnięcia, ale zapewnia dodatkowe korzyści dla twojego projektu i przyszłej elastyczności.
W małych aplikacjach (zazwyczaj stacjonarnych), w których chciałbym uniknąć „fałszywych” klas ViewModel i uprościć sprawę, używam również interfejsu IModel (patrz odpowiedź powyżej) i dbam o to, aby Model nie miał pojęcia o widoku (korzystał z subskrybentów jak w klasycznym MVC).
Również w tym przypadku kontroler okazuje się być dość sprzężony z widokiem i dla uproszczenia nie zawsze wyraźnie je rozdzielam.
Drugie „uproszczone” podejście jest OK, jeśli możesz mieć kilka widoków dla tego samego modelu, ale nie poleciłbym tego, jeśli chcesz użyć tego samego widoku dla różnych modeli. W ramach różnych mam na myśli naprawdę różne z natury, a nie tylko klasy testowe JUnit, które „podążają” za głównym modelem.
źródło
Wierzę, że nie ma na to twardej i szybkiej reguły, zależy to całkowicie od twoich potrzeb.
Znajdziesz ludzi o różnych przekonaniach. Architektury to koncepcje pomagające projektować lepsze rozwiązania.
Oprócz komunikacji w widoku modelu istnieje jeszcze jedna sprzeczność w logice biznesowej w MVC. Wiele osób uważa, że cała logika biznesowa powinna być jednym modelem (patrz to pytanie SO ), z drugiej strony link udostępniony przez Floriana (w jego odpowiedzi) mówi, że logika biznesowa powinna być kontrolerem.
Oprócz tego istnieje możliwość podzielenia logiki biznesowej na logikę aplikacji (umieść ją na kontrolerze) i login domeny (włóż ją do modelu).
Morał tej historii jest taki, że MVC oznacza, że model, widok i kontroler powinny być oddzielne. Poza tym, cokolwiek najbardziej ci odpowiada.
źródło
Używam DTO do komunikacji w widoku modelu.
Na przykład:
źródło
Jestem z obozem, który mówi, że widok nigdy nie powinien komunikować się z modelem. Kontroler zawsze musi być głównym pomocnikiem we wszystkim, a następnie decyduje, co zrobić (sprawdzić poprawność, poprosić o dane z modelu itp.).
Uważam to raczej za kwestię organizacyjną niż cokolwiek innego.
źródło
Jak wielu sugeruje, dlaczego i jak widok i model powinny swobodnie współdziałać w różnych kontekstach, ale głównym powodem, dla którego iOS tworzy Kontroler jest pośrednikiem między nimi, jest unikanie zależności Model i Widok w bazie kodu i umożliwienie nam ponownego użycia model lub widok zgodnie z wymaganiami wraz z ewolucją systemu iOS.
Ponieważ być może będziemy musieli przechowywać aktualizacje naszych aplikacji w interfejsie użytkownika / UX lub modelu, lub czasami w obu, nie powinno to generować kodu zależności trybu między modelem a widokiem. Jeśli chcesz zmienić warstwę prezentacji aplikacji, po prostu przejdź zmień go, możesz nadal używać tego samego modelu i odwrotnie.
Chociaż zgadzam się, że MVC w iOS produkuje gigantyczne ViewControllery z wieloma różnymi logikami i obsługującymi wszelkiego rodzaju rzeczy inne niż te, do których są przeznaczone, więc lepiej jest używać MVVM lub elementów sterujących prezentacji, aby uczynić bazę kodu bardziej elastyczną, łatwą do odczytu i konserwacji za pomocą mniejszych ViewControllerów.
Może to pomóc tym, którzy szukają mniejszych ViewControllerów w iOS:
http://blog.xebia.com/simplification-of-ios-view-controllers-mvvm-or-presentation-controls/
źródło