Magia __get - dylemat natury moralnej

0

Mam nadpisaną metodę __get:

    /**
     * Warning: magic is slower (than getters/setters)
     * @param string $name
     * @return mixed
     * @throws \Exception
     */
    public function __get(string $name)
    {
        $methodName = "get{$name}";
        if (method_exists($this, $methodName)) {
            return $this->$methodName();
        }
        throw new \Exception('No access to property.');
        // or trigger_error('message', E_USER_NOTICE);
    }

Pełny kod jest tu:
https://github.com/ccwrc/design_patterns_practice/blob/master/ExperimentalFolder/MagicMethod.php

I pytanie.

  • czy rzucenie wyjątkiem jest właściwe? W sumie nie można się go zbytnio spodziewać.
  • błąd jest lepszy (trigger_error)?
  • można też zwrócić NULL, ale wyjątek wydaje mi się bardziej prawidłowy, w końcu jakaś właściwość może mieć przypisany NULL i zwrócenie tego nulla przy nieistniejącej właściwości wydaje mi się zapoczątkowaniem katastrofy.

Co jest bardziej prawidłowe: wyjątek/błąd/NULL?

2

Jest jeszcze opcja czwarta, dodanie gettera, jak Pan Bóg przykazał :P

"trigger_error('message', E_USER_NOTICE)" jest słabe. Możesz zignorować E_USER_NOTICE i wtedy nawet się nie dowiesz, co jest nie tak. A sporo aplikacji jednak wyłącza notice'y.

"można też zwrócić NULL" - to samo co wyżej, tylko jeszcze gorsze.

Rzucenie wyjątkiem, to najmniejsze zło z tego wszystkiego, bo daje najwięcej informacji w razie niepowodzenia i zatrzymuje działanie aplikacji, a nie pcha tego nulla dalej.

Natomiast moim zdaniem najlepszym rozwiązaniem jest unikanie magii.

0

Używanie magicznych metod __get i __set to proszenie się o kłopoty, nikt myślący tego nie używa, powinno to być IMO usunięte z PHP.

1
TomRZ napisał(a):

Używanie magicznych metod __get i __set to proszenie się o kłopoty, nikt myślący tego nie używa, powinno to być IMO usunięte z PHP.

Mocki do unit testów? ORM? Obiekt $view do widoków w MVC? API do obsługi struktury drzew, parsery html/XML?

PS: Nie wspominając o podmianie implementacji z Dependency Injection i LSP (magic metody są konieczne, przez to że php jest dynamiczny i pola są takim samym interfejsem jak metody).

1
TomRZ napisał(a):

W każdym z tych przypadków używanie magicznych metod nie jest właściwe.

Twoje wypowiedzi brzmią jakby były powtarzanymi, wyuczonymi linijkami.

Może wyjaśnisz dlaczego to Mocki, ORM, View i struktury danych nie powinny korzystać z elementu języka, jakim są dynamiczne pola?

To że jakiś element jest nie nie przystosowany i odradzany w jednym miejscu, nie znaczy że nie może okazać się przydatny w innym miejscu.

Zarówno DI jak i Liskova mozna zrealizować bez magicznych metod, które z zasady są szkodliwe, są hackiem.

Nie zrozumiałeś - mam na myśli to że masz np jakąś bibliotekę, która dostaje od użytkownika obiekt. Jak to obiekt w php, blibioteka ustawia mu dynamiczne pola. Bez __get i __set nie możesz skorzystać z interfejsu, który oferuje biblioteka. Oczywiście możesz zmienić/edytować bibliotekę jeśli chcesz, ale jeśli mówisz że nie powinno się korzystać z dynamicznych pól w PHP, to proponuję napisać do Dev'ów php, żeby w php 8.0 zrobili php statycznym językiem ;)

1
TomRZ napisał(a):

Tak jest, uważam, że dynamiczne, niezadeklarowane zmienne w obiektach to wielkie zło.

To mówiłem, napisz do twórców PHP, Ruby'ego (i każdego języka dynamicznego) żeby naprawili ich języki, wyrzucają dynamiczne pola.

Od tego są tablice, a nie obiekty.

To nic nie znaczy. Ktoś mógłby powiedzieć "nie używaj pętli, od tego jest array_map()|, a taki argument prowadzi do nikąd.

Poza tym, może się okazać że array będzie nie wystarczający, __get, __set zapewnia większą elastyczność:

  • można modyfikować input/Output
  • można zareagować wyjątkiem
  • można wywołać listener/callback
  • można zmienić stan wewnętrzny, np increament'ować counter
  • etc.

Oczywiście możesz się przesiąść z oop na proceduralny i wszystko to robić na tablicach, życzę powodzenia :D

Ta cała dynamiczność PHPa to tak naprawdę garb/ciężar z początków tego języka kiedy PHP chciał być trochę jak Perl. Ja już dawno oduczułem się stosowania takich hacków, i widzę pozytywne efekty, polecam.

Mówiłem już, jasne że dynamiczne pola w logice to pomysł raczej słaby - ale nie znaczy to absolutnie że w innych miejscach jest bez użyteczny.

W statycznych językach interfejsem są metody - więc tylko metod się używa.
W dynamicznych językach interfejsem są metody, pola, pola dynamiczne, etc. - więc i magicznych metod się używa.

Straciłyby tylko sens gdyby nie dało się w php stworzyć dynamicznie pół. Tylko wtedy - jeśli tego chcesz - napisz do devów php :D

0

Jednak wtrącę jeszcze słówko do wątku bo zauważyłem tutaj coś niepokojącego. Postaram się wytłumaczyć to w taki sposób żeby było to zrozumiałe dla wszystkich.

Przypuśćmy, że wchodzę na forum zawodowych zabójców z prostym pytaniem: półotwarty teren, muszę cicho (praktycznie bezgłośnie) pozbyć się gościa (185cm, 110kg, ale żylasty). Czy lepszy będzie nóż bowiego do podcięcia gardła, czy zakryć usta ręką i wsadzić sztylet w serce?

I wchodząc na to forum nie oczekuję odpowiedzi typu "zabijanie jest be i niemoralne". Ja mam to głęboko w dudzie, że jest be i niemoralne bo to mój zawód, pasja i przynosi kasę (no i jakby nie patrzeć to forum zawodowych zabójców). Oczekuję odpowiedzi typu "gościu, może lepsza będzie w tym wypadku garota", albo "polecam sztylet, ale załóż rękawiczkę na rękę, którą będziesz zakrywał usta, ofiara może ci pogryźć palce - ja nie założyłem rękawiczki i miałem zakażenie, musiałem brać antybiotyki".

A tera do rzeczy. Jak wchodzę na forum programistyczne z konkretnym pytaniem o jedną metodę magiczną to nie oczekuję od kilku osób odpowiedzi "metody magiczne są be, nie używaj". Ciekawe, czy osoby twierdzące, że metody magiczne są złe używały kiedykolwiek konstruktora, bo o dziwno jest on (szok i niedowierzanie) metodą magiczną w PHP?!

@Markuz
Napisałeś swój komentarz przed dokładnym zapoznaniem się z pytaniem, przed zapoznaniem się z odpowiedziami i przed zapoznaniem się z komentarzami do odpowiedzi. Chyba. Mi jednak wydaje się, że pomyliłeś tematy. W związku z tym masz szansę przenieść swój komentarz do odpowiedniego tematu - możesz z niej skorzystać. Oczywiście nie naciskam, to luźna propozycja.

@TomRZ
Jest takie gospodarsko-programistyczne powiedzenie: "nie rozbieraj płotu dopóki nie dowiesz się po co go postawiono". Kiedy już się dowiesz to uderzaj ostro np. tu: https://twitter.com/official_php i walcz o swoje prawa. Ale doradzałbym argumenty zamiast klapek na oczach.

@Desu @TomRiddle
Dzięki za wypowiedzi w temacie, przydały mi się.

1 użytkowników online, w tym zalogowanych: 0, gości: 1