Człowiek uczy się całe życie.
Od kilku lat wszystkie prace, które wykonuję bazują na szkielecie, który rozbudowuję przez cały ten czas.
Szkielet ten polega na tym, że mam moduły (jeden moduł - jedna klasa), w których zdefiniowane są poszczególne zadania wykonywane przez moduł (jedno zadanie - jedna metoda). Na przykład za dodanie artykułu do bazy odpowiedzialna jest jedna z metod odpowiedniej klasy.
Jedna z zasad OOP mówi, że jeżeli moduł A chce żeby było zrobione coś co dotyczy modułu B to najlepiej niech moduł B zrobi to sam bo on wie najlepiej jak to zrobić. Przykład ilustrjący tę zasade w moim przypadku:
Jest moduł do zarządzania grupami użytkowników. Jednym z jego zadań jest definiowanie praw dostępu.
Prawa są wyswietlane dla każdego zainstalowanego modułu w formie rozwijanego drzewka, w którym użytkownik zaznacza odpowiednie checkboxy. Aby skonstruować to drzewko moduł zarządzajacy grupami includuje każdy moduł. Każdy z includowanych modułów zawiera metodę, która otzrymuje referencę do obiektu symblizującego generowane drzewko. Zadaniem tej metody jest dodanie do drzewka checkboxów konkretnego modułu.
Wszystko działa pięknie, chuczy, buczy, lata i gada.
Tylko jest jeden problem. Każdy z modułów zawiera 500 - 1000 linijek kodu. jeżeli modułów jest powiedzmy 20 to aby wygenerować to drzewko potrzeba przeparsować całą masękodu po to aby w ażdym dołączonym module skorzystać z jednej metody zawierającej pięć linijek.
Masakra!
I oto myślę sobie: "Kurcze MVC pomoże. Każdy moduł rozbiję na szereg akcji, widoków i elementów modułu i będzie fajnie. Przy każdym żądaniu będę includował tylko to co trzeba."
No i faktycznie rozbiłem kilka przykładowych modułów zgodnie z paradygmatem MVC i jest super.
Tylko natrafiłem na problem, z którym nie bardzo umiem dać sobie radę.
Chodzi o formularze w panelu administracyjnym np. do dodawania użytkowników, artykułów etc.)
Generalnie zasada jest taka:
1. Trzeba dodać użytkownika - ładuje się widok z formularzem.
2. User wypełnia formularz, klika guzik
3. uruchamiana jest akcja dodajaca usera. Jęzli formularz był wypełniony dobrze to dane są zapisywane i ładowany jest widok z listą użytkowników. Jeśli zaś dane zostały wpisane źle to ładowany jest ponownie widok z formularzem.
Teoria piękna (jak to zwykle z teoriami bywa), natomiast z praktyką trohe gorzej.
Przy okazji budowania dotychczasowych stron stworzyłem sobie piekny zestaw klas służący do generowania i walidacji formlarzy. Z perspektywy OOP aż miło mi sie na to patrzy bo to jedna z lepszych rzeczy jaka zobiłem.
Mam zestaw klas Form_Select, Form_TextBox itd. (co robią nie będę tłumaczył bo to oczywste).
Służą one do tego aby do obiektu klasy Form_Form (reprezentującej formularz) dodać odpowiednie pola.
Form_Form jest kontenerem dla obiektów klas dziedziczących po klasie Form_Pole (takich jak wymieniony wcześniej Form_Select etc.). Każda klasa reprezentująca pole formularza przyjmuje też obiekt odpowiadający za walidację pola, np. Waidacja_IntegerDodatnie, Walidacja_StringWymagane, Walidacja_Godzina. Te obiekty są odpowiedzialne za to aby to co user wpisze w pole było tym co ma wpisać.
Następnie formularz jest wyświetlany przez wywołanie jego metody construct(). Tworzy ona podstawowy szkielet html i wywołuje metodę construct() dla wszystkich obiektów reprezentujących pola tak aby się wyświetliły w formularzu.
Kiedy user wypełni formularz i go wyśle tworzony jest znowu jego obiekt aby go zwalidować metodą waliduj(). Zwraca ona true jęli formularz był wypełniony prawidłowo.
Jak widać obiekt formularza jest tworzony dwukrotnie (raz aby go wyświetliś i drugi aby zwalidować).
Stworzyłem więc metodę prywatną w module aby generowała odpowiedni obiekt klasy Form_Form (bo po co kod kopiować).
I teraz niech mi ktoś powie gdzie ja mam ja umieścić uwzględniając wzorzec MVC?
a) czemu nie w akcji?
bo pomimo że Form_Form zawiera metodę waliduj(), która jest odpowiednia dla akcji to zawiera metodę construct(), która wyświetla formularz.
czemu nie w widoku?
bo pomimo że Form_Form zawiera metodę construct(), która jest odpowiednia dla widoku to zawiera metodę waliduj(), która waliduje formularz.
c) czemu nie w modelu?
bo pomimo, że do wygenerowania formularza potrzebne są informacje z bazy danych (np. lista kategorii, do których może należeć dodawany artykuł) to są tez tam metody construct() i waliduj(), które są odpowiednie dla widoku i akcji.
I co z tym fantem zrobić?
Wszystko spełnia zasady dotyczące tego co mówią podręczniki uczące OOP. Wszystko jest zgodne ze zdrowym rozsądkiem (przynajmniej moim) i wszystkiego sie wygodnie używa. Tylko do MVC jakoś tak daleko... no i to, że praktycznie za każdym wywołaniem skryptu trzeba includować dużo tysięcy linii kodu.
Gdyby ktoś miał pomysł jak rozwiązać mój dylemat z formularzami to bardzo prosze o pomoc.
Tym, którzy doczytali do końca gratuluję.