Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Encje w Domain Driven Design
Forum PHP.pl > Forum > PHP > Object-oriented programming
Psajkus
Siema,
pisze do was z następującym problemem... zastanawiam się czy we dopuszczalne jest uzycie repozytorium w encji, (chodzi mi o metode setProfil)

  1. class UserEntity
  2. {
  3. //jakies atrybuty
  4.  
  5. //jakies metody
  6.  
  7. /** @var ProfilEntity */
  8. private $_oProfil;
  9.  
  10. public function addProfil(ProfilEntity $oProfilEntity)
  11. {
  12. $this->_oProfil = $oProfilEntity;
  13. }
  14.  
  15. public functin getProfil()
  16. {
  17. if(!isset($this->_oProfil)
  18. {
  19. return $this->setProfil();
  20. }
  21. else
  22. {
  23. return $this->_oProfil;
  24. }
  25. }
  26.  
  27.  
  28. private function setProfil()
  29. {
  30. $oProfilRepository = new ProfilRepository;
  31.  
  32. return $oProfilRepository->find();
  33. }
  34.  
  35.  
  36. }
  37.  
  38. class ProfilEntity
  39. {
  40. //jakies atrryburty i metody
  41. }
  42.  



Czy powinienem odwoływac się do repozytorium z poziomu encji czy raczej przeslać obiekt (wykorzystujac metode addProfil). Jak wy robicie?
LBO
Jest to dopuszczalne, aczkolwiek powinieneś to repozytorium przekazać do obiektu jak każdą inną zależność - poprzez wstrzyknięcie.

Inna sprawa, że w DDD bardzo ważne jest podejście Design By Contract i - w idealnym świecie programisty - zależność tego repozytorium powinna być zapodana jako interfejs.
Psajkus
A jak powinno wyglądać tworzenie encji dla kolekcji userow . Czy powinienem pobrać tablice danych w jednym zapytaniu joinem i na podstawioe nich stworzyc encje czy tworzyc kilka osobnych zapytań, np.:

1) zapytanie z joinem
  1. class UserRepository
  2. {
  3. //jakies atrybuty i metdody
  4.  
  5. public function findAll()
  6. {
  7. $aRows = $_usersDAO->findAll(); //zwraca uerow z profilami
  8. $aContener = array();
  9. foreach($aRows as $row)
  10. {
  11. $aUser = array('id' => $row['id'],
  12. 'imie' => $row['imie'],
  13. 'nazwisko' => $row['nazwisko'],
  14. 'profil_id' => $row['profil_id']
  15. );
  16.  
  17. $oUserEntity = new UserEntity($aUser);
  18.  
  19. $aProfil = array('id' => $row['profil_id'],
  20. 'telefon' => $row['telefon'],
  21. 'email' => $row['email']
  22. );
  23.  
  24. $oUserEntity->addProfil(new ProfilEntity($aProfil));
  25.  
  26. $aContener[] = $oUserEntity;
  27. }
  28.  
  29. return new UserCollection($aContener);
  30. }
  31.  
  32. }


2) zwykly select
  1. class UserRepository
  2. {
  3. //jakies atrybuty i metdody
  4.  
  5. public function findAll()
  6. {
  7. $aRows = $this->_usersDAO->findAll(); //zwraca userow
  8. $aContener = array();
  9. foreach($aRows as $row)
  10. {
  11. $aUser = array('id' => $row['id'],
  12. 'imie' => $row['imie'],
  13. 'nazwisko' => $row['nazwisko'],
  14. 'profil_id' => $row['profil_id']
  15. );
  16.  
  17. $oUserEntity = new UserEntity($aUser);
  18.  
  19. $oProfilEntity = $this->_oProfilRepository->find($row['profil_id'])
  20.  
  21. $oUserEntity->addProfil($oProfilEntity);
  22.  
  23. $aContener[] = $oUserEntity;
  24. }
  25.  
  26. return new UserCollection($aContener);
  27. }
  28.  
  29. }
  30.  
  31.  
  32. class ProfilRepository
  33. {
  34. //jakies atrybuty i metody
  35.  
  36. public function find($id)
  37. {
  38. $aRow = $this->_oProfilDao->find($id);
  39.  
  40. return new ProfilEntity($aRow);
  41. }
  42.  
  43. }


3) tworze kolekcje userow bez pobierania profilu i dopiero w widoku gdy wyswietlam userow wywoluje metdoe (z pierwszego postu) getProfil, ktora zwroci mi obiekt Profil.

4) jakieś inne rozwiązanie?


Crozin
Cytat
jakieś inne rozwiązanie?
Nie myślałeś nad wykorzystaniem Doctrine2 jako warstwy DAO? Architektura projektu pasuje idealnie do Twojego w dodatku oszczędziło by Ci to masę pracy.

Co do tego czy wykonać zapytanie SELECT z JOIN-em czy SELECT + n SELECT-ów. W zdecydowanej większości przypadków to pierwsze - bo będzie to po prostu wydajniejsze. To ostatnie możesz stosować np. w przypadku gdy pobierasz kolekcję 10 użytkowników, którą wyświetlasz jako jakąś listę ale dla przykładowo pierwszego elementu tej listy pozna nazwą użytkownika wyświetlasz też jakieś dane z jego profilu. Generalnie możesz poszukać sobie pod frazą "fetch eager lazy" - powinieneś znaleźć sporo materiałów bo jest to dosyć popularne zagadnienie.
Psajkus
Zastosowanie Doctrine na pewno pomogłoby w uzyskaniu efektu o który mi chodzi ale nie pomogłoby mi w zaspokojeniu ciekawości wink.gif. Chciałbym się dowiedzieć jak rozwiązuje się taki problem (poza tym w tym projekcie nie moge zastosować Doctrine).
Crozin
Pierwsze podejście to tzw. "eager fetching" czyli pobranie wszystkiego zawczasu. Jeżeli wiesz że będziesz potrzebować obiektu UserProfile dla (niemalże) każdego obiektu User powinieneś zastosować tą metodę.
Drugie podejście jest niemalże z definicji złe.
Trzecie podejście to tzw. "lazy fetching" czyli dobieranie obiektu UserProfile na żądanie (w momencie wywołania User::getProfile()). Przydatne gdy obiektu UserProfile będziesz potrzebować dla bardzo nielicznych obiektów User z całej kolekcji.

Jak już wcześniej powiedziałem więcej na temat obu metod znajdziesz w sieci.

Cytat
poza tym w tym projekcie nie moge zastosować Doctrine
Teraz to ja muszę zaspokoić ciekawość. wink.gif Dlaczego?
Psajkus
Projekt, który odziedziczyłem jest spitolony. I jest to duzy projekt wciaz rozwijany (chociaz mam nadzieje, ze dazy ku koncowi! wink.gif ) i zastosowanie Doctrine nie jest chyba najlepszym wyjsciem (a taki mix nie bylby wesoly). Zreszta Doctrine 2 pracuje na php 5.3 a serwis jest na serwerze php 5.2.


Dotychczas pobrane dane byly przekazywane bezposrednio do widoku w postaci tablicy. Ma to moze swoje plusy (jest wydajniejsze niz tworzenie wpierw obiektow) ale czy zgodne z OOP? Moim zdaniem powinno pracowac sie na obiektach.
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.