Przyszłość języka PHP

Pewnie wielu z was zastanawia się, jaka będzie przyszłość języka PHP. Co będzie w nowych wersjach, a czego nie będzie i dlaczego. Dlatego powiem kilka słów o tym jak wygląda ewolucja języka.

Proces decyzyjny.

Typowo proces decyzyjny wygląda tak:
ktoś wymyśla feature, tworzy nową propozycję rfc. Następnie zapisuje się na listę mailingową internals tam obwieszcza, że stworzył propozycje i zaprasza do dyskusji.

Następnie osoby zapisane do listy, które to są core developerami PHP dyskutują na temat propozycji. Zwykle pojawia się wiele opinii za i przeciw oraz prośby na uściślenie propozycji. Losy propozycji zależą od tego czy po pierwsze ma sens, jeżeli nie ma, to już na początku osoba proponująca jest pozbawiana złudzeń, że to nie przejdzie.

Jeżeli propozycja ma sens i jest czymś co większość może zaakceptować, to osoba proponująca proszona jest o napisanie prototypowej implementacji i udostępnienie jej jako svn-patch do trunka, do testów. Ostateczną decyzje czy uwzględnić nowy feature podejmuje release manager wydania.

Generalnie proces wprowadzenia nowych funkcjonalności do języka jest procesem demokratycznym, jednak trzeba być dobrym „mówcą” i mieć naprawdę mocne argumenty, żeby wprowadzić coś nowego. Z tego co zauważyłem czytając listę internals, prawie nigdy nie przechodzą featury, które zrywają wsteczną kompatybilność.

Interesujące propozycje.

Z kilkunastu propozycji rfc wybrałem do opisu kilka, które wg. mnie zasługują na szczególną uwagę i zmieniają jakość obcowania z językiem.

1.Błędy jako wyjątki

Proponuje zamianę prawie wszystkich błędów ( oprócz parse i compile errors ) na wyjątki. Czyli defakto ukonstytuowuje to co wiele osób robi ustawiając swój error handler, który wyrzuca exception.

2.Typowanie zmiennych skalarnych

Dodaje do języka możliwość deklarowania w parametrach funkcji typu zmiennej innego niż obiekt np. int, string, float etc.

3.Traits

Dodaje możliwość tworzenia trait-ów czyli abstrakcyjnych klas, które mogą być wielodziedziczone. Nie raz spotykam się z sytuacją, że chce aby dwie lub więcej klas miało kilka wspólnych metod. Natomiast nie mogę zmodyfikować ich klasy bazowej, lub jej tworzenie wydaje się bez sensu.

W tym momencie z pomocą przychodzą nam traity. Zademonstruje przykład. Załóżmy, że mamy projekt w Doctrine lub jakimiś innym ORM-ie opartym na ActiveRecord.

Mamy dwie klasy dziedziczące z Doctrine_Record (nie modyfikowalny), w których to chcemy mieć identyczne eventy na preSave, preDelete etc. Jest to nam potrzebne bo chcemy zaimplementować ustawianie kolejności w tabeli.

Teraz jedynym rozwiązaniem jest napisać te metody i skopiować je pomiędzy klasami. Rozwiązanie z traitami:

trait TOrderable {
    public function preSave($event){
    //...
    }
    public function preDelete($event){
    //....
    }
}

class User extends Doctrine_Record {
    //... metody i właściwosci
    //importujemy Trait
    use TOrderable;
}

class Post extends Doctrine_Record {
    //... metody i właściwości
    //importujemy Trait
    use TOrderable;
}

Z powyższego przykładu można by dość do wniosku, że tak naprawdę Trait-y to interfejsy w których metody posiadają implementacje. Od wielodziedziczenia różnią się tym, że nie mogą zawierać właściwości. Defakto jest to taki copy-paste obsługiwany przez język.

4. Natywne gettery i settery

Dodaje do języka możliwość stosowania natywnych getterów i setterów. Co to oznacza ? Dotąd, żeby ukryć przed użytkownikiem implementacje jakiejś klasy stosowaliśmy gettery i settery w postaci:

class Foo {
    protected $_bar = 1;

    public function setBar($bar){
        $this->_bar = $bar;
    }

    public function getBar(){
        return $this->_bar;
    }
}

//użycie:
$foo = new Foo;
echo $foo->getBar();

Propozycja natomiast wprowadza natywne gettery i settery, czy możliwość odwoływania się do zmiennej $bar tak jak by była zadeklarowana jako public ale za pośrednictwem metody. Przykład:

class Foo {
    protected $_bar = 1;

    public property bar {
         get {
             return $this->_bar;
          }
          set {
              $this->_bar = $value;
          }
    }
}
//uzycie
$foo = new Foo;

//bedzie wywolany get
echo $foo->bar;

//bedzie wywolany set
$foo->bar = 15;

Co właściwie wnosi dobrego ta propozycja ? Po pierwsze, nie trzeba będzie na zaś deklarować wszystkich getterów i setterów na wszelki wypadek czy będą nam potrzebne czy nie. Po drugie wg mnie propozycja dodaje spójność do języka w ten sposób, że z właściwości korzystamy jak z właściwości a z metod jak z metod. Jest to bardziej intuicyjne.

A wy co chcielibyście mieć w tym języku ?

  1. Punkt 1, jak sam wspomniałeś, jest do zrobienia, ale to brzydkie obejście; Na 2 i 3 czekam z niecierpliwością, zaś 4 jest dla mnie niepotrzebne – mając zdeklarowane setX i getX mam tak naprawdę pełny interface, a jeśli nie potrzebuję ładnego interface`u – korzystam z __get, __set i __call…

    Pozdrawiam

  2. Wojciech Soczyński pisze:

    4) to taki fajny syntactic sugar, wiadomo, można się bez tego obejść ale zawsze trochę osłodzi życie 😉

  3. sf pisze:

    1 to chyba każdy czeka 😉 2 jak dla mnie to zabija idee php, o to chodziło w php, że nie trzeba podawać typu, a teraz upodobniamy to do innych języków, zupełnie niepotrzebnie 3 jest mi obojętna, a 4 też dla mnie zbyteczne

    PS zlikwiduj captcha bo dodawanie komentarzy jest denerwujące 😉

  4. Wojciech Soczyński pisze:

    2) nie jest takie bez sensu o ile przy typowanych argumentach będzie następowało automatyczne rzutowanie na właściwy typ, tak jak to jest w innych przypadkach, np. dodawaniu ‚4’ +5 = 9 a przynajmniej nie trzeba będzie robić litanii wewnątrz funkcji typu

    if(is_numeric($arg)){
    //...
    }
    if(is_array($arg)){
    //...
    }

    Co do captchy to niestety jest konieczna, już kiedyś przeżyłem atak botów i maiłem ponad 200 komentarzy o viagrze i powiększaniu penisa 😛

  5. Wojciech Soczyński pisze:

    Na próbę wyłączyłem captche i włączyłem inny wykrywacz spamu, zobaczymy jak będzie 😉

  6. Alan Gabriel Bem pisze:

    Szkoda, że nie ma ani słowa o – prawdziwym – przeciążaniu metod :(

  7. Wojciech Soczyński pisze:

    To co jest prawdziwe, a co nie, zależy od punktu widzenia. Jak dla mnie obecne rozwiązanie jest satysfakcjonujące :>. Ja bym wolał zamiast tego pythonowe dekoratory, dzięki nim można osiągnąć ten sam efekt i inne równie ciekawe, bez zmian w rdzeniu języka

  8. matipl pisze:

    Od długiego czasu czekam aż będzie w corze:

    1.Błędy jako wyjątki
    2.Typowanie zmiennych skalarnych

    bez własnych dodatków, aby uzyskać taki efekt.

  9. Wojciech Soczyński pisze:

    Standartowe błędy jako wyjątki chyba nie prędko jeszcze zobaczymy.

    Natomiast właśnie się toczy dyskusja co do 2) na wewnętrznej liście developerów i w zasadzie wszyscy by chcieli tą funkcjonalność, tylko zastanawiają się nad sposobem wykonania.

    Są dwa podejścia albo sprawdzanie typu zmiennej tak jak w is_int, is_float, etc. Albo po prostu automatyczne rzutowanie i błąd (tutaj też jest dyskusja, exception czy e_strict) w momencie kiedy nie można czegoś zrzutować np array na int.

    Ja osobiście jestem za opcją numer 2 + exception.

  10. Co do typowania, to faktycznie najbardziej pożądana przeze mnie funkcja (oprócz traitsów w dwóch różnych wariantach), na szczęście już nie dyskutują, tylko już to scommitowali:

    Scalar-Type-Hints-are-Here

    ps. dobry blog, w PL nie znalazłem podobnego jeszcze.

  11. Wojciech Soczyński pisze:

    No niby scomitowali, ale nadal toczy się dyskusja na internalsach i nie wiadomo, czy ten ficzer w tej postaci znajdzie się w kolejnym release-ie i czy w tej postaci.

    Btw. dziękuje za słowa uznania.

  1. There are no trackbacks for this post yet.

Leave a Reply

Informuj mnie o odpowiedziach poprzez e-mail. Możesz również subskrybować wpis bez zostawiania komentarza.