Co wchodzi do "kontrolera" w "MVC"?

Myślę, że rozumiem podstawowe pojęcia MVC - Model zawiera dane i zachowanie aplikacji, widok jest odpowiedzialny za wyświetlanie go użytkownikowi, a kontroler zajmuje się wprowadzaniem przez użytkownika. Nie wiem, co dokładnie wchodzi do kontrolera.

Powiedzmy na przykład, że mam dość prostą aplikację (myślę konkretnie o Javie, ale przypuszczam, że te same zasady obowiązują gdzie indziej). Organizuję mój kod w 3 pakiety o nazwie app.model, app.view i app.controller.

W pakiecie app.model mam kilka klas, które odzwierciedlają rzeczywiste zachowanie aplikacji. Te extends Observable i użyć setChanged() i notifyObservers(), aby uruchomić widoki do aktualizacji, gdy jest to właściwe.

Pakiet app.view posiada klasę (lub kilka klas dla różnych typów wyświetlaczy), która wykorzystuje komponenty javax.swing do obsługi wyświetlacza. Niektóre z tych komponentów muszą zostać ponownie wprowadzone do modelu. Jeśli dobrze rozumiem, widok nie powinien mieć nic wspólnego z informacje zwrotne - którymi powinien zająć się Kontroler.

Więc co właściwie włożyć do kontrolera? Czy umieszczam public void actionPerformed(ActionEvent e) w widoku z wywołaniem metody w kontrolerze? Jeśli tak, to czy w kontrolerze należy wykonać walidację itp.? Jeśli tak, w jaki sposób mogę wysyłać komunikaty o błędach z powrotem do widoku - czy powinny one przejść przez Model ponownie, czy kontroler powinien po prostu wysłać go z powrotem do widoku?

Jeśli Walidacja zostanie wykonana w widoku, co umieścić w Kontroler?

Przepraszam za długie pytanie, chciałem tylko udokumentować moje zrozumienie procesu i mam nadzieję, że ktoś może wyjaśnić ten problem dla mnie!

Author: victor hugo, 2009-06-19

13 answers

W zaproponowanym przez Ciebie przykładzie masz rację: "użytkownik kliknął przycisk" Usuń ten element "w interfejsie powinien w zasadzie wywołać funkcję" Usuń " kontrolera. Kontroler nie ma jednak pojęcia, jak wygląda Widok, więc widok musi zbierać pewne informacje, takie jak "który element został kliknięty?"

W formie rozmowy:

View: "Hey, controller, the user just told me he want item 4 deleted."
Kontroler: "Hmm, po sprawdzeniu jego legitymacje, ma do tego prawo... Hej, modelko, chcę żebyś zdobyła punkt 4 i zrobiła wszystko, żeby go usunąć."
Wzór : "Pozycja 4... Rozumiem. Został usunięty. Oddaję głos, kontrolerze."
Kontroler: "tutaj zbieram nowy zestaw danych. Wracamy do ciebie, view."
View: "Super, teraz pokażę nowy zestaw użytkownikowi."

Na końcu tej sekcji masz opcję: albo Widok może złożyć oddzielne żądanie, "podaj mi najnowszy zestaw danych", a w ten sposób być bardziej czyste, lub kontroler domyślnie zwraca nowy zestaw danych z operacją "delete".

 456
Author: Andres Jaan Tack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-23 18:47:53

Problem z MVC polega na tym, że ludzie myślą, że widok, kontroler i model muszą być jak najbardziej niezależne od siebie. Nie - widok i kontroler są często ze sobą powiązane-uważają to za M(VC).

Kontroler jest mechanizmem wejściowym interfejsu użytkownika, który jest często splątany w widoku, szczególnie z GUI. Niemniej jednak widok jest wyjściem, a kontroler jest wejściem. Widok często może działać bez odpowiedniego kontrolera, ale kontroler jest zwykle znacznie mniej przydatne bez widoku. Przyjazne dla użytkownika Kontrolery wykorzystują widok do interpretacji danych wejściowych użytkownika w bardziej znaczący, intuicyjny sposób. To właśnie sprawia, że trudno oddzielić koncepcję kontrolera od widoku.

Pomyśl o sterowanym radiowo robocie na polu detekcji w zapieczętowanym pudełku jako modelu.

Model dotyczy przejść stanu i stanu bez pojęcia wyjścia (wyświetlania) lub tego, co wywołuje przejścia stanu. Mogę dostać robota. pozycja na polu, a robot wie, jak zmienić pozycję (zrób krok do przodu / do tyłu / w lewo / w prawo. Łatwy do wyobrażenia bez widoku lub kontrolera, ale nie robi nic użytecznego

Pomyśl o widoku bez kontrolera, np. ktoś w innym pokoju w sieci w innym pokoju Obserwujący pozycję robota jako współrzędne (x,y) strumieniowe w dół konsoli przewijania. Ten widok pokazuje tylko stan modelu, ale ten facet nie ma kontrolera. Ponownie, łatwo wyobrazić sobie ten widok bez kontrolera.

Pomyśl o kontrolerze bez widoku, np. ktoś zamknięty w szafie z kontrolerem radiowym dostrojonym do częstotliwości robota. Ten kontroler wysyła dane wejściowe i powoduje przejścia stanu bez pojęcia, co robią z modelem(jeśli w ogóle). Łatwe do wyobrażenia, ale nie bardzo przydatne bez pewnego rodzaju sprzężenia zwrotnego z widoku.

Najbardziej przyjazny interfejs użytkownika koordynuje widok z kontrolerem, aby zapewnić bardziej intuicyjny interfejs użytkownika. Na na przykład wyobraź sobie widok / kontroler Z Ekranem dotykowym pokazującym aktualną pozycję robota w 2-D i pozwala użytkownikowi dotknąć punktu na ekranie, który akurat znajduje się przed robotem. Kontroler potrzebuje szczegółów dotyczących widoku, np. pozycji i skali viewportu oraz pozycji piksela dotkniętego miejsca w stosunku do pozycji piksela robota na ekranie), aby poprawnie zinterpretować to (w przeciwieństwie do faceta zamkniętego w szafie z radiem kontroler).

Czy odpowiedziałem już na twoje pytanie? :-)

Kontroler to wszystko, co pobiera dane od użytkownika, które jest używane do wywołania stanu przejścia modelu. Staraj się, aby widok i kontroler były rozdzielone, ale zdaj sobie sprawę, że często są od siebie współzależne, więc jest w porządku, jeśli granica między nimi jest rozmyta, tzn. posiadanie widoku i kontrolera jako oddzielnych pakietów może nie być tak czysto oddzielone, jak byś chciał, ale to jest w porządku. Być może będziesz musiał zaakceptować kontroler nie będzie czysto oddzielony od widoku, ponieważ widok jest od modelu.

... czy jakakolwiek Walidacja itp. powinna być zrobione w kontrolerze? Jeśli tak, to jak I feedback error messages back to the Widok-powinien przejść przez Model ponownie, czy powinien Kontroler odeślij go prosto do widoku?

Jeśli Walidacja odbywa się w widoku, co umieścić w kontrolerze?

Mówię, że połączony widok i kontroler powinny swobodnie współdziałać bez przechodzenia przez model. Kontroler pobiera dane użytkownika i powinien dokonać walidacji (być może używając informacji z modelu i / lub widoku), ale jeśli Walidacja się nie powiedzie, Kontroler powinien być w stanie bezpośrednio zaktualizować swój powiązany widok (np. komunikat o błędzie).

Test kwasowy dla tego jest zadać sobie pytanie, czy niezależny widok (tzn. facet w drugim pokoju Obserwujący pozycję robota przez sieć) powinien widzieć cokolwiek lub nie w wyniku czyjegoś błąd walidacji (np. facet w szafie próbował powiedzieć robotowi, aby wyszedł z boiska). Generalnie odpowiedź brzmi NIE - Błąd walidacji uniemożliwił przejście stanu. Jeśli nie było transtion stanu (robot nie poruszał się), nie ma potrzeby, aby powiedzieć innym poglądom. Facet w szafie po prostu nie dostał żadnych opinii, że próbował spowodować nielegalne Przejście (Brak widoku-zły interfejs użytkownika), i nikt inny nie musi o tym wiedzieć.

Jeśli facet z Ekranem dotykowym próbował wyślij robota z pola, dostał miły komunikat przyjazny dla użytkownika z prośbą, że nie zabić robota, wysyłając go z pola wykrywania, ale ponownie, nikt inny nie musi o tym wiedzieć.

Jeśli inne widoki muszą wiedzieć o tych błędach, to skutecznie mówisz, że dane wejściowe od użytkownika i wszelkie powstałe błędy są częścią modelu i cała sprawa jest trochę bardziej skomplikowana ...

 57
Author: Bert F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-17 14:19:23

Oto Dobry artykuł na temat podstaw MVC.

Stwierdza ...

Controller-Kontroler tłumaczy interakcje z widokiem na czynności, które ma wykonać model.

Innymi słowy, twoja logika biznesowa. Kontroler reaguje na działania użytkownika podjęte w widoku i odpowiada. Umieszczasz tutaj walidację i wybierasz odpowiedni Widok, jeśli Walidacja się nie powiedzie lub powiedzie (strona o błędzie, okno wiadomości, nieważne).

Jest jeszcze jeden dobry artykuł W Fowler.

 23
Author: JP Alioto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-14 15:47:47

Wzorzec MVC chce tylko, aby oddzielić prezentację (= widok) od logiki buisiness (=model). Część kontrolera jest tam tylko po to, aby spowodować zamieszanie.

 14
Author: Dimitri C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-11-23 09:23:56

Bazując na twoim pytaniu, odnoszę wrażenie, że jesteś trochę zamglony na roli modelu. Model jest związany z danymi powiązanymi z aplikacją; jeśli aplikacja ma bazę danych, zadaniem modelu będzie rozmowa z nią. Będzie również obsługiwać każdą prostą logikę związaną z tymi danymi; jeśli masz regułę, która mówi, że dla wszystkich przypadków, gdzie tabela.foo = = " Hura!"i stół.bar = = " Huzzah!"więc nakryj do stołu.field = " W00t!", a następnie chcesz, aby Model się tym zajął.

The Kontroler jest tym, co powinno obsługiwać większość zachowań aplikacji. Więc aby odpowiedzieć na twoje pytania:

" czy dodaję do widoku publiczny void actionPerformed(ActionEvent e) tylko wywołanie metody w kontrolerze?"

Powiedziałbym, że nie. Powiedziałbym, że powinien on żyć w kontrolerze; Widok powinien po prostu przekazywać dane pochodzące z interfejsu użytkownika do kontrolera i pozwolić kontrolerowi zdecydować, które metody powinny być wywołane w odpowiedzi.

" jeśli tak, to powinien jakakolwiek Walidacja itp. zostanie wykonana w kontrolerze?"

Większość twojej walidacji powinna być wykonana przez kontrolera; powinien on odpowiedzieć na pytanie, czy dane są poprawne, a jeśli nie, wprowadź odpowiednie komunikaty o błędach do widoku. W praktyce w warstwie widoku można włączyć kilka prostych sprawdzeń zdrowego rozsądku w celu poprawy komfortu użytkowania. (Myślę głównie o środowiskach internetowych, w których może pojawić się komunikat o błędzie użytkownik naciska "Submit" zamiast czekać na cały cykl submit -> proces -> Wczytaj stronę, zanim powie, że nawalił.) Po prostu bądź ostrożny; nie chcesz powielać wysiłku bardziej niż Musisz, a w wielu środowiskach (znowu myślę o sieci) często musisz traktować wszelkie dane pochodzące z interfejsu użytkownika jako paczkę brudnych brudnych kłamstw, dopóki nie potwierdzisz, że są one rzeczywiście uzasadnione.

"jeśli tak, to jak mogę wysyłać komunikaty o błędach z powrotem do widoku-czy to przejrzyj Model jeszcze raz, czy kontroler powinien wysłać go prosto z powrotem do wyświetlenia?"

Powinieneś mieć skonfigurowany protokół, w którym widok nie musi wiedzieć, co dalej, dopóki Kontroler tego nie powie. Jaki ekran pokazujesz po tym, jak użytkownik uderzy ten przycisk? Widok może nie wiedzieć, a kontroler może nie wiedzieć, dopóki nie spojrzy na dane, które właśnie otrzymał. Może to być "przejdź do tego drugiego ekranu, zgodnie z oczekiwaniami" lub " pozostań na tym ekranie i wyświetl ten błąd wiadomość".

Z mojego doświadczenia wynika, że bezpośrednia komunikacja pomiędzy modelem a widokiem powinna być bardzo, bardzo ograniczona, a widok nie powinien bezpośrednio zmieniać żadnych danych Modelu; to powinno być zadanie kontrolera.

" jeśli Walidacja zostanie wykonana w widoku, co umieścić w kontrolerze?"

Patrz powyżej; prawdziwa Walidacja powinna być w kontrolerze. I mam nadzieję, że masz jakiś pomysł, co należy umieścić w kontrolerze już teraz. :-)

Warto zauważyć, że wszystko może być trochę zamazane na krawędziach; jak w przypadku większości rzeczy tak złożonych, jak inżynieria oprogramowania, wywołania oceny będą obfitować. Po prostu użyj najlepszego osądu, staraj się zachować spójność w tej aplikacji i spróbuj zastosować lekcje, których się nauczysz do następnego projektu.

 9
Author: BlairHippo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 00:44:53

Praktycznie rzecz biorąc, nigdy nie uznałem koncepcji kontrolera za szczególnie przydatną. W kodzie używam ścisłego oddzielenia model/widok, ale nie ma jasno zdefiniowanego kontrolera. Wydaje się to niepotrzebną abstrakcją.

Osobiście, Pełnowymiarowy MVC wydaje się wzorcem projektowym fabryki, ponieważ łatwo prowadzi do mylącego i zbyt skomplikowanego projektu. Nie bądź astronautą architektury .

 9
Author: John Kugelman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:26

Kontroler jest naprawdę częścią widoku. Jego zadaniem jest ustalenie, które usługi są potrzebne do spełnienia żądania, unmarshal wartości z widoku na obiekty, których wymaga interfejs usługi, określenie następnego widoku i dodanie odpowiedzi z powrotem do formularza, którego może użyć Następny Widok. Obsługuje również wszelkie wyjątki, które są wyrzucane i renderuje je do widoków, które użytkownicy mogą zrozumieć.

Warstwa usług to rzecz, która zna przypadki użycia, jednostki pracy i model obiektów. Kontroler będzie inny dla każdego typu widoku - nie będziesz mieć tego samego kontrolera dla interfejsów komputerowych, opartych na przeglądarce, Flex lub mobilnych. Więc mówię, że to naprawdę część interfejsu użytkownika.

Zorientowane na usługi: to jest miejsce, gdzie praca jest wykonywana.

 7
Author: duffymo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 01:16:54

Kontroler służy przede wszystkim do koordynacji między widokiem a modelem.

Niestety, czasami kończy się mieszanie się z widokiem-w małych aplikacjach, choć nie jest tak źle.

Proponuję umieścić:

public void actionPerformed(ActionEvent e)

W kontrolerze. Następnie odbiornik akcji w widoku powinien delegować do kontrolera.

Jeśli chodzi o część walidacji, możesz umieścić ją w widoku lub kontrolerze, osobiście uważam, że należy do kontroler.

Zdecydowanie polecam zajrzenie do widoku pasywnego i nadzorowanie prezentera (na co zasadniczo dzieli się Model View Presenter - przynajmniej przez Fowlera). Zobacz:

Http://www.martinfowler.com/eaaDev/PassiveScreen.html

Http://www.martinfowler.com/eaaDev/SupervisingPresenter.html

 3
Author: Jon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 00:40:21

Oto zasada, której używam: jeśli jest to procedura, której będę używać w szczególności dla akcji na tej stronie , należy ona do kontrolera, a nie do modelu. Model powinien zapewniać jedynie spójną abstrakcję do przechowywania danych.

Wymyśliłem to po pracy z dużą webapp napisaną przez programistów, którzy myśleli, że zostały zrozumiane MVC, ale tak naprawdę nie. ich "kontrolery" są zredukowane do ośmiu linii wywołania statycznych metod klas, które są zwykle nazywane nigdzie indziej: - / czyniąc ich modele niewiele bardziej niż sposoby tworzenia przestrzeni nazw. Refaktoryzacja tego poprawnie robi trzy rzeczy: przenosi cały SQL do warstwy dostępu do danych (aka model), sprawia, że kod kontrolera jest nieco bardziej zwrotny, ale o wiele bardziej zrozumiały i zmniejsza stare pliki "modelu" do zera. :-)

 3
Author: staticsan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 01:02:49

Zauważ również, że każdy widżet Swing może być uważany za zawierający trzy komponenty MVC: każdy ma Model (tj. ButtonModel), Widok (BasicButtonUI) i kontrolkę (sam JButton).

 1
Author: akf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 01:00:47

Masz zasadniczo rację co do tego, co umieściłeś w kontrolerze. Jest to jedyny sposób, w jaki Model powinien wchodzić w interakcję z widokiem. Actionperformed może być umieszczony w widoku, ale rzeczywista funkcjonalność może być umieszczona w innej klasie, która będzie działać jako kontroler. Jeśli masz zamiar to zrobić, polecam przyjrzeć się wzorcowi poleceń, który jest sposobem abstrakcji wszystkich poleceń, które mają ten sam odbiornik. Przepraszam za dygresję.

Anyway, a proper MVC implementacja będzie miała tylko następujące interakcje: Model - > Zobacz Widok - > Kontroler Controller - > View

Jedynym miejscem, w którym może wystąpić Inna interakcja, jest użycie obserwatora do aktualizacji widoku, wtedy Widok będzie musiał poprosić Kontroler o potrzebne informacje.

 1
Author: mnuzzo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 01:12:32

Jak rozumiem, Kontroler tłumaczy z działań interfejsu użytkownika na działania na poziomie aplikacji. Na przykład, w grze wideo kontroler może przetłumaczyć "przeniósł mysz tyle pikseli" na " chce wyglądać w takim I takim kierunku. W aplikacji CRUD tłumaczenie może być "kliknięte na taki i taki przycisk", aby" wydrukować to coś", ale koncepcja jest taka sama.

 0
Author: David Seiler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-19 00:05:20

Robimy to w ten sposób, używając kontrolerów głównie do obsługi i reagowania na wejścia/akcje użytkownika (i _logic dla wszystkiego innego, z wyjątkiem widoku, danych i oczywistych rzeczy _Model):

(1) (ODPOWIEDŹ, reakcja-co webapp "robi" w odpowiedzi na użytkownika) Blog_Controller

- > main ()

- >handleSubmit_AddNewCustomer ()

- >verifyUser_HasProperAuth ()

(2) ("biznes" logika, co i jak webapp "myśli") Blog_Logic

- >sanityCheck_AddNewCustomer ()

->handleUsernameChange ()

->sendEmail_NotifyRequestedUpdate ()

(3) (widoki, portale, jak pojawia się webapp") Blog_View

- > genWelcome ()

->genForm_AddNewBlogEntry ()

->genPage_DataEntryForm ()

(4) (Tylko obiekt danych, pozyskany w _ construct() każdej klasy bloga *, używany do przechowywania wszystkich danych webapp / inmemory razem jako jeden obiekt) Blog_Meta

(5) (Podstawowa Warstwa danych, Odczyt/Zapis do DBs) Blog_Model

- >saveDataToMemcache ()

->saveDataToMongo ()

- >saveDataToSql ()

- >loadData ()

Czasami jesteśmy trochę zdezorientowani, gdzie umieścić metodę, w C lub L. ale Model jest solidny, krystalicznie czysty, a ponieważ wszystkie dane w pamięci znajdują się w _Meta, nie ma się nad czym zastanawiać. Naszym największym krokiem naprzód było przyjęcie _Meta use, tak przy okazji, jak to wyczyściło wszystkie crud z różne obiekty _C, _L i _Model sprawiły, że zarządzanie tym wszystkim było mentalnie łatwe, plus, za jednym zamachem, dało nam to, co nazywa się "Dependency Injection", czyli sposób na przekazanie całego środowiska wraz ze wszystkimi danymi (którego zaletą jest łatwe tworzenie środowiska "testowego").

 0
Author: FYA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-20 16:22:49