Czy kontroler powinien wiedzieć o widoku i modelu? lub odwrotnie?

13

Próbuję zrozumieć, czy powinienem to zrobić:

item = Model()
screen = View()
brain = Controller(item, screen)

albo to..

brain = Controller()
item = Model(brain)
screen = View(brain)

albo to..

class Controller():
    def __init__(self):
        item = Model(self)
        screen = View(self)

czy coś zupełnie innego?

alnafie
źródło

Odpowiedzi:

18

Dla mnie pierwsza opcja ma sens. Zadaniem kontrolera jest koordynacja widoku i modelu. Z tego punktu widzenia sensowne jest, aby kontroler kontrolował odwołania do widoku i modelu.

Tak naprawdę nie możesz mieć kontrolera bez Modelu i Widoku, jednak o wiele bardziej sensowne jest posiadanie Widoku lub modelu (na przykład w testach jednostkowych). Dlatego chcesz przekazać te zależności do kontrolera, a nie do pozostałych dwóch.

Oleksi
źródło
9

ModelI Viewsą niezależne od siebie.

Nie myśleć o Controllerjak mózgi struktury MVC. Pomyśl o tym jako o dyspozytorze, który obsługuje żądania z przeglądarki i wysyła je do Model. Następnie pobiera dane z Modeli pakuje je w sposób przyjazny dla szablonu , a następnie wysyła do View.

Jest Modelto mózg w strukturze MVC i tutaj powinieneś umieścić swoje reguły biznesowe. Reguły biznesowe są wspólne dla wielu kontrolerów . Tak więc kontroler dokumentów i kontroler raportów mogą używać modelu użytkownika, aby zobaczyć, kto ma dostęp do tych rzeczy. Nie chcesz powtarzać tych zasad w obu kontrolerach.

ViewNależy użyć szablonu HTML do prezentacji danych w określony sposób bez źródła danych. Nie powinien być ściśle związany ze schematem bazy danych. Aby wyświetlić tytuł dokumentu, widok powinien wyświetlać zawartość zmiennej szablonu o nazwie document_title, i tylko Controllerwiedza o tym, jak ta zmienna została ustawiona, i tylko Modelwiedza o tym, dlaczego ten dokument ma ten tytuł.

Reactgular
źródło
1
Podoba mi się twoja odpowiedź, ponieważ żeluje z moim ogólnym zrozumieniem MVC. Jednak nie odnosi się do ważnej części pytania, a konkretnie, które części triady zawierają odniesienia do innych? Moim zdaniem zamieszanie wynika z faktu, że to, co opisujesz, polega na tym, że widoki to „głupie szablony z dziurami” (tzn. Nie zawierają odniesienia do kontrolera, ale kontroler zna widoki i podłącza do nich dane z modelu). Jednocześnie kolejną powszechną rzeczą, którą widzę, jest to, że Widoki powinny wysyłać działania użytkownika do Kontrolera. Jak Widoki mogą to zrobić bez odniesienia do C?
alnafie
@alnafie Nadmiernie uprościłeś framework MVC na zaledwie 3 klasy. Rozejrzyj się po istniejących frameworkach open source MVC, a przekonasz się, że jest o wiele więcej do działania. Musi być coś wyższego, co zarządza wszystkimi elementami frameworka. Coś, co wywołuje Kontrolery, i coś, co obsługuje routing do akcji w Widokach.
Reactgular
3

MVC zostało pierwotnie zdefiniowane w celu ułatwienia programowania aplikacji komputerowych. Widok zasubskrybował zdarzenia modelu, aktualizując prezentację po zmianie modelu. Sterownik po prostu przetłumaczył zdarzenia interfejsu użytkownika (np. Naciśnięcie przycisku) na wywołania do modelu. Kontroler i widok zależały od modelu, ale były od siebie niezależne. Model był niezależny od obu. To pozwoliło wielu widokom i kontrolerom pracować na tym samym modelu.

Architektura „MVC” stosowana w aplikacjach web 1.0 (pełne odświeżanie strony, brak AJAX) jest nieco inna. Żądanie sieciowe jest wysyłane do kontrolera. Kontroler w jakiś sposób modyfikuje stan modelu, a następnie wysyła jeden lub więcej modeli do renderowania przez widok. Kontroler i widok zależą od modelu, ale kontroler zależy również od widoku.

Dzięki aplikacjom web 2.0 powracamy do klasycznej architektury MVC po stronie klienta . Model, widok i kontroler znajdują się po stronie klienta jako obiekty Javascript. Kontroler tłumaczy zdarzenia użytkownika na działania modelu. Działania modelowe mogą, ale nie muszą, powodować żądanie AJAX do serwera. Ponownie widok subskrybuje zdarzenia modelowe i odpowiednio aktualizuje prezentację.

Kevin Cline
źródło
+1 dobra odpowiedź. Rozumiem wywołania zwrotne modelu dla aplikacji komputerowych w klasycznym sensie. Przypomina mi stare MFC firmy Microsoft.
Reactgular
2

Widok powinien zasubskrybować zmiany w modelu. Bogactwo subskrypcji jest szerokie, ponieważ mogą być szczegółowe (pokaż mi zmiany w ekwipunku dla tego konkretnego przedmiotu) lub ogólne (model się zmienił); widok może wysłać zapytanie do modelu w odpowiedzi na powiadomienie o zmianie. Widok przedstawia pożądany zestaw elementów modelu na ekranie, aktualizując ekran jak podczas obsługi powiadomień o zmianie.

Kontroler powinien wprowadzać zmiany w modelu w wyniku wskazówek użytkownika (np. Wprowadzanie klawiatury, mysz i polecenia menu).

Model utrzymuje model i listę subskrypcji i powinien powiadamiać widoki o odpowiednich zmianach za pośrednictwem ich subskrypcji.

Musi także istnieć mechanizm tworzenia nowych widoków i kontrolerów (ponieważ w MVC powinieneś mieć dwa lub więcej widoków tego samego modelu (mogą to być te same widoki (punkty) lub różne widoki (punkty). Logicznie możemy uznać, że kontroler musi wykonać lub mieć dostęp do fabryki widoku i kontrolera (pary), która może być częścią kontrolera lub innego komponentu.

Erik Eidt
źródło
-1 Modelsnie powiadamiaj Views. Controllersodpytuj Modelo zmiany, a następnie renderuj, Viewsaby przedstawić te zmiany.
Reactgular
4
@MathewFoscarini w MVC, widok subskrybuje zmiany z modelu. Zobacz na przykład wiki.squeak.org/squeak/598 .
Myślę, że nie mówimy o różnicach w istniejących ramach MVC. Zend MVC, C # .NET i CakePHP nie łączą modelu z widokiem. Widok w tych ramach jest niezależny. Nie wiem z jakim MVC pracowałeś, ale nazwałbym to nietradycyjnym.
Reactgular
6
@MathewFoscarini: są to wszystkie frameworki internetowe i chociaż nazywają się „MVC”, nie przestrzegają klasycznej architektury MVC.
kevin cline
2
Nie jestem pewien, czy którykolwiek MVC jest bardziej „tradycyjny” niż Smalltalk MVC, ponieważ jest to pierwszy, w którym opisano ten wzór.
1

MVC przypomina bardziej modułowość. Jego celem jest to, że ilekroć chcesz zmienić układ interfejsu użytkownika (widok), nie musisz zmieniać logiki aplikacji (kontrolera) ani wewnętrznego przetwarzania danych (modelu).

Aby to osiągnąć, wzorzec polega na wyodrębnieniu logiki implementacji każdego komponentu MVC. Mimo to, jest to całkowicie normalne, że nie wiedzą nawzajem elementy interfejsów .

Często widziałem, że kontroler tworzy lub wywołuje model i widok (dzięki czemu zna ich interfejs), a model lub widok może w zamian powiadomić kontrolera (bardziej jak wzorzec oddzwaniania lub wzorzec obserwatora). Ważną częścią jest to, że kontroler nie zna struktury układu.

Marc-Emmanuel Coupvent des Gra
źródło