Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] OOP - pytanie o konstruktor
Forum PHP.pl > Forum > Przedszkole
kreatiff
Witam. Zaczynam raczkować w OOP, i natrafiłem na taką wątpliwość.
Czy mógłbym prosić o prostą wykładnię, które podejście jest bardziej "prawidłowe" dla poniższego przykładu (o ile którekolwiek jest prawidłowe wink.gif)?
Chodzi mi o to, czy dla zasady konstruktor powinien być możliwie jak najmniej skomplikowany i dalsze zadania na atrybutach powinno się wykonywać w osobnych metodach, czy nic nie stoi na przeszkodzie, by już w konstruktorze wykonywać działania?

Co lepsze? Ta klasa:
  1. class A {
  2. private $zmienna = '';
  3. private $info = '';
  4.  
  5. public function __construct($zmienna) {
  6. $this->zmienna = $zmienna;
  7. $this->info = $info;
  8. if ( $this->zmienna == 'test' ) $this->info = 'ok';
  9. else $this->info = 'coś nie gra';
  10. }
  11.  
  12. public function wyswietl() {
  13. return $this->info;
  14. }
  15. }
czy może ta klasa:
  1. class A {
  2. private $zmienna = '';
  3. private $info = '';
  4.  
  5. public function __construct($zmienna) {
  6. $this->zmienna = $zmienna;
  7. $this->info = $info;
  8. }
  9.  
  10. private function sprawdz() {
  11. if ( $this->zmienna == 'test' ) return 'ok';
  12. else return 'coś nie gra';
  13. }
  14.  
  15. public function wyswietl() {
  16. return $this->sprawdz();
  17. }
  18. }
Proszę nie zwracać uwagi na bezsensowny przykład, możliwy do rozwiązania w 1 linijce w sposób proceduralny. No chyba, że za pomocą klasy ten problem powinien być rozwiązany w kompletnie inny sposób. Wynik końcowy ma za zadanie zwrócić 'ok', albo 'coś nie gra', w zależności od parametru początkowego przy tworzeniu obiektu klasy A.
  1. $a = new A('test');
  2. echo 'Info: '. $a->wyswietl(); // wyświetli 'ok'
skowron-line
Dość głupi przykład podałeś i cieżko powiedzieć. Musisz pamietać że ilu programistów tyle podejść do tematu
Ale jeżeli chodzi o 2 przykład to powinno to bardziej tak wyglądać
  1. class A {
  2. private $zmienna = '';
  3. private $info = '';
  4.  
  5. public function __construct($zmienna) {
  6. $this->zmienna = $zmienna;
  7. $this->info = $info;
  8. }
  9.  
  10. private function sprawdz() {
  11. return $this->zmienna == 'test';
  12. }
  13.  
  14. public function wyswietl() {
  15. return $this->sprawdz() == true ? 'ok' : 'coś nie gra';
  16. }
  17. }
Sephirus
Nic nie stoi na przeszkodzie by sprawdzać niektóre rzeczy w konstruktorze o ile nie jest za dużo. Nie ma ogólnych zasad co do tego co powinien robić konstruktor poza tym, że ma spełniać rolę inicjowania obiektu i wykonania działań wymaganych do poprawnego działania klasy.

Z punktu widzenia wydajności jednak dużo lepiej jest jeśli ograniczy się rolę konstruktora do minimum a nawet pójdzie w stronę leniwości. W twoim przykładzie (jest on wzorcowy wręcz) druga opcja jest prawidłowa - dlaczego? Dlatego że sama klasa po załadowaniu nie musi mieć informacji o tym czy jakieś info jest ok czy nie. W momencie odwołania powinno to być sprawdzane tak jak w przykładzie drugim.

Nie jest to jednak taka oczywista oczywistość i wszystko zależy. Bo jeśli będziesz się odwoływał do tej metody sprawdzającej bardzo często (kilka razy na odpalenie skryptu) to lepiej przerzucić to do konstruktora. Ewentualnie zapisać stan po pierwszym odpytaniu i dalej zwracać już zapisany stan (leniwość).

Musisz sam wyczuć jaką drogą pójść smile.gif

Jeśli masz klasę, która jest spora i odwołujesz się rzadko do jej metod - staraj się aby dane metody posiadały więcej kodu - wówczas jeśli nie zostaną wywołane uzyskasz na wydajności.

W przypadku gdy masz klasę w której non-stop odpytujesz jakąś metodę lepiej przygotować jej dane na początku i przeliczać ewentualnie te, które muszą być przeliczone (na przykład jak się poda jakieś argumenty).

A teraz prosty przykład.

Klasa obsługi bazy danych.

Pytanie czy w konstruktorze powinno się tworzyć połączenie z bazą?

Załóżmy że tak. Wówczas w jakimś modelu na przykład zawsze na zaś masz gotowy obiekt obsługi bazy nawet jak z niego nie korzystasz. Po co więc się łączyć?

W takim razie łączmy się z bazą przy pierwszym odpytaniu jakiejś metody obiektu. Zyskamy tyle, że jak baza nie będzie odpytywana nie będzie połączenia. Co stracimy? To że przy każdej metodzie musimy sprawdzać czy jest połączenie bo jeśli nie ma musimy się najpierw połączyć.

Nie ma prostej odpowiedzi smile.gif Wszystko zależy od tego w jaki sposób będziesz to wykorzystywał. Szkoda że PHP nie udostępnia leniwych funkcji itp... to by się przydało smile.gif
skleps
Cytat(kreatiff @ 28.11.2012, 16:37:19 ) *
Chodzi mi o to, czy dla zasady konstruktor powinien być możliwie jak najmniej skomplikowany i dalsze zadania na atrybutach powinno się wykonywać w osobnych metodach, czy nic nie stoi na przeszkodzie, by już w konstruktorze wykonywać działania?


Tak, ale bez fanatyzmu - a ilu programistów tyle podejść.
Raczej lepszy jest przykład drugi - bo przecież i tak musisz mieć metody, żeby odczytać/zapisać informacje w polach obiektu, więc lepiej się do nich odwołać (do tych metod) niż drugi raz pisać w konstruktorze to samo.
Z kolei konstruktor to świetne miejsce, żeby ustalić wartość stałych obiektu, bo nie będzie i tak metod do ich zapisu, a jedynie do odczytania (w końcu po co tworzyć metodę, która będzie wywołana jeden raz z konstruktora).
kreatiff
Ze głupi przykład to wiem. Chodziło o pokazanie co mam na myśli.
Rozumiem, ze to:
  1. return $this->zmienna == 'test';

zwraca boolean?
(dodano: musi zwracać true/false, bo co innego by miało zwracać wink.gif)

Dziękuję Sephirus za wyjaśnienia. Przyznam szczerze, że po przerobieniu rozdziału PHP i MySQL Welling/Thomson o obiektowym, niewiele z tego zajarzyłem. Dopiero przykłady w Internecie mi nieco rozjaśniły.
I właśnie takie posty, które rozwiewają wątpliwości, których nie znajdziesz tak łatwo w książce, bo ilu programistów, tyle rozwiązań.
Na samym początku przygody z obiektowym miałem w ogóle problem by wyłapać jego sens. Zbyt długo uczyłem się proceduralnego podejścia do php, zamiast od razu chwytać się OOP.
Teraz zaczyna mi się to porządkować, staje się sensowne i logiczne. Ale właśnie, wygląda mi na to, że trzeba wypracować sobie swoje podejście, bo nie ma na to gotowego schematu. A to wymaga ćwiczeń.
Oczywiście wątpliwości się mnożą wraz z kolejnymi przykładami, które próbuję sobie rozwiązać czy stworzyć. No ale nikt nie mówił, że będzie łatwo smile.gif

Dziękuję wszystkim za pomoc.
skleps
Cytat(kreatiff @ 28.11.2012, 17:16:24 ) *
Na samym początku przygody z obiektowym miałem w ogóle problem by wyłapać jego sens. Zbyt długo uczyłem się proceduralnego podejścia do php, zamiast od razu chwytać się OOP.


I dobrze, bo IMHO fanatyczne podejście do obiektówki i wciskanie jej na siłę wszędzie tez nie jest dobre.
To trochę jak strzelanie z amaty do komara smile.gif

Ja już widziałem skrypt, który robił coś wybitnie długo, zrobiony był obiektowo i skomplikowanie (tak na oko, bo nie chciało mi się tego analizować), wykonywał się strasznie długo - kilka minut.
Ja to samo zrobiłem 1 selectem do bazy i kilkunastoma linijkami kodu - skrypt pracował kilka sekund.
Fakt że twórca obiektu zapewne nie raczył przetestowac obiektu na większej ilości danych,
a zabawa polegała na "wypluciu" z bazy danych kilkunastu tysięcy produktów do pliku XML smile.gif


kreatiff
W zasadzie ja nie planuję pracować zawodowo jako programista php (za stary jestem już raczej, młode wilki zaczynające w wieku nastu lat są całe lata świetlne przede mną), bardziej potrzebuję go do moich własnych potrzeb (nie aż tak rozbudowanych jak u programistów zawodowych), dlatego pewnie nieraz jeszcze będę produkował sobie kod proceduralny.
Ale skoro jest coś takiego jak OOP, to dlaczego by nie spróbować.

A, że przy okazji rozjaśniania mi się idei OOP naszedł mnie pomysł przerobienia swojego skryptu, to jest dodatkowa motywacja.
Skrypt wydaje mi się jest wręcz idealny by go rozpisać jako klasę z kolejnymi prywatnymi i publicznymi metodami, zamiast dwóch ogromnych funkcji.
No ale już na samym początku stanąłem przed problemem jak w pierwszym poście.

No nic, spróbuję to sobie przepisać na klasę i jak się uda to może za rok, czy dwa będę się śmiał z głupot jakie popisałem biggrin.gif
skleps
Cytat(kreatiff @ 28.11.2012, 17:50:06 ) *
W zasadzie ja nie planuję pracować zawodowo jako programista php (za stary jestem już raczej, młode wilki zaczynające w wieku nastu lat są całe lata świetlne przede mną), bardziej potrzebuję go do moich własnych potrzeb (nie aż tak rozbudowanych jak u programistów zawodowych), dlatego pewnie nieraz jeszcze będę produkował sobie kod proceduralny.


To tak jak ja smile.gif
OOP używam gdy coś ma być spore spore lub uniwersalne lub często używane w różnych rzeczach.
A drobiazgi które nie mają być uniwersalne tłukę proceduralnie, bo szybciej toto zakodować smile.gif
skowron-line
Cytat(kreatiff @ 28.11.2012, 17:50:06 ) *
W zasadzie ja nie planuję pracować zawodowo jako programista php (za stary jestem już raczej,

Ile masz lat że tak twierdzisz questionmark.gif
kreatiff
30. I niestety kilka błędnych decyzji w przeszłości co do wyboru własnej kariery zawodowej...
Ale kto wie co tam w przyszłości mnie czeka. A do emerytury coraz dalej wink.gif
skowron-line
30 to nie tak źle. Jeżeli się przyłożysz to za rok o tej porze będziesz rasowym programistą.
kreatiff
Dziękuję za wlanie w człowieka dodatkowej wiary smile.gif
Rok mi nie starczy najpewniej, ale i na laurach nie zamierzam spocząć.
Coś tam z tego php się wie i szkoda byłoby to tak po prostu zakończyć.
wNogachSpisz
Najlepiej jeśli konstruktor nie robi nic.
Wtedy zyskujesz możliwość załadowania obiektu i dodaniu mu atrybutów w dowolnej chwili.
Dzięki temu soft daje się łatwiej testować.
skleps
Cytat(kreatiff @ 28.11.2012, 20:12:00 ) *
30.


To ja się może nie będę odzywał....
Ale mam trochę więcej niż 30 lat
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.