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.
Odpowiedzi:
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.
źródło
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
controller
jest mechanizm dostarczania twojego programu.$user->addToCart($product)
addToCart
funkcjauser
obiektu) wykonuje pracę, do której jest przeznaczony, i zwraca odpowiedź (powiedzmysuccess
)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.
Po dodaniu produktu do koszyka, można dodać The
product::id
douser::shoppingCart
.A jeśli chcesz zachować dane, możesz użyć
model
częś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.
źródło
MVC
jest. Dlatego napisałemMVC Framework
.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”.
źródło
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
źródło
Łą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
modelKontroler 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ć.
źródło
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.
źródło
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.
źródło