Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

2 Stron V   1 2 >  
Reply to this topicStart new topic
> Metody magiczne, Czy jest sens stosowania?
JoShiMa
post 25.02.2011, 10:13:09
Post #1





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

Ostrzeżenie: (0%)
-----


dla mnie to chore wywoływac metodę magiczną wewnątrz klasy.


--------------------
Go to the top of the page
+Quote Post
wookieb
post 25.02.2011, 10:14:05
Post #2





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Nieprawda. Jest sens, jeżeli niesie to za sobą jakieś dodatkowe operacje.


--------------------
Go to the top of the page
+Quote Post
JoShiMa
post 25.02.2011, 10:15:16
Post #3





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

Ostrzeżenie: (0%)
-----


Cytat(wookieb @ 25.02.2011, 10:14:05 ) *
Nieprawda. Jest sens, jeżeli niesie to za sobą jakieś dodatkowe operacje.

Nie. Nie ma sensu bo to samo mozna zrobić dowolna metodą choćby prywatną.

Ten post edytował JoShiMa 25.02.2011, 10:15:37


--------------------
Go to the top of the page
+Quote Post
wookieb
post 25.02.2011, 10:18:58
Post #4





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Przykład
  1. class test {
  2. private $variable1 = 'test';
  3. private $variable2;
  4. public function setVariable1($value) {
  5. $this->variable1 = $value;
  6. $this->variable2 = null;
  7. }
  8.  
  9. public function setVariable2($value) {
  10. $this->variable2 = $value;
  11. $this->variable1 = null;
  12. }
  13. }

Widzisz sens? To teraz wyobraź sobie, że zastąpienie tych dwóch metod można zastąpić jedną, magiczną __set.
Jak najbardziej jest sens takiego działania.
Powód edycji: [wookieb]:


--------------------
Go to the top of the page
+Quote Post
Crozin
post 25.02.2011, 10:20:52
Post #5





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Sensowność metod magicznych sama w sobie jest sprawą mocno dyskusyjną. Ale nie widzę problemu by używać ich z wnętrza obiektu - sytuacja jest przecież dokładnie taka sama jak na zewnątrz.

EDIT:
Cytat
Jak najbardziej jest sens takiego działania.
No właśnie nie ma. smile.gif Bo kod staje się nielogiczny (nagle prymitywna operacja przypisania ($abc->def = 'xyz') zaczyna wykonywać jakieś poboczne operacje. A przecież można by utworzyć zwykłą metodę, która by jasno określała co robi. Co za różnica czy $abc->dev = .. czy $abc->set('dev', ...). Poza tym, że pierwszy zapis jest strasznie kłopotliwy.

Ten post edytował Crozin 25.02.2011, 10:24:37
Go to the top of the page
+Quote Post
wookieb
post 25.02.2011, 10:24:34
Post #6





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Cytat(Crozin @ 25.02.2011, 10:20:52 ) *
Sensowność metod magicznych sama w sobie jest sprawą mocno dyskusyjną.

Słyszałem o tym ale nadal nie widzę powodu by widzieć w tym jakiekolwiek przeciwwskazania.


--------------------
Go to the top of the page
+Quote Post
JoShiMa
post 25.02.2011, 10:26:48
Post #7





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

Ostrzeżenie: (0%)
-----


Cytat(wookieb @ 25.02.2011, 10:18:58 ) *
Przykład
  1. class test {
  2. private $variable1 = 'test';
  3. private $variable2;
  4. public function setVariable1($value) {
  5. $this->variable1 = $value;
  6. $this->variable2 = null;
  7. }
  8.  
  9. public function setVariable2($value) {
  10. $this->variable2 = $value;
  11. $this->variable1 = null;
  12. }
  13. }

Widzisz sens? To teraz wyobraź sobie, że zastąpienie tych dwóch metod można zastąpić jedną, magiczną __set.
Jak najbardziej jest sens takiego działania.


Zaręczam Ci, że to samo co możesz umieścić w finkcji __set() możesz umieścić w dowolnej metodzie. Skoro możesz ten kod zwinąć do metody __set() możesz go również zwinąć i umieścić w dowolnej metodzie. funkcje magiczne nie są aż tak magiczne jak się niektórym wydaje.



--------------------
Go to the top of the page
+Quote Post
Daiquiri
post 25.02.2011, 10:28:22
Post #8





Grupa: Administratorzy
Postów: 1 552
Pomógł: 211
Dołączył: 7.07.2009
Skąd: NJ




Nie widzę przeszkód w stosowaniu metod magicznych, jeżeli ktoś ma ochotę - zwłaszcza że widzę ich zasadność. Będzie jednak (z tego co wiem) problem z Reflection API?
Go to the top of the page
+Quote Post
wookieb
post 25.02.2011, 10:33:46
Post #9





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Chyba jednak nie zdajecie sobie sprawy co mówicie. Metody __set i __get umożliwiają zapewnienie dodatkowej logiki w aplikacji tak samo jak "set*" i "get*". Co jeżeli mam 100 właściwości w klasie? 200 metod get i set? Strasznie słabe. Wolę sobie zrobić metodę magiczną __call w połączeniu __set i __get i mieć identyczna funkcjonalność w znaczniej bardziej efektywny sposób.

Mówiąc, że takie operacje można zastąpić dowolną inna metodą jest trochę utrudnianiem losu samemu sobie.
Podam doskonały przykład. W C++ są dostępne wektory. Dzięki przeciążeniu operatorów (coś ala "metoda magiczna") można na nich w bardzo łatwy sposób wykonywać operacje matematycze. Będziemy rezygnować z tak niewyobrażalnej wygody tylko po to, żeby "jasno" było widać w kodzie "set"? Straszne słabe.

Dla jasności przykładu.
Przykładowy wektor to (1,2). Dodanie do niego drugiego wektora (2,3) następuje w ten sposób. (1 + 2, 2 + 3) = (3, 5)

Sam stosuje w większości set i get ale to tylko daltego by zapewnić sobie wywołania łańcuchowe. Przy dużej ilości właściwości to nie ma żadnego sensu.


--------------------
Go to the top of the page
+Quote Post
Crozin
post 25.02.2011, 10:35:58
Post #10





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Cytat
Słyszałem o tym ale nadal nie widzę powodu by widzieć w tym jakiekolwiek przeciwwskazania.
Co przemawia za metodami magicznymi?
- W pewnych przypadkach pozwalają uratować się przed utratą wstecznej kompatybilności.

Dodatkowe "zalety":
- krótszy kod - bo to właśnie różnica 4 znaków na linię świadczy o jakości kodu.

Wady:
- Kod staje się nielogiczny. Nagle operacje, które nie powinny mieć miejsca stają się możliwe i są kompletnie nieprzewidywalne.
- Brak wsparcia ze strony IDE.
- Niezbyt ciekawa sytuacja przy debuggowaniu/próbie zrozumienia kodu.
- Problemy przy dokumentowaniu kodu.
- A przede wszystkim... kod staje się magiczny czyli tracimy jego klarowność i jednoznaczność/oczywistość.

Cytat
Będzie jednak (z tego co wiem) problem z Reflection API?
Całe szczęście z poziomu refleksji nie istnieje coś takiego. Metody magiczne same w sobie niczym nie różnią się od tych normalnych. Jedynie interpreter przed wyrzuceniem błędu o braku metody/właściwości sprawdza czy aby przypadkiem jakaś magiczna metoda, która mogła by się tym zająć nie istnieje. Możesz odwoływać się do nich jak do każdej innej metody: $obj->__call('abc', array('def'));

EDIT:
Cytat
Co jeżeli mam 100 właściwości w klasie? 200 metod get i set? Strasznie słabe.
Strasznie słabe to jest posiadanie takiej ilości właściwości. Poza tym przecież mamy coś takiego jak... tablice i kolekcje.
  1. public function set($key, $value) {
  2. $this->myArray[$key] = $value;
  3. }
__set spisze się jedynie w przypadku, gdy dla wszystkich przypadków użycia będziemy mieli względnie taki sam algorytm. Bo jeżeli każdą zmienną miałbyś traktować indywidualnie skończyłbyś z dwoma setkami IFów.

Co do przeciążania operatorów. Faktycznie w przypadku wielu struktur matematycznych są fajne. Fajnie jest zrobić sobie $myVector - 5 czy $myMatrix * $myMatrix. Ale jedyne co zyskujemy to różnicę kilku znaków ($myVector.substract(5) VS $myVector - 5) a w zamian otrzymujemy mechanizm przez którego powstają potworki których zasada działania jest kompletnie nielogiczna/niezrozumiała/magiczna.
To samo spotkało metody magiczne w PHP - są one używane w nieprawidłowy sposób. Chyba tylko po to by ich używać.

Ten post edytował Crozin 25.02.2011, 10:43:22
Go to the top of the page
+Quote Post
wookieb
post 25.02.2011, 10:44:36
Post #11





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Cytat(Crozin @ 25.02.2011, 10:35:58 ) *
Wady:
- Kod staje się nielogiczny. Nagle operacje, które nie powinny mieć miejsca stają się możliwe i są kompletnie nieprzewidywalne.

No nie. Wszystko ma swoje zadania. I ktoś kto projektuje klasę wie o co chodzi. Potem odpowiednio udokumentować i po problemie.
Podałem Ci przykład wyżej. Jeżeli zmieniasz jedną wartość to druga się usuwa. Po co użytkownik po swojej stronie miałby to sam sprawdzać? A co gorsza kontrolować w takim przypadku kolejność wywołania "zmiany" właściwości? Jest to jak najbardziej wygodne. Poza tym "set" również może w takim wypadku spowodować Twoim zdaniem "nielogiczne" zachowania.

Cytat
- Brak wsparcia ze strony IDE.

Netbeans
Kod
@property-read
@property-write
@property
@method

I jechana.

Cytat
- Niezbyt ciekawa sytuacja przy debuggowaniu/próbie zrozumienia kodu.

To faktycznie jest troszkę utrudnione
Cytat
- Problemy przy dokumentowaniu kodu.

Czytaj wyżej. To, że PHPDOC chyba takich rzeczy nie wspiera to jego problem.

Cytat
- A przede wszystkim... kod staje się magiczny czyli tracimy jego klarowność i jednoznaczność/oczywistość.

Argument zbity wyżej.

P.S. Wydzielam.


--------------------
Go to the top of the page
+Quote Post
Crozin
post 25.02.2011, 11:04:03
Post #12





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


Przede wszystkim powinieneś myśleć nie o autorze klasy, a o jej użytkowniku (nawet jeżeli jest to sam autor).
  1. echo $obj->varA; // varA
  2. echo $obj->varB; // varB
  3.  
  4. $obj->varA = 'test';
  5. echo $obj->varB; // NULL - wtf?
Przecież nigdzie nie zmieniłem żadnej wartości, jedynie zmieniłem wartość właściwości varA. Usuwam przypisanie wartości - zwraca mi ładnie "varB", przywracam przypisanie wartości jakiejś innej właściwości - zwraca mi NULLa.
W taki oto prosty sposób kod staje się magiczny. O ile w przypadku gdy sam jesteś autorem i użytkownikiem dasz sobie bez problemu radę. Ale wyobraź sobie zewnętrzną bibliotekę z piętnastoma takimi obiektami, każdy z jakimś "zwalniającym nas z potrzebny niepotrzebnego pisania" potworkiem pod postacią __set(). A później dochodzą Ci kolejne 4 biblioteki z kolejnymi potworkami - idzie się pochlastać w końcu.

Przykład drugi:
  1. echo $obj->getVarA(); // varA
  2. echo $obj->getVarB(); // varB
  3.  
  4. $obj->setVarA('test');
  5. echo $obj->getVarB(); // NULL - wtf?
Ale reakcja jest trochę inna - od razu wiadomo, że jedynym możliwym miejscem zmiany wartości varB jest metoda setVarA().

Trzeba jeszcze zaznaczyć, że nie jest to najlepszy kod. 10 getterów/setterów najparwdopodobniej powinno być zastąpionych jedną parą, a operacje powinny być wykonywane na tablicy.

Trzeba pamiętać, że cała magiczność ogranicza się do zamiany $obj->__set('var', $value) na $obj->var = $value. Naprawdę nie zyskujemy niczego poza kilkoma znaczkami.

Ahh.. mogłaby to być jeszcze metoda getVarB() (która przykładowo zwracałaby raz varB a raz NULL w zależności od ilości wywołań) - ale wtedy do pierwszego listingu należałoby też dodać wtf spowodowane przez __get() wink.gif
Go to the top of the page
+Quote Post
wookieb
post 25.02.2011, 12:26:59
Post #13





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




To może podam przykład z życia.
  1. class Resource
  2. {
  3.  
  4. /**
  5.  * Cache aplikacji
  6.  * @var Cache
  7.  */
  8. private $cache
  9.  
  10. /**
  11.  * Flaga czy używać cache
  12.  * @var boolean
  13.  */
  14. private $useCache = false;
  15.  
  16. public function __set($name, $value) {
  17. if ($name == 'cache' && $value instanceof Cache) {
  18. $this->cache = $value;
  19. $this->useCache = true; // sporna linijka
  20. } else $this->useCache = (bool)$value;
  21. }
  22.  
  23. public function __get($name) {
  24. if (isset($this->$name)) return $this->$name;
  25. }
  26. }

Pomińmy piękno tego kodu.
Dlaczego linijka oznaczona komentarzem nie miałaby istnieć?
Przecież z logicznego punktu widzenia skoro podajemy obiekt Cache do klasy to nie po to, żeby sobie był, tylko żeby z niego skorzystać? Nielogicznym byłoby w tym przypadku wymuszenie konieczności ustawienia flagi używana Cache.
A co gdybym dopisał opcję ustawiania flagi $useCache na false w przypadku usunięcia obiektu Cache?
To jest jak najbardziej logiczne zachowanie.
Klasa to nie tablica, której przypisujemy po prostu wartości do właściwości. Służy do wykonywania konkretnych zadań w których mieści się kontrola nad wartościami w jej wnętrzu.
Drugi przykład.
  1. class Session {
  2. /**
  3.  * uzytkownik przypisany do sesji
  4.  * @var User
  5.  */
  6. private $user;
  7.  
  8. private $id;
  9. public function __set($name, $value) {
  10. switch($name) {
  11. case 'id':
  12. $this->id = $value;
  13. if (!$value) $this->user = null; // usuwamy obiekt użytkownika skoro usunięto id sesji
  14. }
  15. }
  16. }

Dlaczego nie miałbym usunąć obiektu użytkownika skoro nie ma id sesji co oznacza, że nie powinno jej być.

Oczywiście identyczne zachowania można zrobić za pomocą get i set, tylko co stoi na przeszkodzi aby wykorzystać w tym celu magię? Dla mnie jest to tylko różnica "przyzwyczajeń", niczego więcej.


--------------------
Go to the top of the page
+Quote Post
thek
post 25.02.2011, 12:34:21
Post #14





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




To ja dorzucę jeszcze moją uwagę. Funkcje magiczne, jako wewnętrzne klasy mają dostęp do wszystkiego i są widoczne/ tworzą funkcje jako public z zewnątrz. W efekcie Wywołanie nieistniejącego settera/gettera, daje nam dostęp do wszystkich atrybutów, niezależnie od ich specyfikatora dostępu (!). W tym momencie poszło się paść private i protected. Wszystko jest widoczne dla wszystkich. Stworzenie więc jednego do wszystkiego to zakładanie sobie sznura na szyję.


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
wookieb
post 25.02.2011, 12:37:50
Post #15





Grupa: Moderatorzy
Postów: 8 989
Pomógł: 1550
Dołączył: 8.08.2008
Skąd: Słupsk/Gdańsk




Cytat(thek @ 25.02.2011, 12:34:21 ) *
To ja dorzucę jeszcze moją uwagę. Funkcje magiczne, jako wewnętrzne klasy mają dostęp do wszystkiego i są widoczne/ tworzą funkcje jako public z zewnątrz. W efekcie Wywołanie nieistniejącego settera/gettera, daje nam dostęp do wszystkich atrybutów, niezależnie od ich specyfikatora dostępu (!).

Zastanów się z 10 razy i napisz post jeszcze raz. Poza tym __get i __set nie służy jedynie do uzyskiwania dostępu do zmiennych prywatnych i chronionych.


--------------------
Go to the top of the page
+Quote Post
cojack
post 25.02.2011, 12:43:05
Post #16





Grupa: Zarejestrowani
Postów: 898
Pomógł: 80
Dołączył: 31.05.2008

Ostrzeżenie: (20%)
X----


Dla mnie jest rzeczą okrutną że nie można __set i __get ustawić na private ;(


--------------------
cojack blog - mój blog (na jakiś czas off).
"jak czegoś nie wiem, to nie myślę że wiem" - moja domena
Go to the top of the page
+Quote Post
Eby
post 25.02.2011, 13:06:08
Post #17





Grupa: Zarejestrowani
Postów: 6
Pomógł: 1
Dołączył: 16.10.2007

Ostrzeżenie: (0%)
-----


Z mojej perspektywy to trochę tak jakby sprzeczać czy lepiej użyć "return" czy "echo".
Jednego i drugiego należy używać tam gdzie to jest potrzebne (ułatwia życie, tworzy kod łatwiejszy do modyfikacji itp).
Np. używając metod magicznych do view helperów (niezbyt ładny przykład) :
  1. echo helper->tag('a', 'more', array('href'=>'controller::action','class'=>'link'));

oczywiście zamiast tego (bo to magiczne, nieładne i nieczytelne) można użyć:
  1. $taghelper = new View_Helper_Tag();
  2. $taghelper->setTag('a');
  3. $taghelper->setContent('more');
  4. $taghelper->setParam('href', array('controller'=>'controller','action'=>'action'));
  5. $taghelper->setParam('class', 'link');
  6. echo $taghelper->returnHtml();

Moim zdaniem pierwszego kodu używa się łatwiej i szybciej niż drugiego - zwłaszcza w sytuacji gdy mamy 700 linii w szablonie i nie chcemy z jakichś powodów tworzyć ich tam 4000.
Tego samego helpera i metod magicznych można użyć w klasie która służy do budowania całego grida czy formularza lub w samej klasie helper by nie dublować kodu.
Teraz gdy dochodzi dodatkowy rodzaj helpera, wystarczy dodać odpowiednią klasę obsługi a samego wrapera już nie trzeba ruszać.
Oczywiście możemy zrobić fabrykę która zwraca odpowiedni rodzaj helpera i wtedy nie mamy części kłopotów, ale pojawiają się inne - każde podejście ma swoje wady i zalety i składni języka należy użyć w zależności od potrzeb (i naszych preferencji).
Go to the top of the page
+Quote Post
thek
post 25.02.2011, 13:39:36
Post #18





Grupa: Moderatorzy
Postów: 4 362
Pomógł: 714
Dołączył: 12.02.2009
Skąd: Jak się położę tak leżę :D




Cytat(wookieb @ 25.02.2011, 12:37:50 ) *
Zastanów się z 10 razy i napisz post jeszcze raz. Poza tym __get i __set nie służy jedynie do uzyskiwania dostępu do zmiennych prywatnych i chronionych.
Wookieb... Dobrze napisałem. Używając __set i __get, tworzymy metodę, która udostępnia wszystkim na zewnątrz atrybuty klasy. Jeśli byśmy tego nie chcieli w pełni, to musimy to ograniczać już wewnątrz definicji tej metody. Przykładowo mamy wspomnianą przez Ciebie klasę z 200 atrybutami, w tym 5 private i 5 protected, z których nie wszystkie chcemy udostępniać na zewnątrz. Co robimy? Sięgamy po refleksję by sprawdzić, czy dany atrybut jest na "black-liście"? Fajnie... Kosztem naszej wygody (linie kodu) zarżynamy wydajnościowo aplikację, która oprócz magii jeszcze po refleksję sięga.

O to mi chodziło w przykładzie. __set i __get oraz inna magia daje dostęp nie zawsze w sposób jaki byśmy chcieli ostatecznie uzyskać i musimy nad tym panować. Poza tym powiedz mi jedno wookieb: "Czy __set i __get ruszają do działania jeśli atrybut jest public?", bo jak dla mnie nie. Sam kwantyfikator zezwala na grzebanie mi w zmiennych public, więc o czym my mówimy tutaj? O pisaniu settera i gettera magicznego dla czegoś, co i tak nie będzie użyte? Bo klasa mając składową publiczną odda nam ją od razu i odwołanie się do magii nie nastąpi nigdy?


Dla mnie większy sens mają te funkcje tylko gdy chcemy się zająć wyłapywaniem błędów własnych, a nie posługiwanie tym w sposób nadmierny. To tak jak z mechanizmem wyjątków. Powstał by prościej obsługiwać sytuacje wyjątkowe, a ludzie używają tego do kontroli przepływu danych w aplikacji niczym wariant IF, który dodatkowo trudniej wysypać bo jest "inteligentniejszy".

PS... Tak wiem... Pozwala utworzyć i odczytywać w locie obiektowi nieistniejące składowe choćby, ale IMHO takie posługiwanie się wynika ze zrypanego procesu projektowego. Źle zaprojektowana aplikacja po to sięgnie. Dobrze przemyślana nie potrzebuje takich łat.


--------------------
Najpierw był manual... Jeśli tam nie zawarto słów mądrości to zapytaj wszechwiedzącego Google zadając mu własciwe pytania. A jeśli i on milczy to Twój problem nie istnieje :D
Go to the top of the page
+Quote Post
JoShiMa
post 25.02.2011, 13:41:30
Post #19





Grupa: Zarejestrowani
Postów: 1 374
Pomógł: 149
Dołączył: 1.03.2006

Ostrzeżenie: (0%)
-----


Cytat(wookieb @ 25.02.2011, 10:33:46 ) *
Chyba jednak nie zdajecie sobie sprawy co mówicie. Metody __set i __get umożliwiają zapewnienie dodatkowej logiki w aplikacji tak samo jak "set*" i "get*". Co jeżeli mam 100 właściwości w klasie? 200 metod get i set? Strasznie słabe. Wolę sobie zrobić metodę magiczną __call w połączeniu __set i __get i mieć identyczna funkcjonalność w znaczniej bardziej efektywny sposób.

Ale co Ci uniemożliwia wstawienie kodu, który umieściłbyś w __set() wstawić do jednej metody set i nie mieć ich 100?

  1. function set($varName,$value){
  2. $this->$varName = $value;
  3. }


Zadziała nawet jeśli nie istnieje taki parametr klasy, bo stworzy go w locie.

I po co Ci funkcja magiczna?


Nie twierdzę, że funkcje magiczne są zupełnie do bani. Jednak używanie ich wewnątrz klasy to totalny bezsens.

Ten post edytował JoShiMa 25.02.2011, 13:46:31


--------------------
Go to the top of the page
+Quote Post
Crozin
post 25.02.2011, 13:51:03
Post #20





Grupa: Zarejestrowani
Postów: 6 476
Pomógł: 1306
Dołączył: 6.08.2006
Skąd: Kraków

Ostrzeżenie: (0%)
-----


@Eby: Jak można porównywać return do echo? Poza tym ten przykład to też wiele z tematem wspólnego nie ma. Jak już to powinieneś porównać takie zapisy:
  1. echo $helper->tag('a', 'more', array('href'=>'controller::action','class'=>'link'));
  2. echo $helper->helper('tag', 'a', 'more', array('href'=>'controller::action','class'=>'link'));
  3. echo $helper->helper('tag', array('a', 'more', array('href'=>'controller::action','class'=>'link')));
Chociaż osobiście wszystkie uważam za niezbyt trafne.

@wookieb: Co do pierwszego listingu... jest on chyba niekompletny bo kompletnie nie trzyma się kupy - albo ja nie potrafię sobie wyobrazić co ten kod miałby robić (konkretniej metoda __set w przypadku gdy podajemy klucz inny niż "cache"). Poza tym już uwidacznia się tu pierwszy "wtf". Na metodę __set() spada obowiązek wykonywania wielu zadań - czy nie lepiej by było:
  1. function setCache(CacheInterface $cache) {
  2. $this->cache = $cache;
  3. $this->useCache = true;
  4. }
  5.  
  6. public function set($key, $value) {
  7. //...
  8. }
I używać kodu normalnie, tj:
  1. $r = new Resource();
  2. $r->setCache($myCacheImpl);
  3. $r->set('xyz', 'aaa');
  4.  
  5. // zamiast
  6. $r->cache = $myCacheImpl;
  7. $r->xyz = 'aaa';
Raczej nie przekonasz mnie, że interfejs drugiego rozwiązania jest lepszy... bo jak dla mnie to jest on okropny i podatny na błędy.

Cytat
A co gdybym dopisał opcję ustawiania flagi $useCache na false w przypadku usunięcia obiektu Cache?
Dodać metodę odpowiedzialną za usuwanie cache, która po usunięciu zmieni flagę?

Cytat
Klasa to nie tablica, której przypisujemy po prostu wartości do właściwości. Służy do wykonywania konkretnych zadań w których mieści się kontrola nad wartościami w jej wnętrzu.
Gdy pisałem o tablicach/kolekcjach miałem na myśli taką sytuację:
  1. class AbcMyClass {
  2. protected $storage = array();
  3.  
  4. public function get($key, $default = null) {
  5. return array_key_exists($key, $this->storage) ? $this->storage[$key] : $default;
  6. }
  7.  
  8. public function set($key, $value) {
  9. $this->storage[$key] = $value;
  10. }
  11. }
  12.  
  13. class AbcMyClass {
  14. public function __get($key) {
  15. return isset($this->{$key}) ? $this->{$key} : null;
  16. }
  17.  
  18. public function set($key, $value) {
  19. $this->$key = $value;
  20. }
  21. }
Pomijając fakt o ile bardziej podatne na błędy i mniej elastyczne jest drugie rozwiązanie (ograniczone możliwości dla nazwania kluczy, problem gdy nazwa klucza jest w zmiennej) spójrzmy na całą różnicę pomiędzy użyciem obu rozwiązań:
  1. $obj->get('parameterA');
  2. $obj->parameterA;
  3.  
  4. $obj->set('parameterA', 123);
  5. $obj->parameterA = 123;
  6.  
  7. $obj->get($abc->getKey());
  8. $key = $abc->getKey(); $obj->$key; // nie jestem pewien czy $obj->{$abc->getKey()}; zadziała. Zrezstą za używanie zmiennych zmiennych powinno się coś obcinać


Co do drugiego przypadku (z klasą Session). Znowu ten sam problem - dziesiątki IFów. Na pewno żaden z nas nie byłby szczęśliwy mając wykorzystywać tą klasę. Takie rozwiązanie dla mnie byłoby do zaakceptowania wyłącznie w przypadku konieczności zachowania wstecznej kompatybilności. Tj. zakładając, że mamy już kod, klasy, która ma publiczną właściwość "id" musimy dodać jeszcze opcję usuwania użytkownika gdy jest ona fałszem. Paskudne rozwiązanie ale jedno z niewielu jakie pozwala na zachowanie tej nieszczęsnej kompatybilności.
Go to the top of the page
+Quote Post

2 Stron V   1 2 >
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 29.06.2025 - 12:44