Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Konstrukcja obiektów
Forum PHP.pl > Forum > PHP > Object-oriented programming
athabus
Witam,

zastanawiam się jak inicjować obiekty o wielu właściwościach. Dajmy na to mam produkt, który posiada 20 własności takich jak cena, nazwa, kategoria, marka itd itp.

Czy lepiej przekazać dużą tablicę asocjacyjną do konstruktora, czy zainicjować pusty obiekt i potem wywołać serię poleceń typu $produtk->setName() itd.

A może jest jeszcze jakiś inny patent?
TomASS
pomysł z tablicą jest chyba lepszy. Ładujesz dane do tablicy a później przekazujesz ją do obiektu. Zresztą właściwości w obiekcie też wygodnie trzymać w jednej tablicy.
Wygodna jest też w użyciu metoda magiczna __set
athabus
Jeśli chodzi o przechowywanie właściwości obiektu, to raczej nie lubię tablic. Trudno się w nich połapać i sensownie je kontrolować - chociaż oczywiście to tylko moje zdanie. Znacznie bardziej preferuje obiekty. Czyli np. grupowanie podobnych wlasnosci w obiekt. W ten sposób mogę narzucać kontrolę parametrów wejściowych - żeby np. cena była jako liczba z danego zakresu itp. Przykładowo produkt wygląda u mnie np. tak

objPrice - obiekt ceny, czyli cena netto, stawka vat itd.
objFeaturesCollection - kolekcja cech produktu
objPromotion - informacje na temat promocji produkt- kiedy się zaczyna, kiedy kończy, opis, warunki itp.

Tablice też mają swoje plusy, zresztą też często je stosuje - wszystko zależy od sytuacji.

Co do metody __get - oj tak, też ją lubie biggrin.gif Choć wolałbym aby wprowadzono Properties tak jak w C#

Wracając jednak do tematu. Przekazanie tablicy jako parametru wejściowego jest kłopotliwe - łatwo o błędy. Zawsze się wkurzam, gdy pracuje nad takim większym obiektem bo usuwanie literówek i różnic w nazwach parametrów zajmuje mi sporo czasu angrysmiley.gif Z drugiej strony inicjowanie wszystkiego ręcznie też jest upierdliwe... Może ktoś zna sposób w jaki można to zautomatyzować.
batman
Nie jestem pewien czy dobrze zrozumiałem Twój problem. Wydaje mi się, że potrzebujesz czegoś takiego:

1. Klasa produkt - ogólne info o produkcie.
2. Klasa cena - info o cenie (nieważne jaka cena - tylko netto, brutto, vat, itp)
3. Klasa paramatry - dodatkowe paramtry (tutaj możesz utworzyć tablicę: nazwa_parametru=>wartość)

Jedynym problem pozostaje połączenei tych klas. Można określić klasę 1. jako klasę główną, po której dziedziczą pozostałe. Do tego w klasach 2, 3 i 4 zastosować wzorzec singleton (wówczas masz pewność, iż chodzi o ten sam obiekt).

Rozwiązanie wydaje się być nawet dobre. Na chwilę obecną znajduję tylko jedno "ale". Co z pamięcią? Jeśli obiekt będzie duży (baaaardzo dużo parametrów, "niezdrowe iteracje winksmiley.jpg ", itp), wówczas może zabraknąć pamięci. (Sądzę jednak, że nie powinno być to problemem)
athabus
Batman - niestety nie o to mi chodzi.

Zastanawiam się nad tym jak inicjuje się obiekty z wieloma parametrami. To o czym Ty piszesz to już następny etap, czyli przechowywanie wszystkiego wewnątrz obiektu. Chodzi mi o to co zrobić - czy przekazać dużą tablicę do konstruktora, ze wszystkimi parametrami, czy raczej zrobić to tak jak np. w ooh forms, że tworzysz podstawę obiektu a potem "ustawiasz go" wywołując kolejne funkcje w stylu
  1. <?php
  2. $textBox->setDefaultValue('5') itd.
  3. ?>


Jeśli chodzi o przechowywanie parametrów to tu akurat robie mniej więcej tak jak mówisz - ale nie dziedziczę obiektów tylko tworze z nich kompozycję - IMHO dziedziczenie w takiej sytuacji to nie najlepszy pomysł.
TomASS
Z tego co mówisz, to rzeczywiście przechowywanie danych w obiektach ma dla Ciebie sens - dużo w tym racji. Możesz połączyć tablice z obiektami, masz np.

objCena i jako parametr przekazujesz do konstruktora tablicę z danymi (cena, stawka VAT, akcyza, itp..), tak jak mówisz obiekt ten od razu sprawdzał poprawność danych, idąc dalej np objRozmiar z przekazywaną tablicą parametrów może od razu sprawdzać czy wymiar nie jest np. liczbą ujemną.
faster
Ja zawsze staram się robić tak, że tworzę metodę statyczną (albo konstruktor) ze wszystkimi parametrami wymaganymi dla obiektu. Dzięki temu, jak dodam kolejny parametr to metoda mi się wywali przy wywołaniu ze gdzieś tam nie mam wszystkich parametrów. Przez to mam pewność, że nie pominąłem żadnego istotengo parametru. Problem faktycznie pojawia się przy dużej ich ilości. Setowanie po kolei ma ten minus, że nigdy nie dojdziesz do tego czy masz wszystkie potrzebne czy nie (chyba że przy zapisie czy innej akcji bedziesz sprawdzał). Ale właściwie co przeszkadza, że będziesz miał metode z 20 parametrami smile.gif? Będzie trochę nieczytelne i tyle.

pozdro
athabus
faster - też tak kiedyś robiłem, ale powaliły mnie konstruktory z parametrami na 3 linie i dlatego z tego zrezygnowałem:( .Teraz z reguły robie tak, że przekazuje tablicę - tyle, że tu faktycznie trzeba się napracować, żeby wszystko było łatwo modyfikowalne w przyszłości.

Za tablicą też przemawia jedna rzecz - a mianowicie można w obiekcie dao stworzyc takie zapytanie żeby można było wynik selecta od razu przekazać jako tablica inicjująca obiekt

np. Select produkty.productId as id, marki.idMarki as marka ... itd. -> wtedy po fetchowaniu do tablicy asocjacyjnej od razu masz gotową tablicę inicjującą obiekt.

Obie te metody przy większych obiektach są jak dla mnie jak to kiedyś mawiał jeden znajomy: "jak sznurkiem łatane i smarkiem klejone" snitch.gif Problem w tym, że nic lepszego nie przychodzi mi do głowy sad.gif
batman
Widzę dwa rozwiązania Twojego problemu.

Pierwszy - przekazujesz do konstruktora tablicę - wtym przypadku musisz pamiętać by wszystkie potrzebne parametry się w niej znalazły, a następnie w konstruktorze sprawdzasz poprawność tablicy.

Drugi - tworzysz "pusty" obiekt i dla każdego parametru tworzysz metody do dodawania i wyciągania danych. W metodach tych możesz również sprawdzać poprawność danych. Ewentualnie możesz robić taj jak napisane zostało przez TomASS. A mianowicie __set i __get.

Jak dla mnie lepszą metodą bedzię metoda druga - masz większą kontrolę nad tym co wprowadzasz do obiektu.
Turgon
a nie prościej __call ? I wtedy tylko parsowanie co z daną metodą trza zrobić smile.gif
athabus
batman - też wydaje mi się, że przy dużych obiektach druga metoda jest lepsza. Stosowałem tablice, ale w gotowych rozwiązaniach widać jednak tendencję -> utwórz pusty/początkowy obiekt i następnie uzupełnij go parametrami. Chyba spróbuję stosować to rozwiązanie w przyszłości. Co prawda wymaga to pamiętania co trzeba "dodać" do obiektu, ale chyba jest to wygodniejsze niż stosowanie megatablic gdzie łatwo o pomyłki, które później trudno wyszukać. W obu przypadkach na pewno i tak trzeba zrobić metodę testującą poprawność obiektu

Nie wiem czy masz dokładnie to co ja na myśli, ale chyba najwygodniej będzie utworzyć kilka metod typu setPrice itd. Raczej nie będę korzystał z metody __set - jeśli chodzi o dane konfiguracyjne, to wolę mieć wszystko jawnie podeklarowane, z odpowiednimi metodami wymuszającymi odpowiednie typu parametrów itp. Przy wielu parametrach do ustawienia __set staje się bardzo nieczytelnym rozwiązaniem - ale to tylko moja opinia. Pozatym jawna deklaracja metod dostępowych daje możliwość podpowiadania składni w edytorze - nie wiem jak wy, ale ja z moją sklerozą bardzo cenię sobie ten feature biggrin.gif

Jakby ktoś jeszcze miał ciekawe sugestie to chętnie wysłucham.
faster
A ja bym się jeszcze raz zastanowił, czy nie da się podzielić klasy na mniejsze i te mniejsze zawierać jako atrybuty tej 'dużej' klasy. Przy tworzeniu dużej klasy (obiektu) podajemy w param. konstruktora obiekty pomniejszych składowych tej klasy. Jedna ważna zaleta -> w konstruktorze dużej klasy możesz wtresy sprawdzać typy pomniejszych obiektów.

Czy możesz podać przykład klasy, która stwarza Ci problem?

Pozdro
DeyV
Ja również jestem zwolennikiem przesyłania danych "zapakowanych" w małe obiekty.
W znaczący sposób ułatwia to sprawdzanie poprawności wprowadzanych danych, a także odwoływanie się do nich.

Chciałbym jednak zwrócić uwagę na jedną rzecz. Bezsensowne wydaje mi się w takiej sytuacji korzystanie z _get i _set - ponieważ sami pozbywamy się mechanizmu do wykrywania literówek w nazwach atrybutów.

Nie lubię jednak tworzenia dziesiątek metod typu
setName( $sName ){
$this ->sName = $sName;
}
Dlatego zazwyczaj rezygnuję z ich tworzenia wszędzie tam, gdzie nie są potrzebne jakiekolwiek operacje wykonywane podczas pobierania lub wprowadzania danych.
Zamiast tego deklaruję te atrybuty jako publiczne, a dzięki temu przy włączonym E_ALL odrazu dostaję informację o próbie utworzenia atrybutu, który nie został zdefiniowany.

ps. No i ma się wartości domyślne winksmiley.jpg
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.