MVC dla gry PHP/MySQL/JQuery/HTML - poprawnie?

0

Witam.
Chcę użyć modelu MVC do dość nietypowego zagadnienia, a mianowicie w aplikacji webowej (dajmy na to gry karcianej) opartej o PHP/MySQL/JQuery/HTML. Wiem że MVC rzadko używa się do gier, znam wady i zalety tego rozwiązania, w każdym razie zdecydowałem się na to i chcę teraz w pełni poprawnie użyć MVC.

Potrzebuję dowiedzieć się, czy mój projekt jest poprawny (zgodny z MVC) i czy da się w nim ewentualnie coś uprościć?

Wiem że post będzie długi, pytań wiele, ale chciałem być możliwie precyzyjny i z góry dziękuję za pomoc przy rozwiązaniu któregokolwiek z nich :-)

Zacznę od przedstawienia swojego rozwiązania. Na początku rzeczy które raczej nie budziły u mnie wątpliwości (przedstawiam w dwóch etapach by łatwiej było wyłapać moje błędy i sposób rozumowania):

Model
Język: PHP
Reprezentacja: klasa Model
Odwołuje się do: brak odwołań
Zadania: Komunikuje się z bazą danych i zwraca obiekty (PHP) różnych typów, zależnie od zapytania. Np. na zapytanie $model->getUser() zwraca obiekt User o polach takich jak login, password etc. (wypełnionymi dzięki komunikacji z bazą.

Controller
Język: PHP
Reprezentacja: klasa Controller
Odwołuje się do: Model, View
Zadania: Inicjuje Model i View, karze widokowi wyrenderować obiekty (np. $view->renderPanel("loginPanel")).

View
Język: PHP
Reprezentacja: klasa View
Odwołuje się do: Model
Zadania: Tworzy strukturę HTML i renderuje obiekty (echo $html). O tym co należy renderować decyduje Controller (zgłaszając np. chęć renderingu panelu zalogowanych użytkowników), natomiast jak to zrobić w szczegółach to kwestia View.
Przy okazji View dopytuje o niektóre dane Model. Np. gdy Controller rozkazuje wyrenderować panelu zalogowanych użytkowników, Controller nie troszczy się o przesyłanie serii danych (nie wie nawet które dane pokaże View). Zamiast tego View pobiera od Modelu listę użytkowników.
I tutaj ważne pytanie, gdyż nie wiem czy mam rację: to co napisałem w ostatnim akapicie kłóci się prezentowaną często w internecie wizją View, który nie powinien ponoć odnosić się do Modelu inaczej niż przez Controller.
Wydaje mi się jednak że nie jest to prawdą a jakimś spowszedniałym w necie uproszczeniem. Czy nie jest czasem tak, że w pełnym MVC View może odwoływać się do Modelu bezpośrednio (state query)? Na potwierdzenie znalazłem parę stron, napisane jest o tym m.in. na stronie java.sun i Oracle (razem ze schematem, na którym jest wyraźne Method Invocations z View do Model):
http://www.oracle.com/technetwork/articles/javase/mvc-136693.html

Nie wiem czy jest tak jak mówię, czy jestem w błędzie, czy może obie wersje są poprawne jako dwie alternatywne realizacje MVC.

No dobrze, na razie nieźle.
W index.php stworzymy Controller, ten stworzy Model, pobierze dane, stworzy View, wyda mu polecenie render (podczas którego View być może poprosi o coś Model) i strona zostanie wyrzucona z View poprzez echo $html.

Teraz natomiast dochodzi reszta funkcjonalności MVC: przede wszystkim reakcja na użytkownika.
Do tego zaprzęgam JQuery.
Z tego co wiem View powinien odebrać sygnały od użytkownika i przesłać je do Controller bez żadnej dodatkowej precyzyjnej analizy?
Czy będzie to zrealizowane poprzez podpięcie w View (osadzenie w kodzie wynikowym strony) obiektu JavaScript ViewJQUERY (czyli dołączenie innego widoku - jest to coś co należy do kompetencji View? I czy to w ogóle jest podpinanie drugiego widoku czy może coś innego?).
ViewJQUERY miałby za zadanie podpięcie wszystkich kliknięć i innych eventów do swoich funkcji, które zakodowują te eventy w formie ciągu tekstowego "źródło-id_źródła-wartość", np. "button-34-pressed", "card-55-dropped", a następnie wysłanie tego ciągu do obiektu Controller poprzez POST (AJAX) i oczekiwanie na odpowiedź asynchronicznie. Gdy odpowiedź nadejdzie (w formie listy komend tekstowych od Controller), ViewJQUERY je wykona (np. "render-panel-2" przetworzy w jakimś switchu i wyrenderuje panel, dopytując przy tym Model, również przez AJAX).

Dodatkowo dochodzi konieczność powiadamiania View o zmianie stanu obiektu Model, gdy np. drugi gracz wykona akcję (przez którą Controller zmieni Model).
Model musi więc jakoś poinformować View o swojej zmianie (powiadamianie Controller jest zbędne, bo w mojej grze na żadną zmianę bazy nie będzie on reagował, wszystkie będą dla niego znane).
Z racji że nie widzę rozwiązania by bezpośrednio z kodu PHP wywołanego przez użytkownika 1 skomunikować się z obiektem JavaScript istniejącym już na stronie na komputerze użytkownika 2, chciałem zrobić to poprzez ciągłą, powtarzającą się co jakiś czas pętlę w ViewJQUERY (kod JQuery dopytuje co pewien czas poprzez AJAX czy Model czasem się nie zmienił, jeśli tak, to prosi o listę zmian).
To rozwiązanie jednak nie do końca mi się podoba. Zamiast Modelu informującego View o zmianie stanu, mam tutaj View wiecznie pytający Model czy nastąpiła zmiana stanu, a to przecież zależność trochę odwrotna. Da się coś z tym zrobić?

Ostatnia uwaga: Controller będzie otrzymywał od Model obiekty, natomiast ViewJQUERY w zapytaniach do Model nie może posługiwać się obiektami PHP, dostanie więc ciągi tekstowe. Czy z tego powodu zrobić obiekt ModelAJAX który będzie różnił się od Model formatem zwracanych danych?
Wiem że w realnych zastosowaniach może występować wiele modeli, kontrolerów i widoków w jednym programie, ale nie mam pewności czy tutaj jest to zasadne.

W wyniku tego o co teraz roszerzyłem mój pierwotny koncept, Model uzyskuje odwołanie do View (state change), powstaje drugi widok (ViewJQUERY), być może drugi Model (ModelAJAX), a View uzyskuje odwołanie do Controller (event notify).

Na koniec mały schemat tego co tutaj opisałem (nie jest to formalny schemat UML, więc nie patrzcie na to co jest oznaczone jakim prostokątem i strzałką, to tylko wizualizacja, jak rysunek z Gimpa ;p ):

user image

0

Przy okazji View dopytuje o niektóre dane Model. Np. gdy Controller rozkazuje wyrenderować panelu zalogowanych użytkowników, Controller nie troszczy się o przesyłanie serii danych (nie wie nawet które dane pokaże View). Zamiast tego View pobiera od Modelu listę użytkowników.
I tutaj ważne pytanie, gdyż nie wiem czy mam rację: to co napisałem w ostatnim akapicie kłóci się prezentowaną często w internecie wizją View, który nie powinien ponoć odnosić się do Modelu inaczej niż przez Controller.

Większość MVC jakie oglądałem faktycznie działa w taki sposób, że dostaje pewne dane i już o nic nie dopytuje sobie kogokolwiek. Nie komunikuje się z Modelem, bo za to ma odpowiadać Kontroler. W bardziej ortodoksyjnej wersji - Widok ma być głupi, ma tylko wyświetlać, co dostanie. Najbardziej ortodoksyjne wersje zabraniają używania instrukcji if wewnątrz widoku.

Niemniej wzorce projektowe, także MVC, to nie są absolutnie idealne i cudowne sposoby na zrealizowanie czegoś - jeśli chcesz zrobić to w ten sposób, bo się tobie przyda, to zrób.

Z tego co wiem View powinien odebrać sygnały od użytkownika i przesłać je do Controller bez żadnej dodatkowej precyzyjnej analizy?

Tak bym zrobił - jQuery jako głupie odebranie tego, co user zrobił, a co konkretnie z tym zrobić zależy już od kontrolera.

Z racji że nie widzę rozwiązania by bezpośrednio z kodu PHP wywołanego przez użytkownika 1 skomunikować się z obiektem JavaScript istniejącym już na stronie na komputerze użytkownika 2, chciałem zrobić to poprzez ciągłą, powtarzającą się co jakiś czas pętlę w ViewJQUERY (kod JQuery dopytuje co pewien czas poprzez AJAX czy Model czasem się nie zmienił, jeśli tak, to prosi o listę zmian).
To rozwiązanie jednak nie do końca mi się podoba. Zamiast Modelu informującego View o zmianie stanu, mam tutaj View wiecznie pytający Model czy nastąpiła zmiana stanu, a to przecież zależność trochę odwrotna. Da się coś z tym zrobić?

Klasyczne rozwiązanie typu push - poczytaj o np. COMET http://en.wikipedia.org/wiki/Comet_%28programming%29, w przypadku nowoczesnych aplikacji HTML5 możesz przemyśleć np. WebSockets.

Ostatnia uwaga: Controller będzie otrzymywał od Model obiekty, natomiast ViewJQUERY w zapytaniach do Model nie może posługiwać się obiektami PHP, dostanie więc ciągi tekstowe. Czy z tego powodu zrobić obiekt ModelAJAX który będzie różnił się od Model formatem zwracanych danych?

Jeśli twoje obiekty przychodzące z modelu będą "głupie", w rodzaju Javowych POJO czy dotnetowych POCO, zawierające tylko dane, to możesz bezproblemowo posługiwać się jednymi obiektami, tylko transformując je na JSON dla potrzeb JavaScriptu.

1 użytkowników online, w tym zalogowanych: 0, gości: 1