![]() |
![]() ![]() |
![]() |
![]() ![]()
Post
#1
|
|
Grupa: Zarejestrowani Postów: 47 Pomógł: 1 Dołączył: 24.06.2010 Skąd: Sopot Ostrzeżenie: (0%) ![]() ![]() |
Hej,
przeczytałem kupę tematów o MVC na forum i zastanawia mnie tu jedna rzecz. Większość osób pokazuje schemat działania aplikacji jako taki: 1.) Kontroler rozpoznaje co użytkownik chce zrobić (np wyświetlić listę użytkowników). 2.) Kontroler odpala wtedy odpowiedni widok. 3.) Widok odpala model. 4.) Model przerabia co tam potrzebuje i zwraca dane do widoku. 5.) Widok prezentuje dane. Co mnie dziwi to fakt, że w ten sposób jeśli zmienię model, to muszę ingerować też w pliki widoku. Jest on uzależniony od konkretnego modelu. No i widok bezpośrednio współpracuje z modelem, a kontroler pełni funkcję jedynie routera. Czy w takim razie nie lepszy byłby schemat taki? 1.) Kontroler rozpoznaje co użytkownik chce zrobić (np wyświetlić listę użytkowników). 2.) Kontroler wybiera model i go odpala. 3.) Model przerabia co tam potrzebuje i zwraca dane do kontrolera. 4.) Kontroler wybiera widok i przekazuje mu dane od modelu. 5.) Widok wyświetla dane. W ten sposób Kontroler rzeczywiście pełni funkcję pośredniczącą między warstwą danych i działań, a warstwą prezentacyjną. Mogę stworzyć różne widoki do reprezentowania tego samego typu danych, a jednocześnie mogę mieć wiele źródeł danych, które będą wyświetlane przez ten sam widok. Co więcej upraszcza to schemat akcji, który może wyglądać tak: 1.) Kontroler rozpoznaje, co użytkownik chce zrobić (np dodać nowego użytkownika do bazy). 2.) Kontroler wybiera model i go odpala. 3.) Model przerabia co tam potrzebuje i zwraca dane do kontrolera (np kod błędu, kod sukcesu, itd.) 4.) Kontroler wybiera widok i przekazuje mu dane od modelu. 5.) Widok wyświetla dane. Voila! Okazuje się w ten sposób, że model jest równoważny akcji. Model służy wszystkim operacjom na danych, kontroler służy rozpoznawaniu tego co chce użytkownik i tego co chce model, a widok służy do prezentowania danych przekazanych mu przez kontroler. Co więcej, jeśli widok zwróci błąd, to kontroler znów rozpoznaje co się dzieje i odpala odpowiedni model jako reakcję, np logger. Pure MVC? Czy może jednak w takim podejściu tkwi jakiś błąd? pozdr. Ten post edytował MacDada 27.07.2010, 18:50:34 |
|
|
![]()
Post
#2
|
|
Grupa: Zarejestrowani Postów: 450 Pomógł: 84 Dołączył: 27.11.2008 Skąd: Warszawa Ostrzeżenie: (0%) ![]() ![]() |
Kontroler musi mieć dostęp do modelu - to oczywiste, ale żeby było zgodnie z MVC, widok także powinien mieć do niego dostęp. Takiego rozwiązania używamy tylko wtedy gdy jest dla nas "komfortowe". Przykład: menu renderowane jest z danych pobranych z bazy, nie będziemy chyba dołączać do każdego kontrolera kodu odpowiadającego za przypisanie menu pobranego przez model do zmiennej w widoku (IMG:style_emoticons/default/winksmiley.jpg) (pomijam tu globalne przypisywanie zmiennych do widoków).
|
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 952 Pomógł: 154 Dołączył: 20.01.2007 Skąd: /dev/oracle Ostrzeżenie: (0%) ![]() ![]() |
Wtedy jeśli zmienisz model, zamiast widoku będziesz musiał modyfikować kontroler (IMG:style_emoticons/default/smile.gif) . Poza tym to już wtedy nie będzie MVC, ale jeden z wzorców pochodnych. W MVP jedno z założeń mówi, że rola modelu i widoku jest zmniejszona na rzecz przypakowanego kontrolera zwanego tam prezenterem, który m.in. pośredniczy w komunikacji. Tyle jeśli chodzi o część teoretyczną, teraz praktyka:
Tak, jak mówisz, robione jest w zdecydowanej większości dostępnych frameworków. I to, czy jest to podejście wygodniejsze czy nie, to już trzeba programistów pytać. Na pewno w części zastosowań lepiej się ono sprawdzi, jednak w innych lepszy będzie MVC. Ja osobiście jestem zwolennikiem trzymania się oryginału bez żadnych udziwnień, ponieważ bardzo często już miałem do czynienia z mocno przerośniętymi kontrolerami, które robiły dosłownie wszystko, tylko nie to, do czego zostały stworzone. Ponadto zapominasz o pewnej rzeczy, jak ustandaryzowany interfejs. Nie wyobrażam sobie sytuacji, by modele nie trzymały się jakiejś konwencji. Dzięki temu niedawno udało mi się zaprojektować... kontroler CRUD ogólnego przeznaczenia oraz zestaw widoków do niego. Może z nim współpracować każdy model, który implementuje odpowiednie interfejsy, przez co de facto napisanie panelu sprowadza się do zrobienia modelu, ponieważ kod kontrolera liczy sobie 7 linijek, z czego 5 to deklaracje klasy, metod i nawiasy klamrowe (IMG:style_emoticons/default/smile.gif) . |
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 229 Pomógł: 34 Dołączył: 7.12.2008 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Od razu mówię, że nie mam jakiegoś strasznie dużego doświadczenia we frameworkach, ale wydaje mi się, że drugie podejście (wszystko przechodzi przez kontroler) jest sensowniejsze i bardziej intuicyjne. Piszesz Zyx, że w drugim podejściu kontroler robi wiele rzeczy, których nie powinien. A co, kiedy w pierwszym schemacie (typowy MVC) widok pobiera dane z Modelu i okazuje się, że Model zwrócił kod błędu. Teraz to widok zaczyna robić zbyt wiele zbędnych rzeczy, ponieważ musi sprawdzać kod błędu i zawiera w sobie niepotrzebne instrukcje if, przez co traci na przejrzystości kodu. A w podejściu drugim wywołujemy model i mamy prosty zestaw instrukcji warunkowych z renderowaniem widoków. Przejrzystość kodu znacznie na tym zyskuje.
A dodatkowo co z sytuacją o której pisał MacDada: zwracanie różnych typów widoków (HTML, JSON, XML). Wtedy tylko raz tworzymy odwołanie do danego modelu i ponownie dzięki kilku prostym instrukcjom if wyświetlamy odpowiedni widok. Oczywiście tak jak powiedziałem, nie mam dużego doświadczenia we frameworkach, dlatego byłbym wdzięczny za ewentualne skorygowanie mojego myślenia (IMG:style_emoticons/default/winksmiley.jpg) Pozdrawiam |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 952 Pomógł: 154 Dołączył: 20.01.2007 Skąd: /dev/oracle Ostrzeżenie: (0%) ![]() ![]() |
Jakie setki ifów? Słyszał waść o wyjątkach? (IMG:style_emoticons/default/smile.gif) Rzecz jest prosta: widok nie łapie wyjątków modelu, dzięki czemu może odebrać je kontroler i zareagować, kierując do standardowego systemu obsługi błędów modelu.
Jeśli chodzi o kwestię różnych typów widoków, umiejscowienie komunikacji niewiele zmienia. Podam Ci przykład w pseudokodzie:
Pamiętaj, że widok to nie tylko kod HTML (szablony), ale też logika prezentacji. Stronicowanie wyników ma sens w przypadku HTML-a, ale może nie mieć w formacie JSON lub PDF. Obsługa stronicowania to zadanie widoku - dzięki powyższemu podejściu, gdzie widok sam sobie pobiera dane, kontroler nie musi nawet wiedzieć, co dokładnie jest mu potrzebne do wykonania swojego zadania. Jeśli widok nie komunikuje się z modelem, kod ten musi wylądować w kontrolerze i wtedy nagle tu się pojawia mnóstwo ifów, a kod kontrolera staje się długi i przeładowany. Ponadto warto zwrócić uwagę, że da się stworzyć tzw. uniwersalne widoki wielokrotnego przeznaczenia. Jest to coś, co ciężko uświadczyć we frameworkach, które warstwę widoku zredukowały do systemu szablonów. Mam sobie uniwersalny widok do wyświetlania listy elementów, który ma już wbudowaną obsługę stronicowania, sortowania, filtrowania i co tam sobie jeszcze wymarzysz. Jeśli wszystkie dane idą przez kontroler, a ja będę chciał gdzieś sobie zrobić listę elementów, muszę zrobić Ctrl+C i Ctrl+V całego kodu, a następnie go popoprawiać, lub też obudować sztuczną atrapą, która sprowadzi nas do MVC. Tymczasem ja sobie robię:
I co? 6 linijek, a ja mam listę elementów modelu z sortowaniem, stronicowaniem, filtrowaniem i wszystkim, co sobie tylko model zażyczy. Jeśli tę samą sztuczkę chcę powtórzyć w innym miejscu, mogę to od razu zrobić, bo jedyne, co tak naprawdę muszę zrobić, to wprowadzić model do gotowego widoku. Kod kontrolera jest krótki i przejrzysty, dzięki czemu po dodaniu uwierzytelniania i kontroli uprawnień wciąż nadaje się do czytania. PS. Jeśli chcesz poeksperymentować z tego typu rzeczami, to obejrzyj sobie mój eksperymentalny framework stworzony do tego celu: http://github.com/zyxist/Trinity . Kod jest publicznie dostępny i możesz namacalnie sprawdzić, jak to działa w praktyce. Ten post edytował Zyx 27.07.2010, 21:29:09 |
|
|
![]()
Post
#6
|
|
Grupa: Zarejestrowani Postów: 229 Pomógł: 34 Dołączył: 7.12.2008 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
No i tutaj wychodzi brak doświadczenia (IMG:style_emoticons/default/winksmiley.jpg)
Faktycznie teraz ma to dla mnie dużo większy sens i właśnie o taką odpowiedź mi chodziło (IMG:style_emoticons/default/smile.gif) Tak więc ode mnie duże ukłony i dziękuję (IMG:style_emoticons/default/winksmiley.jpg) Trzeba jedynie zmienić trochę sposób myślenia i przystosować się do takiego podejścia, chociaż moim zdaniem ilość kodu będzie porównywalna w obu przypadkach. Niemniej podejrzewam, że dla wielu osób nadal podejście numer 2 jest bardziej intuicyjne i stąd takie, a nie inne zachowanie współczesnych frameworków. Jeszcze raz dzięki i pozdrawiam |
|
|
![]()
Post
#7
|
|
Grupa: Zarejestrowani Postów: 952 Pomógł: 154 Dołączył: 20.01.2007 Skąd: /dev/oracle Ostrzeżenie: (0%) ![]() ![]() |
Również dziękuję, bowiem sam też przy okazji odpowiadania znalazłem rozwiązanie jednego zagadnienia, które mnie nurtowało (IMG:style_emoticons/default/smile.gif) .
Zgadzam się, że MVC wymaga od programisty pewnego przyzwyczajenia, tym bardziej że nie ma się za bardzo na czym wzorować. Z tego, co już zdążyłem zauważyć, efektywne wykorzystanie MVC zależy w dużej mierze od zdyscyplinowania programisty z dwóch powodów. Pierwszy to kwestia interfejsów, które należy dobrze zdefiniować i się ich trzymać. Hipotetyczny framework MVC powinien oczywiście dostarczać szereg gotowych interfejsów do typowych zadań, ale przy bardziej egzotycznych potrzebach programista będzie już musiał stworzyć coś własnego. Drugi powód to umiejętność dostrzegania schematów i pisania takiego kodu, by nadawał się on do wielokrotnego użycia. Można pracować i bez tego, ale jak to jest z wzorcami - jeden programista zrobi z nich cudo, a drugi skopie dokumentnie (IMG:style_emoticons/default/smile.gif) . Podejście nr 2 jest o tyle intuicyjne, że de facto nie różni się ono w działaniu od skryptów pisanych sposobami gospodarczymi (IMG:style_emoticons/default/smile.gif) . Zauważ, że jak pisałeś kiedyś jakieś proste stronki, miałeś schemat: pobierz dane z bazy i przekaż je do systemu szablonów. Co prawda pobierałeś tam dane bezpośrednio z bazy, ale schemat postępowania był dokładnie taki sam i wiele rozwiązań można przenieść na grunt frameworków niemal bezpośrednio. Wg mnie takie uproszczenie dobrze działa dla aplikacji schematycznych, natomiast staje się mocno problematyczne przy bardziej nietypowych wymaganiach (np. modularny CMS, gdzie definicja strony, zamiast być zakodowana na sztywno, musi być ładowana z bazy, albo warstwa modelu jest bardzo skomplikowana). |
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 47 Pomógł: 1 Dołączył: 24.06.2010 Skąd: Sopot Ostrzeżenie: (0%) ![]() ![]() |
OK, czyli mechanizm, który opisałem to MVP. Próbowałem przeanalizować kod z git-huba z „prawdziwym MVC”, ale po kilku plikach doszedłem do wniosku, że nie potrzebuję w swoich projektach aż takiej komplikacji. MVP w zupełności mi na razie odpowiada (IMG:style_emoticons/default/smile.gif)
W każdym razie dzięki Zyx, bo widzę, że nie pierwszy raz się produkowałeś na ten temat... (IMG:style_emoticons/default/winksmiley.jpg) http://www.zyxist.com/en/archives/16 |
|
|
![]()
Post
#9
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Cytat doszedłem do wniosku, że nie potrzebuję w swoich projektach aż takiej komplikacji Jeżeli analizowałeś projekt Trinity to wiedz, że tam masz masę "syfu" niezwiązanego z samą implementacją MVC.IMO spróbuj sobie zrobić jakąś prostą aplikację nawet typu blog opartą na prawdziwym MVC (no, takim troszkę zmodyfikowanym na potrzeby środowiska HTTP, bo w nim ciężko o to by Model powiadamiał Widok o tym, że ma się on odświeżyć :]). Napewno zyskasz cenne doświadczenie + będziesz mógł rzetelnie ocenić czy MVC czy MVP bardziej pasuje do Twoich wymagań. |
|
|
![]()
Post
#10
|
|
Grupa: Moderatorzy Postów: 4 465 Pomógł: 137 Dołączył: 26.03.2004 Skąd: Gorzów Wlkp. ![]() |
Z tą nomenklaturą to też ostrożnie. Gdy szukałem po necie o różnicach MVC i MVP, to też nie wyszło tak pięknie jak opisuje Zyx. Po wizycie na jednej, czy dwóch stronach w ogóle straciłem rozeznanie (IMG:style_emoticons/default/sciana.gif)
|
|
|
![]()
Post
#11
|
|
Grupa: Zarejestrowani Postów: 47 Pomógł: 1 Dołączył: 24.06.2010 Skąd: Sopot Ostrzeżenie: (0%) ![]() ![]() |
Pod względem teoretycznym zgadzam z Zyx'em. Wystarczy spojrzeć na diagram MVC na Wikipedii i wyraźnie widać, że Widok także może mieć bezpośredni dostęp do modelu.
Stąd doszedłem do wniosku, że w praktyce zamiast MVC lepiej zrobić MVTC, czyli Model View Template Controller. W ten sposób mamy Kontroler, który odpala model i odpowiedni widok, widok odpala sobie w razie potrzeby model, a na koniec zbiera to co chce do kupy i przekazuje do Szablonu. W ten sposób wilk syty i owca cała, tzn Graficy bawią się jedynie na Szablonie, a jednocześnie Widok nie jest tylko Szablonem, ale zawiera także logikę Widoku w postaci paginatora, itp. Choć na razie to czysta teoria, bo takiego podejścia nie wypróbowałem i nie widziałem (IMG:style_emoticons/default/winksmiley.jpg) EDIT: W mojej wizji kontrolerów byłoby wiele. Przykład oklepany - blog (IMG:style_emoticons/default/winksmiley.jpg)
Jak widać generalnie działałoby to tak, że Kontroler nadrzędny odpala Widok, który korzysta z podrzędnych Kontrolerów i odpowiedniego Modelu, by zbudować sobie dynamiczną zawartość. Taka jakby hierarchia. Co dziwne, w ten sposób Kontrolerzy nie korzystają z Modelów, bo... nie potrzebują? Nie wiem po co miałyby to robić. Zalety tego rozwiązania (oprócz samego oddzielenia warstwy prezentacji od treści) widzę dwie:
Ten post edytował MacDada 29.07.2010, 00:44:25 |
|
|
![]()
Post
#12
|
|
Grupa: Zarejestrowani Postów: 2 291 Pomógł: 156 Dołączył: 23.09.2007 Skąd: ITALY-MILAN Ostrzeżenie: (10%) ![]() ![]() |
Pod względem teoretycznym zgadzam z Zyx'em. Wystarczy spojrzeć na diagram MVC na Wikipedii i wyraźnie widać, że Widok także może mieć bezpośredni dostęp do modelu. Stąd doszedłem do wniosku, że w praktyce zamiast MVC lepiej zrobić MVTC, czyli Model View Template Controller. W ten sposób mamy Kontroler, który odpala model i odpowiedni widok, widok odpala sobie w razie potrzeby model, a na koniec zbiera to co chce do kupy i przekazuje do Szablonu. W ten sposób wilk syty i owca cała, tzn Graficy bawią się jedynie na Szablonie, a jednocześnie Widok nie jest tylko Szablonem, ale zawiera także logikę Widoku w postaci paginatora, itp. Choć na razie to czysta teoria, bo takiego podejścia nie wypróbowałem i nie widziałem (IMG:style_emoticons/default/winksmiley.jpg) EDIT: W mojej wizji kontrolerów byłoby wiele. Przykład oklepany - blog (IMG:style_emoticons/default/winksmiley.jpg)
Jak widać generalnie działałoby to tak, że Kontroler nadrzędny odpala Widok, który korzysta z podrzędnych Kontrolerów i odpowiedniego Modelu, by zbudować sobie dynamiczną zawartość. Taka jakby hierarchia. Co dziwne, w ten sposób Kontrolerzy nie korzystają z Modelów, bo... nie potrzebują? Nie wiem po co miałyby to robić. Zalety tego rozwiązania (oprócz samego oddzielenia warstwy prezentacji od treści) widzę dwie:
To o czym mowisz to fron controller i block controller czy jakos tak czyli jeden glowny szbalon dla calej strony do tego jeden kontroler i model ktory pobiera w jakie miejsce do glownego szablonu maja byc podpiete moduly/pluginy/widgety czy co tam chcesz.Jak juz sam mowiles kazdy modul np ma swoj model,kontroler i szablon/template... Ja mam tak w moim fw jest mi z tym wygodnie i w ogole wszystko ladnie hula, wrzuce gdzies na jakiegos rapida zeby mozna bylo sobie zobaczyc pisane dosyc dawno wiec kod troche lichy teraz napisalbym bym to przynajmniej x2 lepiej :] Jedyne co to cala logika jest w kontrolerze bo "widok" u mnie to zwykly szablon/templare nie klasa widoku ktora odpala szablon ;] P.S lap jak chcesz: http://www.sendspace.pl/file/1e498eb450c7b4c35fa1098 Ten post edytował marcio 29.07.2010, 16:08:44 |
|
|
![]()
Post
#13
|
|
Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
@MacDada: To co opisałeś to tzw. HMVC (tj. nie MVC, ale na literce H się teraz skupiamy). H jak hierarchiczny.
Ten post edytował Crozin 30.07.2010, 01:11:19 |
|
|
![]()
Post
#14
|
|
Grupa: Zarejestrowani Postów: 47 Pomógł: 1 Dołączył: 24.06.2010 Skąd: Sopot Ostrzeżenie: (0%) ![]() ![]() |
@MacDada: To co opisałeś to tzw. HMVC (tzw. nie MVC, ale na literce H się teraz skupiamy). H jak hierarchiczny. Coś tak czułem, że podejrzane by było, gdyby nikt wcześniej na to nie wpadł (IMG:style_emoticons/default/haha.gif)
|
|
|
![]() ![]() |
![]() |
Aktualny czas: 23.09.2025 - 11:50 |