Czy w MVC kilka widoków może mieć ten sam kontroler, czy jeden widok musi mieć jeden unikalny kontroler?

15

Mam kilka pytań podczas projektowania architektury dla projektu wokół MVC. (Jest to projekt C ++ / Marmalade SDK, nie używam żadnego konkretnego frameworka MVC, robię go.)

W kilku artykułach (jak na oryginalnym artykule Steve'a Burbka ) wciąż czytam pojęcie „triada MVC”, co mnie denerwuje, ponieważ wziąłem tę koncepcję dosłownie. Kiedy czytam to po raz pierwszy, wyglądało na to, że aplikacja jest zbudowana wokół jednostek „triady MVC” - po jednej dla każdego elementu interfejsu, jak przypuszczałem - ale uważam, że jest to raczej mało elastyczne i myślę, że nie tak zamierzano używać MVC. Następnie, badając dalej ten problem, znalazłem kilka przykładów ścisłego połączenia kontrolera i widoku, a mianowicie relację 1-do-1 - TextEditView ma TextEditController.

Ale kiedy wracam do mojego projektu, stwierdzam, że użyteczne może być posiadanie jednego kontrolera (według „jednostki logicznej”, takiej jak AddElementController) i kilku widoków dla tego konkretnego kontrolera.

Wyraźnie myślę o czymś takim jak AddElementController, który powinien mieć interfejs użytkownika tabulatora. Czy powinienem mieć AddElementController, który ma AddElementTabView i kilka AddImageView, AddSoundView itp. Dla kart? Czy powinienem mieć inny „kontroler podrzędny” dla każdego widoku karty?

Podsumowując, i jeśli chodzi o wzorzec MVC (a nie zrozumienie / wdrożenie tego wzorca w ramach X), czy poprawne jest posiadanie kilku widoków dla kontrolera, czy też każdy widok powinien mieć swój konkretny kontroler?

Ponadto, czy poprawne jest przechowywanie niektórych informacji o stanie na kontrolerze, czy też powinno to być bezpaństwowe (co oznacza, że ​​stan powinien być umieszczony w jakimś modelu stanu spoza domeny)?

Dzięki wszystkim z góry.

pedrosanta
źródło

Odpowiedzi:

14

Problem polega na tym, że wzorzec MVC został zaprojektowany w systemie, który tak naprawdę już nie istnieje. Został wynaleziony w Smalltalk w czasie, gdy biblioteki UI nie istniały. Aby utworzyć okno dialogowe, narysowałeś wszystkie pola, podświetliłeś odpowiednie kwadraty, upewniłeś się, że rysowany tekst znalazł się we właściwym miejscu ... itd ...

Wyobraź sobie, jak by to było napisać aplikację dialogową, używając tylko jednego dużego płótna. To świat, z którego pochodzi MVC.

„Widok” w tym systemie był polem tekstowym i była klasą odpowiedzialną za rysowanie ramki, tekstu, rysowanie wybranych obszarów, reagowanie na zmiany w tekście itp.

„Kontroler” był kolejną klasą, która pobierała zdarzenia myszy, które miały miejsce w tym polu, takie jak poruszanie myszą, klawisz w dół, klawisz w górę, kliknięcia itp. I decydowało o tym, co się stanie. Czy powinniśmy zmienić tekst? Czy powinniśmy zmienić wybór? Takie rzeczy.

„Model” to kolejna klasa reprezentująca podstawowe dane i stan komponentu. Model pola tekstowego miałby oczywiście tekst, czcionkę, zaznaczenie itp.

Jak widać, w takiej sytuacji trzy elementy są bardzo uwikłane w przedstawienie jednego pomysłu. W tym kontekście sensowne jest mówienie o „triadzie”.

Dzisiaj, jeśli pracujesz nad tworzeniem biblioteki interfejsu użytkownika i korzystaniem z surowych poleceń rysunkowych, możesz zrobić coś podobnego. Jednak zastosowanie wzorca „MVC” wykroczyło poza pierwotny cel. Teraz masz „widok”, który może być kompletnym oknem dialogowym i kontroler, który reaguje na zdarzenia takie jak „textChanged” lub „buttonClicked”. Model w dzisiejszym MVC jest zwykle czymś dość odłączonym od systemu (ale ogólnie jest połączony z widokiem, zapewniając pewnego rodzaju interfejs obserwatora) i może istnieć wiele widoków związanych z jednym modelem.

W systemie, który niedawno zaprojektowałem, mieliśmy na przykład około 10+ widoków, z których każdy obserwował jednego „posiadacza” dokumentu i jego aktywny dokument. Główny interfejs rysunkowy współdziałał z układem dokumentu, różnymi widokami właściwości, które obserwowały wybrany element i zapewniały interfejs zapisu, oraz reprezentację widoku głównego w mniejszej skali, która pokazywała cały dokument zamiast tylko widocznego okna. Niektóre z tych widoków miały kontrolery o różnej złożoności, które zamieniały zdarzenia GUI w zmiany w dokumencie, co z kolei powiadamiałoby o jego różnych widokach.

Czy nadal możesz nazwać taki związek „triadą”? Być może, ale myślę, że implikuje to zbyt wiele dawnej, starszej aplikacji MVC.

Czy możesz współdzielić kontrolery z różnymi widokami? Zależy od tego, jak podobne są widoki. Przekonałem się, że ogólnie mówiąc, tego typu obiekt ma zachowanie specyficzne dla kontrolowanego przez niego widoku ORAZ model, którym manipuluje, aby był bardzo wielokrotnego użytku ... ale zawsze są wyjątki.

Edward Strange
źródło
5

To zależy. Istnieje kilka wariantów MVC, niektóre, w których sens ma tylko relacja 1: 1 (jak „skromne okno dialogowe”), inne, w których tak nie jest. Poleciłbym przeczytać serię artykułów „ Build Your Own CAB ”, wyjaśniającą najważniejsze warianty MVC.

Doktor Brown
źródło
3

Widoki nie mają kontrolerów w MVC. Kontroler jest szefem, więc Kontroler decyduje, który Widok ma być renderowany, a Widoki nie dbają / nie dbają, który Kontroler zażądał Widoku.

Możesz / będziesz mieć absolutnie wiele widoków z kontrolera. Pomyśl o stworzeniu modelu dla każdego widoku, jeśli chcesz trzymać się wzoru MVC.

Mert Akcakaya
źródło
3

Celem kontrolera jest kontrolowanie interakcji użytkownika z modelem domeny - to jest poziom pośrednictwa między tym, co użytkownik widzi (widok), a stanem aplikacji (model).

Gdy użytkownik zgłasza żądanie, jest ono kierowane do kontrolera. Kontroler decyduje, w jaki sposób przekazać to żądanie do aplikacji, zwykle za pośrednictwem pewnego rodzaju klasy usług. Następnie interpretuje odpowiedź z tej klasy usługi i decyduje, jaki widok odesłać do użytkownika.

Kontroler może zawsze zwrócić ten sam widok (1: 1), jeśli istnieje tylko jedno żądanie, które użytkownik może wysłać do kontrolera i zawsze wymaga tego samego rodzaju odpowiedzi. Na przykład HelloWorldControllerzawsze HelloWorldViewwyświetla komunikat „Witaj, świecie!”

Z drugiej strony kontroler często musi decydować o różnych widokach, w zależności od tego, co mówi model. TeamRosterControllerMoże zwróci RugbyTeamRosterViewlub FootbalTeamRosterView, w zależności od rodzaju żądanego zespołu.

Generalnie preferowane jest, aby kontrolery były bezstanowe, chociaż pewien dostęp do stanu sesji użytkownika może być konieczny lub pożądany. W miarę możliwości należy zarządzać dostępem do tego stanu osobno.

Zdecydowanie polecam przyjrzenie się rzeczywistej ramie MVC, aby zobaczyć, co ona robi i jak działa. Nie musisz go używać, ale na pewno uzyskasz lepsze zrozumienie przed zbudowaniem własnego.

Matthew Flynn
źródło