Jak bardzo w architekturze MVC model i widok są ściśle powiązane z kontrolerem?


16

Mam aplikację, która korzysta z MVC, ale trochę się zastanawiam, jak powinien wyglądać kontroler. Na przykład widok wyświetla jednocześnie tylko niektóre podzbiory danych modelu. Nie jestem jednak pewien, jak dokładnie to powinno być zorganizowane. Czy normalne jest na przykład widok lub model bezpośredniego wywoływania funkcji na kontrolerze? Przez jakiś interfejs? A może są całkowicie zamknięte i nigdy nie wiedzą o Administratorze ani o sobie nawzajem?

Podobnie jak edycja; jest to niestandardowa aplikacja, która nie została napisana w żadnym frameworku internetowym, więc nie szukam tutaj szczegółów specyficznych dla frameworka i mam swobodę wyboru.


1
Nie odpowiem, ponieważ moje doświadczenie jest ograniczone w architekturach MVC, ale z tego, co słyszałem i rozmawiałem z innymi, M&V są ściśle ze sobą powiązane, ale nie C. C. M na ogół wywołuje funkcje na C i V często tylko powiązania danych z jakimś podzbiorem M.
Steven Evers

8
@SnOrfus: To jest dokładnie odwrotne do tego, co myślałem - M & V są sprzężone z C, ale nie ze sobą.
DeadMG

1
Jak wiele odpowiedzi może być tak błędnych. Tutaj przeczytaj wersję MS msdn.microsoft.com/en-us/library/ff649643.aspx
Reactgular

Odpowiedzi:


15

Kontroler kontroluje przepływ aktywności. Użytkownik wykonuje tę akcję, kontroler przekazuje dane widoku do domeny, która robi wszystko, co musi wtedy zrobić, w oparciu o odpowiedź (odpowiedzi), kontroler informuje strukturę, którą widok ma wyświetlić w następnej kolejności (i daje mu wystarczającą ilość danych do zrobienia więc).

Kontroler musi być zatem w pewnym stopniu sprzężony z modelem domeny. to znaczy. Możesz umieścić warstwę usługi pomiędzy, ale, ściśle według definicji, staje się ona częścią domeny.

Jest również sprzężony z danymi widoku, ale nie z samym widokiem. to znaczy. mówi po prostu „pokaż widok klienta przy użyciu tego szczegółu klienta”. Ramy następnie decydują, gdzie powinien znaleźć ten widok.

Teraz powinno to pozwolić na oddzielenie modelu domeny od widoku przy użyciu modelu widoku tych samych danych. Niektórzy programiści to robią, inni nie, i myślę, że to w dużej mierze kwestia osobistych preferencji.

W Railsach bardzo zachęcamy do wypychania obiektów domeny (ActiveRecord) do widoku i ufasz, że widok nie korzysta z tego dostępu (np. Nie powinieneś wywoływać klienta.save z widoku, mimo że będą dostępne).

W świecie .NET mamy tendencję do zmniejszania ryzyka, nie dopuszczając rzeczy, które nie powinny się zdarzyć, i być może z tego powodu wydaje mi się, że model widoku odłączonego jest bardziej popularny.


1
Zobacz model jest bardzo powszechną praktyką, jeśli chodzi o testy jednostkowe. Zwykle można automatycznie mapować model domeny lub obiekt DTO na model widoku. Następnie użyjesz modelu widoku w widoku. Wyświetl model można łatwo przetestować i nie jest on powiązany z warstwą poniżej.
CodeART

7

Uwaga: Robert C. Martin (znany również jako wujek Bob) wyjaśnia to w znacznie lepszy i humorystyczny sposób w swoim przemówieniu Architektura utracone lata . Trochę długo, ale uczy wielu dobrych koncepcji.

tl; dr: Nie myśl i nie planuj swojej aplikacji pod kątem MVC. Struktura MVC to tylko szczegół implementacji.

Najbardziej mylące w MVC jest to, że programiści próbują użyć wszystkich sklejonych ze sobą komponentów.

Spróbuj myśleć w kategoriach programu, a nie ram.

Twój program ma cel. Pobiera niektóre dane, robi rzeczy z danymi i zwraca niektóre dane.

W ten sposób controllerjest mechanizm dostarczania twojego programu.

  1. Użytkownik wysyła żądanie do Twojego programu (powiedzmy, dodaj produkt do koszyka).
  2. Kontroler przyjmuje to żądanie (informacje o produkcie i dane użytkownika), wywołuje niezbędną część programu, która obsłuży to żądanie $user->addToCart($product)
  3. Twój program ( w tym przypadku addToCartfunkcja userobiektu) wykonuje pracę, do której jest przeznaczony, i zwraca odpowiedź (powiedzmy success)
  4. Kontroler przygotowuje odpowiedź za pomocą odpowiedniego view: np. w obiekcie kontrolera$this->render($cartView('success')

W ten sposób kontrolery są oddzielone od programu i wykorzystywane jako mechanizm dostarczania. Nie wiedzą, jak działa twój program, po prostu wiedzą, która część programu musi zostać wywołana dla żądań.

Jeśli chcesz użyć innej struktury, Twoja aplikacja nie będzie wymagać zmiany, wystarczy napisać odpowiednie kontrolery, aby zadzwonić do programu w celu uzyskania żądań.

Lub jeśli chcesz utworzyć wersję komputerową, Twoja aplikacja pozostanie taka sama, wystarczy przygotować mechanizm dostarczania.

A Model. Pomyśl o tym jako o mechanizmie trwałości.

W sposób OO w twoim programie znajdują się obiekty przechowujące dane.

class User {
    //...
    private $id;
    private $shoppingCart;
    //...
}

class Product {
    //...
    private $id;
    //...
}

Po dodaniu produktu do koszyka, można dodać The product::iddo user::shoppingCart.

A jeśli chcesz zachować dane, możesz użyć modelczęści frameworka, która zazwyczaj polega na użyciu ORM, do odwzorowania klas na tabele bazy danych.

Jeśli chcesz zmienić ORM, którego używasz, twój program pozostanie taki sam, zmienią się tylko informacje mapowania. Lub jeśli chcesz uniknąć jednoczesnego korzystania z baz danych, możesz po prostu zapisać dane do zwykłych plików tekstowych, a aplikacja pozostanie taka sama.


Najpierw napisz swój program. Jeśli programujesz w sposób „OO”, używaj zwykłych starych obiektów języka. Na początku nie myśl w kategoriach MVC.


Świetne wideo. Dzięki. Nie zgadzam się jednak z twoją interpretacją tego. MVC nie jest szczegółem w znaczeniu, które ma wujek Bob. Zauważysz, że MVC jest wzorem architektonicznym bardzo podobnym do wzorca, który tworzy „Interactor / Entity / Boundary”. Z drugiej strony, każdy konkretny system MVC, taki jak Spring czy cokolwiek innego, jest rzeczywiście czymś, co zaleca odroczyć. Jak wyjaśnia, te frameworki nazywane „MVC” są swego rodzaju draństwem tego terminu.
Edward Strange

Tak, napisałem to w sposób, w jaki ludzie myślą, co to MVCjest. Dlatego napisałem MVC Framework.
Hakan Deryal

2

Martin Fowler dobrze opisuje paradygmat MVC. Oto link do jego artykułu na http://martinfowler.com/eaaDev/uiArchs.html

Zwróć uwagę na jego cytat na temat oddzielnej prezentacji „Ideą oddzielnej prezentacji jest dokonanie wyraźnego podziału między obiektami domeny, które modelują nasze postrzeganie świata rzeczywistego, a obiektami prezentacji, które są elementami GUI, które widzimy na ekranie”.


1

Oto prosty przykład wykorzystania MVC w typowej aplikacji Java Swing ...

Załóżmy, że masz panel zawierający przycisk i pole tekstowe. Po naciśnięciu przycisku uruchamiane jest zdarzenie, które prowadzi do pewnej zmiany stanu w aplikacji. Po zarejestrowaniu zmiany stanu TextField wyłącza się.

Byłoby to typowe podejście przyjęte przez prostą aplikację MVC ...

Kontroler rejestruje się jako odbiornik zdarzeń Widoku. Po kliknięciu przycisku sam widok nie obsługuje zdarzenia; kontroler robi. Kontroler jest specyficzny dla Swinga, ponieważ musi obsługiwać zdarzenia związane z Swingiem.

Kontroler otrzymuje to powiadomienie i musi zdecydować, kto musi je obsłużyć (widok lub model). Ponieważ to zdarzenie zmieni stan aplikacji, postanawia przekazać informacje do Modelu odpowiedzialnego za dane i logikę programu. Niektórzy popełniają błąd, umieszczając logikę programu w kontrolerze, ale w OOP modele reprezentują zarówno dane ORAZ zachowanie. Przeczytaj Martin Fowler o swoim ujęciu.

Wiadomość jest odbierana przez model we właściwym kontekście. Oznacza to, że jest całkowicie pozbawione jakichkolwiek odniesień do Swing lub jakichkolwiek innych odniesień specyficznych dla GUI. Ten komunikat dotyczy Modelu i TYLKO modelu. Jeśli importujesz instrukcje javax.swing do modelu, oznacza to, że nie kodujesz poprawnie modelu.

Model następnie ustawia stan na „wyłączony” i przechodzi do powiadamiania wszystkich zainteresowanych stron o zmianie tego modelu. Widok, zainteresowany tym wydarzeniem, zarejestrował się już jako obserwator zmian modelu. Po odebraniu zdarzenia zmiany stanu Model przez widok przechodzi do wyłączenia pola tekstowego. Widok może również pobierać informacje tylko do odczytu bezpośrednio ze swojego modelu bez konieczności przechodzenia przez kontroler (zwykle przez określony interfejs udostępniony przez model dla takiej aktywności).

Promując takie luźne połączenie między prezentacją a logiką biznesową i warstwami danych, zauważysz, że Twój kod jest znacznie łatwiejszy w utrzymaniu. Wraz ze wzrostem liczby systemów rośnie również Twoje podejście do MVC. Na przykład Hierarchical MVC jest rozszerzeniem często używanym do łączenia triad MVC ze sobą w celu utworzenia dużych systemów w całym przedsiębiorstwie bez łączenia ze sobą podsystemów


0

Łączenie (rodzaj, którego chcesz uniknąć) obejmuje wzajemną zależność między dwiema klasami. Oznacza to, że Foo zależy od paska, a pasek zależy od Foo, więc nie można tak naprawdę zmodyfikować jednego bez modyfikacji drugiego. To zła rzecz.

Jednak tak naprawdę nie można uniknąć NIEKTÓRYCH zależności. Klasy muszą się trochę o sobie dowiedzieć, inaczej nigdy by się nie komunikowały.

We wzorcu MVC kontroler kontroluje komunikację między modelem domeny a widokiem prezentacji. Jako taki, kontroler musi wiedzieć wystarczająco dużo o modelu, aby poprosić go o zrobienie tego, co powinien zrobić. Kontroler musi także wiedzieć wystarczająco dużo o widoku, aby móc go przedstawić klientowi lub użytkownikom. Tak więc model Kontroler ma współzależności na obu. Jednak widok może istnieć doskonale bez kontrolera - nie ma tam zależności. Podobnie model nie ma żadnych zależności od kontrolera - jest po prostu tym, czym jest. Wreszcie model i widok są całkowicie od siebie oddzielone.

Zasadniczo kontrolerem jest poziom pośredni, który oddziela widok od modelu, aby nie musieli się o sobie znać.


Ach - dlatego głosy przegłosowane - źle napisałem. Miałem na myśli, że Kontroler ma zależności od obu. Nie!
Matthew Flynn

-5

Z mojego doświadczenia wynika, ogólnie model zależy tylko na widoku, a nie specyficzny, często jako obserwator ... jeśli ma takiego sprzęgła w ogóle.

Widok ogólnie łączy się z tym, na co patrzy, co ma sens. Trudno wymyślić widok, który można oddzielić od tego, co ogląda ... ale czasami możesz mieć częściowe sprzężenie lub coś takiego.

Kontroler często łączy się z jednym i drugim. Ma to również sens, ponieważ zadaniem jest przekształcenie widoku zdarzeń w zmiany modelu.

Oczywiście to tylko tendencja, którą zaobserwowałem i tak naprawdę nie mówi nic o żadnym konkretnym przykładzie.

Aby zrozumieć, czym jest MVC i jaka jest tendencja do łączenia, powinieneś przyjrzeć się, jak powstała MVC. Środowisko, w którym utworzono MVC, było takie, w którym „widżety” jako elementy formularza, z którymi można budować okna dialogowe, nie istniały. „Widok” był pudełkiem i rysował różne rzeczy. Widok tekstu to pole, które rysuje tekst. Widok listy był polem, które rysowało listę. „Kontroler” odebrał wszystkie zdarzenia myszy i klawiatury z systemu interfejsu użytkownika, które miały miejsce w tym widoku; nie było zdarzeń „textChanged” lub „selectionChanged”. Sterownik przejmie wszystkie zdarzenia niskiego poziomu i wygeneruje interakcję z modelem. Po zmianie model powiadamia o swoich poglądach; od tego czasu zaczęliśmy postrzegać ten związek jako „obserwatora” i to „

TO jest esencja wzoru MVC. Ponieważ tego rodzaju programowanie interfejsu użytkownika na niskim poziomie zasadniczo nie jest już wykonywane, MVC ewoluowało w wielu różnych kierunkach. Niektóre rzeczy, które noszą dziś tę nazwę, prawie wcale nie przypominają MVC i naprawdę należy je nazwać czymś innym. Nadal można go jednak używać w sensie dialogu jako całości wchodzącego w interakcję z większym obiektem. Istnieje jednak wiele lepszych alternatyw.

Zasadniczo wszystko, co MVC miało rozwiązać, dzieje się teraz w widżetach i jest to coś, z czego nie musimy już korzystać.


Dla tych, którzy myślą, że wiedzą lepiej:

http://www.codeproject.com/Articles/42830/Model-View-Controller-Model-View-Presenter-and-Mod

http://msdn.microsoft.com/en-us/library/ff649643.aspx

Jestem pewien, że jest ich więcej, ale to tylko początek listy w Google. Jak widać, model bardzo zależy od interfejsu widoku w WIELU implementacjach. Zasadniczo model jest obserwowalny, a widok jest obserwatorem.

Ale dlaczego fakty przeszkadzają ...

Artykuł już opublikowany w innej odpowiedzi obsługuje również moje stwierdzenia:

http://martinfowler.com/eaaDev/uiArchs.html

Jeśli ludzie chcą nadal mówić, że KAŻDY w branży projektowania jest w błędzie, to nie ma problemu.


4
To jest po prostu źle. Model nigdy nie może zależeć od widoku! Nawet jeśli ten widok jest abstrakcyjny lub interfejs. Model powinien być całkowicie oddzielony od prezentacji!
Falcon

3
Odpowiedź jest zła. Model nie zależy od widoku ani kontrolera.
CodeART

2
@Crazy Eddie Powiedziałeś: „Z mojego doświadczenia wynika, że ​​ogólnie model zależy tylko od widoku, a nie konkretnego, często jako obserwator”. Cytowane referencje mówią: „Jednak model nie zależy ani od widoku, ani od kontrolera”. Czy przeczytałeś nawet cytowany artykuł? Nie wygląda na to.
CodeART

2
@Crazy Eddie: Nie obchodzi mnie, co pisze ktoś na kiepskim projekcie kodowym. To okropny projekt. Używanie obserwatora do nasłuchiwania zmian jest w porządku, ale umieszczenie interfejsu prezentacji w modelu domeny jest bardzo złe. Cytowany kod z artykułu jest wadliwy w kilku podstawowych aspektach w odniesieniu do MVC. Pozwala nawet modelowi domyślnie zależeć od kontrolera. Co za bzdura.
Falcon

3
@Crazy Eddie: lol @ downvote rampage. Rozwścieczyłem cię?
Falcon

-7
  • Kontroler wysyła model do widoku i przetwarza przesłany model z widoków, jednak nie jest ściśle powiązany z widokiem lub modelem.

Jeśli kontroler był ściśle powiązany z widokiem, będziemy w świecie formularzy internetowych. Masz kod, za którym byłby powiązany z plikiem szablonu (dotyczy formularzy internetowych ASP.NET)

Z tego powodu kontroler nie jest sprzężony z modelem ani widokiem. To tylko mechanizm przetwarzania żądań i wysyłania odpowiedzi.

  • Widok jest ściśle powiązany z modelem. Wprowadź zmiany w modelu (np. Zmień jego właściwość), a będziesz musiał wprowadzić zmiany w swoim widoku.

  • Model nie jest ściśle powiązany z widokiem. Wprowadź zmiany w widoku, a nie będzie to miało wpływu na model.

  • Model nie wie nic o kontrolerze ani widokach, w których można go użyć. Dlatego model nie jest ściśle powiązany z widokiem lub kontrolerem.

Inny sposób myślenia na ten temat:

  • Wprowadź zmiany w kontrolerze - widok i model pozostaną niezmienione

  • Wprowadź zmiany w modelu - widok ulegnie uszkodzeniu, ponieważ opiera się na modelu

  • Wprowadź zmiany w widoku - model i kontroler pozostaną nienaruszone

To luźne sprzężenie w projektach MVC sprawia, że ​​można je łatwo przetestować jednostkowo.


1
To jest tak źle, że to nie jest śmieszne. Nie warto nawet tego wyjaśniać. Po prostu całkowicie zignoruj ​​tę odpowiedź.
Reactgular

1
@MathewFoscarini Przestań płakać i pozostaw „poprawną odpowiedź”
CodeART

2
lol, cała teoria projektowania stojąca za MVC polega na tym, że nie są od siebie zależne.
Reactgular

Zostawiłem dla ciebie więcej informacji, mam nadzieję, że będzie to miało sens
CodeART
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.