Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Tworzenie obiektów w zgodzie z mvc
Forum PHP.pl > Forum > PHP
Fixus
Witam mam mały czysto teoretyczny problem.

Chodzi o wzorzec MVC.

Załóżmy, że mamy OBIEKT typu Human
Każdy human ma właściwości jak $name, $surname i $age

i załóżmy, że OBIEKT typu human ma metodę służącą do pobrania wszystkich zapisanych ludzi zbazy danych

getAllHumans()

Teraz czy jeżeli bezpośrodnie w tym obiekcie odwołam się do bazy będzie to zgodne z tym wzorcem projektowym? Czy trzeba odwołać się do modelu który połączy się z bazą i to pobierze ?
askone
Hej

Wszystko zależy czym jest obiekt Human... Czy to kontroler, czy widok, czy może właśnie model... Skoro pytasz to pewnie to kontroler więc lepiej jak zdefiniujesz odpowiedni model i poprzez niego zapytasz źródło danych np. bazę, plik xml o odpowiednie dane.

Bezpośrednie odwołanie do bazy z poziomu kontrolera zadziała, ale nie będzie zgodne z MVC.

Pozdrawiam
trylas
Przyjmujac ze:
php - Infrastruktura - Logika zachowań - infrastruktura komunikacyjna pomiędzy modelem widokiem i kontrolerem
phpm - model - klasy php - serce aplikacji
phtml - widok i kontroler - wizualizacja zarówno efektów działania jak i danych wprowadzanych przez użytkownikaoraz interfejs dla danych wprowadzanych przez użytkownika

plik .php (strona sterująca)nigdy nie powinien zawierac zapytan SQL ani kodu html
plik .phpm (klasy) nie powinien zawierac kodu html
plik .phtml (szablony) nie powinien zawierac zapytan SQL i powinbien korzystac tylko z podstawowej skladni PHP (for , if ,while)

pozdr
Fixus
hmm to chyba źle do tego podchodzę gdyż dla mnie obiekt Human to po prostu OBIEKT smile.gif Typ danych jak Integer czy String

cała przykładowa aplikacja jest sterowana przez kontroler w klasie powiedzmy Controller.php który po żądaniu użytkownika ma zwrócić wszystkie obiekty typu Human
askone
Hej

Twój Controller.php to główny kontroler aplikacji tzw Bootstrap, FrontController. Jeśli chcesz się uczyć o MVC to polecam analizę kodu frameworka Kohana - sam w ten sposób zdobywałem wiedzę o tym wzorcu projektowym. Dodatkowo poznajesz framework...

Pozdro
Nattfarinn
Cytat(Fixus @ 2.11.2009, 11:03:06 ) *
Witam mam mały czysto teoretyczny problem.

Chodzi o wzorzec MVC.

Załóżmy, że mamy OBIEKT typu Human
Każdy human ma właściwości jak $name, $surname i $age

i załóżmy, że OBIEKT typu human ma metodę służącą do pobrania wszystkich zapisanych ludzi zbazy danych

getAllHumans()

Teraz czy jeżeli bezpośrodnie w tym obiekcie odwołam się do bazy będzie to zgodne z tym wzorcem projektowym? Czy trzeba odwołać się do modelu który połączy się z bazą i to pobierze ?

Wszystko zależy od tego kto na ile swobody sobie pozwala, ale wg ścisłego trzymania się zasad MVC będzie to działanie niezgodne z założeniami wzorca. Metoda getAllHumans() samym swoim działaniem jest typowym getterem zarezerwowanym raczej dla modelu. Można też zapytać, dlaczego obiekt klasy Human ma posiadać metodę getAllHumans()? Czasem (zawsze?) lepiej jest odseparować od siebie części kodu i wydzielić z nich osobne klasy (w tym przypadku agregować obiekt modelu). Może wydawać się to pozornie mniej wygodne pod względem pisania, ale takie działanie prowadzi do zachowania przejrzystości kodu i rzeczywistego odseparowania M od V od C winksmiley.jpg. No i unika się nieświadomego stosowania antywzorca (God Object).
Fixus
@Nattfarinn - z tego co mówisz to zgodnie z MVC obiekt jako struktura/typ danych powinien być podzielony na model i co ?
czym jest ta druga część:)
Nattfarinn
Cytat(Fixus @ 2.11.2009, 13:30:47 ) *
@Nattfarinn - z tego co mówisz to zgodnie z MVC obiekt jako struktura/typ danych powinien być podzielony na model i co ?
czym jest ta druga część:)

Nie chcę żeby to zabrzmiało jako coś oczywistego, ale obiekt powinien odpowiadać dokładnie za to, do czego go przeznaczyliśmy. Jeśli posiadasz klase Human, charakteryzującą potencjalnego człowieka - to ta klasa powinna odpowiadać tylko i wyłącznie za to. I z tego powodu metoda getAllHumans() nie powinna być częścią klasy Human. To nie tylko zasady MVC, ale generalnie zasady OOP które nieświadomie się łamie dla własnej wygody. Nie ma w tym łamaniu nic złego właściwie, bo to leży tylko w kwestii piszącego, czy chce się trzymać wzorców czy nie smile.gif

Mówiąc jaśniej: obiekt jako struktura/typ danych nie powinien być dzielony wcale, ale nie powinny być mu również przypisywane metody które go nie dotyczą. W podanym przez Ciebie przypadku, wygląda na to, że obiekt Human mógłby z powodzeniem być zwracany przez fabrykę (załóżmy dla przykładu: klasę Population) pełniącą funkcję modelu (lub z modelu korzystjącą). Niektóre rzeczy w programowaniu można (i bardzo to pomaga) tłumaczyć na rzeczywistych przypadkach: Człowiek [class Human] nie zna wszystkich ludzi na ziemi i to nie jego powinno się o to pytać [::getAllHumans()]. smile.gif
Fixus
i chyba tej ostatniej wypowiedzi potrzebowałem smile.gif Sporo mi to rozjaśniło.

Do tej pory uważałem, że obiekt to obiekt a mvc służy do zarządzania aplikacją, jej sterowania i nie ma nic związanego z klasami takimi właśnie jak np. human czy population. Teraz widzę, że faktycznie Population może być modelem z racji tego, że jest bardzo ogólna i nie ma prawie żadnego innego zastosowania jak komunikacja i zwracania danych.

z drugiej strony zauważam, że takie rygorystyczne trzymanie się wzorców obiektowych czasami mija się z celem - takie jest moje zdanie smile.gif

//edit

może to już niepotrzebne drążenie tematu ale jeszcze jedno pytanie - mam nadzieję, że ostatnie
Jeden człowiek nie zna wszystkich ludzi, ale co z nim samym
czy w klasie Human implementacja takiej metody
  1. public Human getHuman(int id) {
  2. sql = "select * from tabela wher eid = 'id'";
  3. }


będzie zgodna z mvc ? smile.gif (to jest oczywiście pseudokod tongue.gif )
}
marcio
Powtarzam jak bedzie to w modelu to bedzie zgodne.
Nattfarinn
Cytat(marcio @ 2.11.2009, 15:01:14 ) *
Powtarzam jak bedzie to w modelu to bedzie zgodne.

Czyli możesz napisać wprost, że zgodne nie jest, bo autor w pierwszym poście pytał przecież:
Cytat(Fixus @ 2.11.2009, 11:03:06 ) *
Teraz czy jeżeli bezpośrodnie w tym obiekcie odwołam się do bazy będzie to zgodne z tym wzorcem projektowym? Czy trzeba odwołać się do modelu który połączy się z bazą i to pobierze ?


Ale wracając do Twojego ostatniego pytania, tak jak nie wprost powiedział kolega: Ze wzorcem MVC zgodne nie będzie. Najpoprawniej i najwydajniej byłoby tworzyć obiekty klasy Human z już istniejących, pobranych przez odpowiedni model danych. Tworzenie obiektu, który dane pobiera sobie indywidualnie przez różnorakie metody (chociaż konstruktor byłby bardzo odpowiedni) ma niewielką rację bytu i nie widzę większego sensu tworzenia takich elementów. Owszem, jako pytanie teoretycznie przykład dobry, ale uczulam na takie zagrania smile.gif. Widzę, że największe problemy masz ze zrozumieniem czym właściwie jest wzorzec MVC i jak go zastosować. Po krótce mogę powiedzieć Ci tylko tyle, że to obiekty będące Modelami powinny wykonywać wszelkie operacje we/wy na danych z zewnętrznych źródeł (tj. baza danych, plik etc) i dopiero same dane przekazywać poszczególnym, wyspecjalizowanym obiektom. Model działa tutaj jako pośrednik i chociaż składnię może mieć niewiele bardziej skomplikowaną od Twojego przykładu i na dobrą sprawę jest zupełnie zbędny (obiektowość też jest przecież zbędna) - ujednolica projekt i sprowadza do stosowania metod modelu zamiast każdorazowego operowania zapytaniami czy plikami. To tyle jeśli chodzi o sam model. Literatury elektronicznej o MVC google podpowie o wiele więcej niż jestem w stanie sobie wyobrazić - dlatego nie będę próbował się z Google siłować winksmiley.jpg.

Podsumowując: nawet jeśli przykład...
  1. class Human {
  2. public $id = 12345;
  3. (...)
  4. public function getHuman($id) {
  5. $sql = "select * from tabela wher eid = 'id'";
  6. return (...);
  7. }
  8. }

... nie jest poprawny, to ten już jest:
  1. class PopulationModel {
  2. public function getHumanById($id) {
  3. $sql = "select * from tabela wher eid = 'id'";
  4. return (...);
  5. }
  6. }
  7.  
  8. class Human {
  9. public $id = 12345;
  10. public function getHuman($id) {
  11. $population = new PopulationModel();
  12. return $population->getHumanById($this->id);
  13. }
  14. }

Nie skupiam się w tym momencie nad sensownością, ale zachowaniem funkcjonalności przy jednoczesnej zgodności z MVC.
Fixus
Dzięki bardzo wszystkim za pomoc szczególnie tobie Nattfarinn teraz już rozwiałeś chyba wszystkie moje wątpliwości smile.gif

Pozdrawiam
thek
To może i ja się dorzucę nieco do rozjaśnienia tematu. Przyrównaj się do... siebie jako obiektu klasy Human winksmiley.jpg To co tak naprawdę wiesz tyczy tylko Ciebie. Nawet nabliższe Ci osoby maą pewn tajemnice (własności typu private), a reszta to publiczne. Udostępniają Ci ewentualnie pewne kanały łączności (metody publczne), porozumienia, dzięki którym możesz im coś przekazać lub coś się o nich dowiedzieć. W innych językach jest jeszze ciekawiej, ponieważ możesz tworzyć funkcje zaprzyjaźnione, które posiadają dostęp do pewnych danych, normalnie niedostępnych dla ogółu smile.gif Możesz więc co najwyżej kombinować z funkcją modelu, która poda Ci wszystkie dane o innym obiekcie, ale tylko te dostępne publicznie i jeszcze by było weselej, tylko gdy o nie jawnie zapytasz. Obiektowe programowanie ma na celu odwzorowanie otaczającej nas rzeczywistości na język programowania. stąd klasa Human ma swoje dane, może zapytać o czyjeś dane publiczne, ale nie może wyciągać nic innego jeśli nie jest w jakiejś zależności ściślejszej z innym obiektem tej klasy. Dzięki temu nie wiesz co robi sąsiad dopóki sam ci nie powie podczas rozmowy. Możesz najwyżej zrobić klasę Police ( biggrin.gif ), która będzie miała wgląd do pewnych "kartotekowych" danych (choćby logi lub wpisy w bazie) jakiegoś obiektu lub Court ( winksmiley.jpg ), która nałoży ograniczenia na obiekty klasy Human tongue.gif
cojack
A ja też dorzucę dwa grosze na temat tej sprawy, gdyż ostatnio opisywałem ją na swoim blogu, pod hasłem MVC w PHP cz.2.

Kontroler to kontroler, nie może posiadać zapytań do bazy danych. Nattfarinn podał jak najbardziej dobry przykład, tylko że ja bym się jeszcze uparł co do nazewnictwa klas, aczkolwiek to już inna bajka, ale mimo wszystko ja bym klasę module nazwał HumanModel, dlaczego? Bo w tej klasie modelu dla kontrolera Human będziesz posiadał inne metody niż np pobieranie ile jest wszystkich ludzi. Dlatego nazwa klasy trochę nie będzie odpowiadać jej zastosowaniom. A jeden model dla jednego kontrolera. Amen. No i oczywiście rozumiem że ten przykład dwóch klas w jednym "pliku" to tak tylko na pokaz.
Nattfarinn
Cytat(cojack @ 3.11.2009, 10:39:40 ) *
ja bym się jeszcze uparł co do nazewnictwa klas, aczkolwiek to już inna bajka, ale mimo wszystko ja bym klasę module nazwał HumanModel

Ja również, ale dałem takie a nie inne nazewnictwo i taką a nie inną klasę, żeby zobrazować różnicę pomiędzy modelem a warstwą logiki biznesowej bez sugerowania, że do każdej klasy powinien istnieć osobny model smile.gif.

Cytat(cojack @ 3.11.2009, 10:39:40 ) *
No i oczywiście rozumiem że ten przykład dwóch klas w jednym "pliku" to tak tylko na pokaz.

Oczywiście, ale nie będę się rozdrabniał na poszczególne tagi przy podawaniu trywialnego przykładu smile.gif
thek
Ogólne założenia Twojego wpisu cojack do którego podałeś linka są zgodne z moimi za wyjątkiem jednego -> 1 model - 1 kontroler - 1 widok. Oczywiście abstrahując od sytuacji gdy któregoś nie trzeba (po co w klasie logowania widok?) pozostaje jeszcze coś takiego jak zbiór uniwersalnych metod danego projektu. Może to być model zawierający metody używane w wielu innych, które na swój sposób mogły by stać się helperem lub biblioteką w późniejszych projektach lub dalszej fazie życia projektu. Ale równie dobrze mógłby to być pewien widok, który jest związany z często powtarzanymi akcjami. Choćby widok maila. Jeśli serwis jest ujednolicony to wystarczy jeden widok odpowiadający za sformatowanie maila do wysyłki i tylko go wypełniamy danymi. Nie musi on być przypisany do konkretnej klasy. To tylko taki mój mały wtręt do całości, która jest jak najbardziej prawidłowa.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.