Post
#1
|
|
|
Grupa: Zarejestrowani Postów: 276 Pomógł: 3 Dołączył: 22.10.2003 Skąd: Wrocław Ostrzeżenie: (0%)
|
Zacząłem niedawno pisać na poważnie (w końcu praca duplomowa) w php5 i chciałbym się spytać czy to co napisałem, jest w pełni w duchu obiektowości. Może widzicie tam jakieś błędy, może macie jakieś wskazówki. Za wszelkie rady, spostrzeżenia, w szczególności te bardzo krytyczne, będę niezmiernie wdzięczny.
Gwoli wyjaśnienia, klasa ta ma odpowiadać za obsługę użytkownika: (*) dodawać (*) usuwać (*) uaktualniać (*) parsować poprawność wprowadzonych danych itp. A więc jeszcze raz proszę o jak najwięcej uwag i krytyki (ew. pochwały też przyjmuję (IMG:http://forum.php.pl/style_emoticons/default/biggrin.gif) )
Ten post edytował NuLL 28.11.2005, 23:06:30 |
|
|
|
![]() |
Post
#2
|
|
|
Grupa: Zarejestrowani Postów: 18 Pomógł: 0 Dołączył: 22.11.2005 Ostrzeżenie: (0%)
|
Witam Aztech!
Więc zaczynamy.. zajmijmy się duchem obiektowości ; ). Pierwsza zasada: każdy obiekt w systemie powinien mieć ściśle określoną odpowiedzialność, którą da się opisać jednym zdaniem. Powinien dostarczać implementacji jakiegoś zachowania lub struktury z dziedziny problemu. Jednym słowem musimy wystrzegać się tak zwanych god classes, przeciążonych nadmierną odpowiedzialnością i kodem. W tej kwestii poradziłeś sobie nie najgorzej, ale też daleko od ideału. Przyjrzyjmy się odpowiedzialności klasy, którą potrzebujesz stworzyć. Będzie to prawdopodobnie klasa opisująca obiekt użytkownika w Twojej aplikacji. Obiekt taki ma identyfikować pojedynczego użytkownika i dostarczać niezbędnych poprawnych danych o nim. Ponadto obiekt taki ma być utrwalany w bazie danych. W tym miejscu powinno nasunąć się już pytanie, czy obiekt użytkownika powinien też odpowiadać za utrwalanie siebie w bazie danych. Zgodnie z architekturą wielowarstwową obiekt użytkownika należy do warstwy logiki biznesowej, a zapisywanie do bazy to już odpowiedzialność warstwy danych. Aby oddzielić zupełnie te dwie odpowiedzialności musielibyśmy się zająć pojęciem ORM, którego niewielki fragment znajdziesz w przykładowym rozdziale z PoEAA http://www.awprofessional.com/articles/article.asp?p=30661. W twoim przypadku prawdopodobnie wystarczy prostsze rozwiązanie, które w zasadzie już zastosowałeś a nazywa się Active Record http://martinfowler.com/eaaCatalog/activeRecord.html. Jest wzorzec stosowany do tworzenia obiektów dziedziny, których struktura pokrywa się ze strukturą tabeli i które reprezentują pojedynczy rekord takiej tabeli. Oprócz podstawowej niewielkiej ilości logiki biznesowej, potrafią one utrwalać się w bazie danych. Skoro padła już nazwa jakiegoś wzorca, to możemy być pewni, że część odpowiedzialności prawdopodobnie uda nam się wyłączyć do klasy bazowej. http://www.daholygoat.com/jaws/html/index....ction=Page&id=8 Więc ustaliliśmy już kwestie utrwalania danych http://patternshare.org/default.aspx/Home.MF.ActiveRecord , postanowiliśmy wyodrębnić klasę bazową. Teraz zastanówmy się nad metodą wydobywania danych i konkretyzacji obiektów. Aby odciążyć trochę klasę użytkownika, odpowiedzialność za wyszukiwanie obiektów w bazie należałoby wyodrębnić do oddzielnego obiektu. Przy okazji zastosujemy Separatek Interface http://patternshare.org/default.aspx/Home....aratedInterface ukrywając implementację przed kodem klienta. W praktyce kod klienta będzie wyglądał mniej więcej tak:
Poświęćmy jeszcze chwilę tworzeniu obiektów User. Nie podoba mi się, że pozwalasz tworzyć puste obiekty nie wykorzystując konstruktora. Poza tym konstruktor jest metodą wykorzystywaną tylko w momencie inicjacji obiektu, więc wywołanie go w metodzie TUser:: clearData() jest błędem. Musisz odpowiedzieć sobie na pytanie jakie dane wymagane są do prawidłowego funkcjonowania obiektu User i zadbać o ich inicjalizację w czasie konstruowania obiektu. Prawdopodobnie nie może istnieć użytkownik, który się jakoś nie nazywa i nie ma podanego e-maila (który jest w wielu miejscach aplikacji wykorzystywany do komunikacji z nim). Konkretyzacja obiektu powinna wtedy wyglądać tak:
O enkapsulacji pamiętasz, kolejna ważna zasada zgodna z duchem obiektowości ; ). Mamy wszystkie składowe jako prywatne. Odpowiednie metody ustawiające wartości. Dodałbym jeszcze metody do pobierania potrzebnych wartości albo zrobił pożytek z metody __call() dla zmniejszenia ilości kodu (chociaż biorąc pod uwagę przejrzystość interfejsu, może jednak nie). Metody walidujące zawarł bym przy odpowiednich seterach. Sqle do modyfikowania rekordów zgonie ze wzorcem ActiveRecord zostają w klasie User. Wyszukujące wyłączamy. Dodajemy obiekt klucza stanowiący interpretację wzorca http://martinfowler.com/eaaCatalog/identityField.html, pilnujący tożsamości obiektów i powiązanych rekordów w bazie. Przy ładowaniu obiektów z bazy rejestrujemy je w IdentityMap http://martinfowler.com/eaaCatalog/identityMap.html dostępnej za pomocą jakiegoś rejestru, zabezpieczającej naszą aplikację przed wielokrotnymi odwołaniami do bazy danych i tworzeniem wielu instancji tego samego obiektu. Na koniec dodajemy kontrolę nad modyfikacją naszych obiektów w czasie ich życia i automatyczne utrwalanie zmian w bazie danych, za co odpowiedzialnością obarczamy „obiekt jednostki pracy”. Natomiast kolekcje obiektów obsługujemy (z wykorzystaniem opóźnionego ładowania) za pomocą specjalnego obiektu implementującego interfejs jednego z iteratorów SPL (tak jak to proponuje Matt Zandstra w „php 5 Objects, Patterns, and Practice” http://www.amazon.com/exec/obidos/ASIN/159...018931-2571322) …i czy projektowanie obiektowe nie jest poezją!? : ) Dodatkowe uwagi: 1. Obsługa błędów w Twojej klasie jest fatalna. Skoro korzystasz z PHP5 i chcesz w pełni wykorzystywać jego możliwości obiektowe, to tak jak sugerowali przedmówcy powinieneś używać wyjątków. Dobra lektura na początek: http://www.zend.com/php5/articles/php5-exceptions.php 2. Pilnuj typu zmiennych, to że luźne typowanie w php daje dużo możliwości, nie zabezpiecza go przed wieloma problemami związanymi z tym. Ułatwieniem mogą być dobrze przygotowany standardy pisania kodu. Ja na przykład jak dodaje do nazw zmiennych przedrostek wskazujący jakiego typu jest zmienna. Poza tym lepiej dokumentuj swój kod, a w szczególności API. http://phpdoc.org/ 3. Dodatkowo skoro PHP5 skoro nowy model obiektowy to sugeruję PDO jako abstrakcję dostępu do danych, zamiast AdoDb. Tak to z grubsza mogłyby wyglądać zależności klas. Tobie pozostawiam implementację i życzę miłej zabawy. (IMG:http://blazej.niepije.org/php.pl/user.png) |
|
|
|
Aztech Czy to jest poprawne - w duchu obiektowości? 28.11.2005, 22:48:44
Kinool konstrukto nic szczegolnego nie robi wiec chyba zr... 29.11.2005, 00:39:43
dr_bonzo Nie wiem czy masz taka metode (troche ich tam duuz... 29.11.2005, 00:50:18
Aztech @Kinool: Faktycznie na samej górze jest 0 1 a pote... 29.11.2005, 01:27:08
chmolu Krzysztofie, gdzieś ty się chował do tej pory? Don... 29.11.2005, 16:06:13
Aztech Dzięki informacjom Krzysztofa wypożyczyłem sobie k... 29.11.2005, 18:04:14
ActivePlayer troszeczke nie rozumiem schematu... albo z nazewni... 29.11.2005, 20:47:09
Ludvik [PHP] pobierz, plaintext <?php public function ... 29.11.2005, 21:12:21
krzysztof f. Cytat(ActivePlayer @ 2005-11-29 19:47:09)tros... 30.11.2005, 10:05:47
ActivePlayer Cytat(krzysztof f. @ 2005-11-30 10:05:47)Cyta... 30.11.2005, 10:51:54
krzysztof f. Active Record jak wspominałem jest najprostszym wz... 30.11.2005, 12:00:14
kula Witam wszystkich.
Przeczytalem te wszystkie oszer... 20.01.2006, 06:16:48
NuLL CytatJak ma sie sprawa jesli chodzi o pozniejszą z... 20.01.2006, 13:12:49 ![]() ![]() |
|
Aktualny czas: 28.12.2025 - 12:29 |