Co by było gdyby ? – pomysły na PHP

Jeżeli śledzicie dzone.com. Pewnie zauważyliście, że od pewnego czasu na blogach osób związanych z Javą przetaczają się dwa związane ze sobą tematy. Pierwszym z nich jest kwestia uczynienia Javy wolną (udostępnienie jej na wolnej licencji, uniezależnienie od Oracle) a drugim z nich jest kwestia zmian w języku. Kilka osób poddało pomysł aby zrobić fork Javy wydany na jednej z licencji open-source’owych. Co do zmian w języku to część osób rozczarowana tym jaki kształt ma w tej chwili język oraz powolnym wprowadzaniem nowości do niego doszła również do wniosku, że najlepiej było by stworzyć nową wersję Javy niekompatybilną wstecznie – Backward Incompatibile Java. Znalazło się jak to zwykle bywa sporo osób, które stwierdziły ze oba pomysły jak najbardziej idą ze sobą w parze i proponują stworzenie „wolnego” forka Javy i rozwijanie go w sposób niekompatybilny wstecznie. Mnie nasuwa się jedynie pytanie, czy taki fork dalej będzie (i będzie można go nazywać) Javą ?

Postanowiłem odnieść tą sytuację do własnego podwórka i zastanowić się co by było gdyby stworzyć fork interpretera PHP. Jakie zmiany ja przeprowadziłbym w języku i dlaczego oraz czy po tych zmianach ten fork można by nazwać jeszcze PHP. Zachęcam też wszystkich do zabawy i wpisywania własnych propozycji.

Jedną z pierwszych rzeczy jaką był zmienił, to usunięcie przestarzałych rzeczy typu register globals, short open tag, magic quotes, safe mode, allow call time pass by reference.

Drugą rzeczą było by przejrzenie pliku php.ini i usunięcie wszystkich opcji, które w jakikolwiek sposób niejawnie wpływają na wykonywanie skryptów – banowanie klas, funkcji etc. Domyślam się, że po tej operacji, zostały by tylko opcje związane z włączaniem/wyłączaniem rozszerzeń oraz limit czasu i pamięci.

Trzecią rzeczą było by zastąpienie wszystkich errorów wyjątkami, a szczególnie fatal_error (z wyjątkiem parse_error i compile_error z wiadomych względów).

Zmiany omówione jak na razie w zasadzie nie zmieniają samej istoty języka a tylko sposób działania interpretera. Dalsze rzeczy jednak już jak najbardziej.

Po czwarte usuną bym słowa kluczowe i mechanizmy: global i goto. Są to pozostałości po językach bardziej niskopoziomowych i zwykle po prostu zaciemniają kod. Co więcej, pisząc w sposób obiektowy, nie ma w ogóle potrzeby ich wykorzystywania.

Po piąte – biblioteka standardowa. Zamiast jednej globalnej przestrzeni nazw przesunął bym funkcje z różnorakich rozszerzeń do własnych namespaceów.

Po szóste – typy proste. Typy proste zamieniłbym na obiekty, które dziedziczą z klasy ‚Value’. Obiekty których klasy dziedziczą z klasy ‚Value’ były by niezmienne (immutable) oraz przekazywane przez kopię. Obiekty użytkownika, które dziedziczyły by z abstrakcyjnej klasy Value mogły by też same obsługiwać rzutowanie (funkcja typu __cast).

Po siódme zmiana orientacji języka na bardziej funkcjonalno-obiektowy niż proceduralno-obiektowy. Usunięcie możliwości przekazywania przez referencje typów prostych – konsekwencja punktu szóstego.

Po ósme – anonimowe klasy i obiekty oraz obiekty typu singleton jak w Scal’i oraz usunięcie możliwości deklaracji statycznych metod i pól klasy.

Po dziewiąte – czytelniejsze struktury kontrolne – usunięcie konieczności stosowania nawiasów „(” i „)” w if, for, foreach, empty, isset, unset – podobnie jak w Google Go!.

Po dziesiąte – możliwość przeciążania operatorów na poziomie przestrzeni nazw – definiuje w jakimś namespace funkcję function +() i jest ona wykorzystywana w danej przestrzeni nazw zamiast domyślnej implementacji.

Po jedenaste – możliwość używania własnych typów prostych na poziomie przestrzeni nazw. Przykładowo tworzę klasę MyString. Wpisuje use MyString as String, po takim czymś kod $a = "ala ma kota" będzie równoważny $a = new MyString('ala ma kota').

Po dwunaste – traits i mixins.

Po trzynaste – dekoratory w stylu Pythona i/lub adnotacje.

Po czternaste – __call który jest wywoływany przy każdym wywołaniu metody obiektu, nie tylko w przypadku gdy nie istnieje.

Uff ale się rozpisałem, wiem, że niektóre pomysły tutaj mogą wydawać się trochę szalone ale w końcu na początku ostrzegałem, że puszczę wodzę fantazji. Z wszystkich wymienionych punktów w zasadzie zastosowanie punktu 5 i 6-tego czyli zmiany w bibliotece standardowej i typach podstawowych zmieniają diametralnie oblicze języka i powodują, że ciężko już mówić po takich zmianach, że to „coś” jest PHP-em. Natomiast cała reszta to w zasadzie są dodatki i drobny lifting systemu obiektowego.

Jestem bardzo ciekaw co o tym wszystkim myślicie, oraz co wy zmienilibyście gdybyście rozpoczynali fork PHP?

  1. KKH pisze:

    Coś takiego:

    function f(const array $a) { … }

    Nie jestem ekspertem jakby co, więc liczę na ewentualne naprostowanie.

    Nurtuje mnie brak modyfikatora „const”. Array i string leca w PHP domyślnie przez wartość. Jest to fe facto „referencja”, a przy pierwszym rozjechaniu się kopii z oryginalem, PHP kopiuje dane. Robilem testy wydajnościowe z wielkimi danymi i widać, że tak to działa. Poza tym gdzieś czytałem o takiej optymalizacji wydajnościowej silnika PHP.

    Chciałbym mieć modyfikator const, ktory działa tak, że argument leci syntaktycznie „przez wartość” (tak jak teraz), fizycznie jako referencja, ale przy rozminięciu się kopii z orygniałem, nie są kopiowane bajty, a rzucany wyjątek.

    To dotyczy array i string. Możnaby rozciągnąć na obiekty, ale wtedy sprawa odrobinę się komplikuje, bo obiket ma metody mogące go modyfikowac niejawnie. W C++ chyba modyfikator const dawało sie metodom dozwolonym dla stałych obiektow. (słabo już pamiętam C++).

    Mam teraz sporo kodu, gdzie argument powinien być niemodyfikowany ale podany przez referencję z powodów wydajnościowych. Język nie chroni mnie przed niepożadanym zmodyfikowaniem argumentu gdy używam referencji i spadkiem wydajności gdy uzywam przez wartość.

  2. AllahAkbar pisze:

    Po piętnaste: Zmieniłbym język na python lub ruby i przestał się demotywować ograniczeniami obecnego języka.

  3. andrzej pisze:

    Allah dobrze rzecze, polać mu!

  4. @allah, andrzej: napisałem co nieco w Pythonie i nie jest dla mnie jakiś mega super w porównaniu do PHP, już prędzej zmieniłbym język na Scala’e, sam PHP jaki jest raczej nie ma jakiś poważniejszych „ograniczeń” (do tego do czego jest przeznaczony – www), natomiast brakuje troszkę spójności

    @kkh – ten feature o którym wspomniałeś w engine PHP nazywa się copy on write, obiekty są zawsze przekazywane przez referencje a właściwie jest kopiowany identyfikator obiektu (na jedno wychodzi), z tego co widziałem copy on write jest dużo szybsze niż przekazywanie przez referencję, myślę, że obecny mechanizm jest akurat lepszym rozwiązaniem od twojej propozycji, co więcej, uważam, że wysokopoziomowy język powinien ściągać z programisty takie szczegóły implementacyjne i sam aplikować odpowiednie optymalizacje

  5. Spawnm pisze:

    AllahAkbar – nic głupszego się napisać nie dało?
    Do www python jest sto razy gorszy nawet z django.

    „usunięcie możliwości deklaracji statycznych metod” Bez sensu, co z factory?

  6. Z tego co czytałem, w php6 mają całkowicie zniknąć z php.ini takie opcje jak: register_globals, magic_quotes_gpc, etc.

  7. A co do „goto”, to przecież dopiero niedawno został dodany :) (bodajże w php 5.3) I już chcielibyście go wyrzucić?

    Wiecie co jest wspaniałego w pe-ha-pe? To, że nie narzuca mi jak mam pisać swój kod, jak ktoś potrafi odpowiednio używać goto to niech go sobie używa i przyśpieszy swój kod, uprości, jak mu wygodniej.

    Wyrzucić „global”? I co, koniec możliwości kodowania proceduralnego? Teraz mam wszystkie nawet najprostsze funkcje ładować w obiekty i moje strony mają się ładować w 0.5 sek zamiast 0.05 sekundy? No fenk ju.

  8. @cezary – php6 nie będzie, jego development został przerwany, a branch w svn usunięty, goto ja osobiście bym usunął dlatego, że tak naprawdę nic nie daje a debugowanie kodu z nim jest bardzo utrudnione, sami autorzy zresztą php napisali, że dodają goto ale nie należy go używac :P, co do global, to da się kodować bez niego i szczerze, ja np. nie pamiętam kiedy ostatni raz go użyłem, global również wydatnie utrudnia debugowanie – nigdy nie wiadomo co w nim siedzi, zresztą ja tu mówię o sytuacji gdybym chciał zrobić „fork” php czyli osobną gałąź rozwojową niezależną od „oficjalnej dystrybucji”, zawsze mógłbyś sobie działać na tej oficjalnej z goto i global…

    @spawn – zamiast metod statycznych dodanie obiektów singletonowych z Scala’i – efekt podobny a dzięki temu nie ładujemy wszystkiego do jednego worka, fabrykę też można przez taki obiekt zaimplementować i przynajmniej mamy rozdzieloną kreację obiektu od definicji klasy

  9. KKH pisze:

    @Wojciech Soczyński

    Niezrozumieliśmy się. Jeszcze raz, krótko i węzłowato.

    CONST oznacza, ze argument jest STAŁĄ i jego próba modyfikacji skutkuje rzuceniem wyjątku. Technicznie rzecz biorac, do momentu proby modyfikacji mamy do czynienia z tym samym co argument bez modyfikatora const. Próba modyfikacji – silnik rzuca wyjątek. Dla array i string modyfikacja jest natychmiastowa, a dla obiektów należy wprowadzić podzial metod na dozwolone i niedozwolone dla stałego obiektu.

  10. batman pisze:

    Fajnie tak pogdybać. Moje typy to:
    – ścisła kontrola typów
    – porządek w języku (np. niech igła jest zawsze pierwszym parametrem)
    – zamiast błędów zgłaszać wyjątki (nawet dla notice)
    – więcej SDK dla PHP pozwalających na korzystanie z zaawansowanych rozwiązań

  11. Ok, rozumiem już o co ci chodzi, chociaż motywacja do mnie nie przemawia 😉

  12. KKH pisze:

    @Cezary Tomczak

    „Wiecie co jest wspaniałego w pe-ha-pe? To, że nie narzuca mi jak mam pisać swój kod, jak ktoś potrafi odpowiednio używać goto to niech go sobie używa i przyśpieszy swój kod, uprości, jak mu wygodniej.”

    Gorzej gdy zaczniesz obcować z cudzym kodem albo swoim sprzed paru tygodni :). Poza tym fistaszkowe optymalizacje[1] w PHP to głupota, bo sam PHP jest 30-100 razy wolniejszy od najszybszych „platform”, a tymi optymalizacjami naprawdę niewiele da się ugrać. Co innego cashowanie, uzywanie wbudowanych funkcji zamiast analogicznego kodu w PHP, nie wygłupianie się z regexpem z byle okazji, sensowne podejście do bazy danych.

    W sumie to niezły szok, jak spolaryzowane jest środowisko. jedni optymalizują goto, a inni bez frameworków nie ruszają z miejsca. :)

    ____________
    [1] – unikanie wywołań funkcji, rozwijanie petli, rugowanie podwójnego cudzysłowia, godzina debatowania czy wprowadzić kolejną zmienną w ciele funkcji czy użyć tej co już jest (bo przecież wprowadzenie zmiennej „kosztuje”). Sam niedawno złapałem się na fistaszkowej optymalizacji zamieniając $arr[‚a’][‚str’] na $arr[‚a_str’].

  13. KKH pisze:

    @Wojciech Soczyński

    motywacja wzięła się z moich osobistych obaw. Narobiłem iteratorów, wrapperów itd (ale bez przesadyzmu :) ). Duże tablice latają w te i wewte, a ja nie mam gwarancji, że gdzieś niechcący ich nie zmodyfikowałem. A skoro są języki gdzie tak rozumiany const istnieje, to pomyslałem, że fajnie byłoby go tu mieć.

    @AllahAkbar
    Co do ssania PHP. Ja osobiście juz się przekonalem, że on mocno ssie, zwłaszcza robiąc certa, bo wtedy chcialem rozumieć dosłownie wszystko i na kilka niezłych głupot trafiłem, które jakoś mi umkneły wcześniej (myślałem, ze cer jest trudniejszy i stąd to zgłębianie). Ale! Jest sporo softu w tym języku, sporo ludzi, a niektóre modyfikacje w miarę proste. Ja bym tego tak nie rzucał. PHP to dla mnie wygodne jak znoszone spodnie dzinsowe :). Szkoda by się zmarnował.

    Ad rem jeszcze. Z braków to ja bym dorzucił coś co podpada nie pod język, ale jego implementację.

    np. funkcja f zwraca tablicę, a ja nie mogę indeksować jej bezpośrednio, tzn. pisać:

    f(arg)[indx];

    tylko

    $dummy = f(arg);
    $dummy[indx];

    no trochę glupie to 😀 chyba, ze już poprawili w nowszej wersji. Nie sprawdziałem ostatnio.

  14. No to i ja się odniosę do tak bogatego merytorycznie postu. ;]

    1. Jak już wspomnieli przedmówcy, niektóre z tych „funkcjonalności” zostaną usunięte w kolejnej wersji PHP.
    2. Jedna uwaga – „blokowanie funkcji” jest bardzo przydatne przy ograniczaniu dostępności na hostingach. Oczywiście dla nas programistów jest to małe ograniczenie, ale musimy zrozumieć też inne strony.
    3. Błędów parsowania nie da się złapać, a co do reszty polecam set_error_handler().
    4. Jak już zostało wspomniane – nie chciałbym, żebyśmy się nagle zachłysnęli OOP, więc global powinien zostać, żeby tak samo jak w C++ PHP był językiem obsługującym oba paradygmaty – proceduralny i obiektowy.
    5. Wolałbym jednak pomysł wzięty z C++, czyli wszystko upakowane w std. Nie jest tego aż tak dużo, po prostu wystarczy nie zapychać „root namespace”.
    6. Zdecydowanie nie. To nie jest Java, więc nie próbujmy na siłę zmieniać inta w Integer. Takie rozwiązania można sobie zresztą zrobić samemu – parę klas + type hinting i do przodu.
    7. Jeśli pozostawimy przy tym możliwość programowania typowo proceduralnego, to zgoda.
    8. Usunięcie statycznych właściwości klasy? Zdecydowanie nie. Czym je zastąpisz?
    9. Jestem w stanie ustąpić w wielu miejscach, ale nie wracajmy do Pascala, ok? for($i = 0; $i ten język jest tak nieczytelny, że nie wiem jak można postulować zamianę czegokolwiek na niego. Bez urazy dla programistów Ruby’ego, ale po prostu ja go nie trawię.

    @Wojciech – PHP6 nie będzie, to i owszem, nowa wersja jeśli już będzie miała numerek 7. Z tego co wiem nieprawdą jest jednak, że został całkowicie zarzucony – zmiany, które były juz zrobione w 6 zostaną zmergowane i wydane „kiedyś” jako PHP 5.4.

    To tyle ode mnie. ;]

  15. Coś mi usunęło fragment komentarza.

    @AllahAkbar – naprawienie zepsutego samochodu nie polega na kupieniu nowego, to po pierwsze. Po drugie PHP powstawał na nieco innych założeniach niż Python, więc nie widzę tutaj sensu dyskusji. Ruby to już w ogóle „pojechałeś” -> ten język jest tak nieczytelny, że nie wiem jak można postulować zamianę czegokolwiek na niego. Bez urazy dla programistów Ruby’ego, ale po prostu ja go nie trawię.

  16. @tomasz kowalczyk:

    co do punktu nr 8, już dwa razy wrzucałem ten link ale dla Ciebie wrzucę jeszcze raz:
    obiekty singletonowe w Scala, żeby dużo nie mówić pomysł polega na tym, że zamiast robić pola statyczne, mamy singletonowe obiekty, deklaruje się je tak jak klasy z wyjątkiem tego, że zamiast class używa się słowa kluczowego object i taki obiekt jest tylko w jednym egzemplarzu i dostępny globalnie, po prostu singleton ale w dużo bardziej eleganckiej formie, w języku scala właśnie te obiekty zostały przeznaczone jako zastępnik metod statycznych, których w tym języku nie ma, dla mnie metody statyczne to w pewnym sensie zaprzeczenie idei programowania obiektowego

  17. W sumie Scala ładnie to załatwia, przynajmniej twórcy języka nie schowali głowy w piasek zasłaniając się OOP. Nadal jednak zostałbym przy realizacji statycznych pól i metod w tradycyjny sposób, z dwóch powodów:
    1. Po prostu przyzwyczaiłem się do takiej idei statyczności w kodzie, do tego w innych językach jest to zaimplementowane w podobny sposób, więc nie wydaje mi się to specjalnie istotne.
    2. Nie zawsze statyczne pola i metody odnoszą się do nowych, oddzielnych bytów, czasem może to np. być jakiś mały helper który zwyczajnie brzydko byłoby wrzucić w funkcję, a jako metoda statyczna załatwia sprawę.

    PS Kurczę, zauważyłem, że ucięło też punkty od 9 do 14, to chyba przez ten kawałek kodu, który wstawiłem – czy mógłbyś to zmoderować tak, żeby były widoczne? Czy ta treść się w ogóle zapisała w bazie?

  18. @tomasz:

    niestety ucięło i nigdzie tego nie widzę, więc o ile to możliwe wrzuć to jeszczę raz, jeżeli chcesz żeby twój kod był widoczyny zawrzyj to między znacznikami bbcode’u ‚sourcecode lang=”php”‚ tak jak tutaj:

    <?php echo 'aaa' ?>
  19. 9. Jestem w stanie ustąpić w wielu miejscach, ale nie wracajmy do Pascala, ok? Pętle ściągnięte z C++ wyglądają o niebo lepiej niż te „wydumane” z Pascala.
    10. Raczej przeciążanie operatorów na poziomie klasy, tak jak w C++. Przestrzenie nazw służą wyłącznie grupowaniu tematycznie podobnego kodu, a nie implementacji nowych funkcjonalności. Co, jeśli będęchciał użyć w którejś z klas domyślnej implementacji danego operatora? parent::operator+()?
    11. To by tylko zaciemniło kod, a nie daje żadnych nowych możliwości.
    12. Każda nowa funkcjonalność języka mile widziana. Mi prywatnie podoba się idea mixinów, z traitsami nie miałem do czynienia.
    13. Adnotacje mają się pojawić w kolejnej wersji PHP, o ile nie ma ich już w PHP 5.3.
    14. Jak najbardziej zgoda, rozszerzyłbym to tylko o metody __beforeCall() i afterCall() – możnaby wtedy bardzo fajnie implementować wstrzykiwanie filtrów do klas.

    To mniej więcej ten tekst, który mi ostatnio ucięło. ;]

  20. @tomasz:
    9. Jak dla mnie po prostu kupa nawiasów jakie czasami się gromadzą przy okazji if-ów i innych tego typu struktur jest po prostu mało czytelna dlatego chciałbym się ich pozbyć
    10. to kwestia tego jak kto interpretuje namespace, dla jednych ten mechanizm słuzy jedynie do aliasowania nazw funkcji, dla innych namespace/moduł to taka wyższa abstrakcja od klas – klasa agreguje metody, moduł klasy, supermoduł inne moduły…, np. w Pythonie moduł też jest obiektem :>, dzięki temu, że mamy możliwość przeciążania operatorów na poziomie modułu, można pisać bardziej generyczne mechanizmy, nic nie stoi też na przeszkodzie by takie modułowe przeciążenie sprawdzało czy klasa ma zdefinowaną własną funkcję przeciążającą…
    11. nowe możliwości są takie, że jeżeli typy proste były by też obiektami, to w ten sposób można by rozszerzać ich funkcjonalność, gdy typy proste są zwykłymi wartościami, to oczywiście nie ma sensu
    13. O adnotacje była zacięta walka i bardziej możliwe, że się nie pojawią, polecam jeden z wcześniejszych moich wpisów
    14.Mając __call wywoływany zawsze, wystarczyło by już samemu napisać __beforeCall i __afterCall, szkoda dokładać kolejne „specjalne/magiczne” funkcje…

  21. 13. Czytałem, czytałem. ;] Nie ma więc sensu gdybać na ten temat – zobaczmy co czas pokaże.
    14. Ale ten __call() byłby wykonywany przed metodą, więc dla nas żaden zysk, bo mielibyśmy tylko jedną możliwość wstrzyknięcia własnego kodu. A tak jedna metoda mogłaby przygotowywać środowisko a druga sprzątać po wszystkim.

  22. 14. No chyba, że to ten __call() determinowałby czy metoda w ogóle zostanie wywołana – wtedy było by tak:

    class A {
    
    function b(){
    }
    
    function __call($name, $arguments){
    //kod przed wywolaniem metody
    
    return call_user_func_array(array($this,$name),$arguments);
    
    //kod po wywolaniu metody
    
    }
    
    }
    
  23. W sumie to też jest jakaś opcja, ale dla mnie jest to już przesadna kontrola. Jeśli wywołuję metodę, to nie chcę, żeby jakikolwiek kod ją arbitralnie blokował – w moim przypadku opcja z __beforeCall() i rzuceniem wyjątku np. w przypadku braku uprawnień byłoby sporo lepsze.

  24. Rumcajs z Jcina pisze:

    O ile bardzo ciekawie tutaj piszecie, to nie zapominajcie o ortografii (w końcu ciekawe tematy czyta wiele osób, trzeba mieć to na uwadze).

    Nie powinno się pisać „Java’y”, tylko „Javy”, nie ma takiego tworu jak „Java’ą”, jest za to „Javą”, a zamiast „Fork’a” piszemy „Forka”.

    Wybaczcie, ale musiałem się w tej sprawie wypowiedzieć już po przeczytaniu pierwszego akapitu. Pozdrawiam!

  25. Ja jestem strasznym purystą językowym i raczej takich błędów nie popełniam, także pozwolę sobie „odbić piłeczkę” tych oskarżeń dalej. ;] Jeśli jednak zauważyłbyś gdziekolwiek w moim tekście błąd ortograficzny lub językowy – krzycz, dzwoń, pisz – mi na tym bardzo zależy. ;]

  26. @rumcajs:

    hm widocznie nie do końca dobrze zinterpretowałem uwagi Zyxa

  27. KKH pisze:

    singletonów zamiast metod statycznych?

    „obiekty singletonowe w Scala (…) dla mnie metody statyczne to w pewnym sensie zaprzeczenie idei programowania obiektowego”

    A singleton to taka koszerna obiektówka jest? :) Metoda statyczna przynajmniej siedzi sobie zaenkapsulowana w klasie, składniowo wskazuje na swoją klasę, nie wypuszcza zmiennych globalnych i last but not least: gdy jest prywatna, nie śmieci poza klasą – takie też tępić? No nie wiem…Może w tej Scali jest jeszcze coś o czym nie wspomniałeś, bo dla mnie ta propozycja to zamiana siekierki na kijek (albo kijka na kijek).

    W kwestii ulepszeń języka.

    Ścisłe typowanie jako opcja. Nie jestem na 100% pewien, ale myśle, że umożliwienie ścisłego typowania jako opcji (obok lużnego) umożliwiłoby pisanie fragmentów kodu nadających się do lepszej optymalizacji przez sprytniejszy silniczek. Uklon do pomysłu FB aby kompilowac PHP na C++.

    A może bardziej otworzyć PHP na pisanie rozszerzeń w C? Ani manual, ani społeczność, ani materiał na zfce nie promuje pisania takich wstawek. Może słabo szukalem, a może nikomu to nie jest do szczęścia potrzebne.

    Ogarnięcie bajzlu z kodowaniem znaków. Wiele funkcji napisano pod ASCII, a przypadkiem działają pod UTF8. To są „bagienne” okolice na które wielu developerow nie zwraca uwagi, bo zwykle jakoś to działa. Tak, wg. futurologów ma byc kiedyś poprawione, ale na razie nie ma.

    Zastanawiam się też czemu zadania godne Crona nie mogłyby być robione via silnik PHP. Ideologia KISS przeszkadza? Może. Nie upieram się, ale mój PHP dawałby po prostu jakiś register_task() w standardzie, tzn. z poziomu aplikacji, bez zwalania tych rzeczy na admina systemu.

    I jeszcze sie poskarżę. W pewnym projekcie postawiłem na pliki CSV, ale okazało sie, że w PHP fgetcsv() nie jest kompatybilne z fputcsv(). Wywala się gdy ostatnim znakiem napisu jest backslash. Ktoś to nawet zgłosił jako błąd i odpowiedziano mu, że to nie błąd, a poza tym BC to rzecz bardzo ważna.

    Bardzo ważna panowie, wiec spokojnie z tym php-fiction :)

    Co do pisowni.

    Do uwag Rumcajsa dodam apel o śmielsze używanie kropki. Potok słów z asekuranckimi przecinkami daje nieźle po oczach i niespecjalnie dobrze się czyta. Fakt, że kompilator języka polskiego tego nie łyka też ma znaczenie 😉

  28. KKH pisze:

    a, i jeszcze jedno. W pdręczniku, pod wieloma funkcjami jest napis w stylu:

    Warning

    On some operating systems flock() is implemented at the process level. When using a multithreaded server API like ISAPI you may not be able to rely on flock() to protect files against other PHP scripts running in parallel threads of the same server instance!

    Może ktoś bardziej obeznany powie mi czy to jest realny problem, tzn. czy w praktyce takie środowiska występują? Bo jeśli tak, to trochę dziwne i ja bym w takim przypadku postulował zajęcie się tą sprawą. Jakoś losowo zmieniajace sie flocki, locale i tym podobne mnie nie śmieszą.

  29. @kkh

    Co do ścisłego typowania, to ja jestem przeciw (niestety prawie wszystkie dane jakie php dostaje z zewnątrz to string). Natomiast wolałbym bardziej precyzyjnych reguł automatycznego rzutowania, oraz wyjątków/warningów przy stratnych niejawnych rzutowaniach.
    Jeżeli chodzi np. o aspekt optymalizacyjny to np. w języku clojure w nowej wersji dodano coś takiego jak sugestia typu, działa to tak że opisuje się, że jakaś zmienna ma pewien typ i kompilator dzięki temu optymalizuje kod, natomiast nie implikuje sprawdzania typów tych zmiennych.

    Z uwagami do kodowania zgadzam się jak najbardziej, jest to jeden z najpoważniejszych problemów php

    Jeżeli chodzi o metody statyczne i dlaczego uważam, że singletony z scali są lepsze – ideą programowania obiektowego jest wiązanie ze sobą struktur danych oraz funkcji które na nich operują w obiekty. Obiekty te eksponują dla świata zewnętrznego tylko swoje zachowania (interfejs).

    Jak wynika z tego opisu, metody obiektu działają w jego kontekście na wewnętrznym stanie obiektu. Metody statyczne z definicji są bezkontekstowe – natomiast jeżeli potrzebują do działania zmiennych statycznych klasy, oznacza to, że jednak mają jakiś kontekst. Dochodzimy tu do meritum sprawy: kontekst takich metod statycznych jest odrębny od kontekstu działania metod z instancji obiektu, a więc cel ich działania jest również inny.

    Z mądrych zasad programowania obiektowego wiemy, że klasa powinna spełniać tylko jedno zadanie, a jeżeli zajmuje się większą ilością rzeczy to należy zrefaktorować ją w taki sposób, by wydzielić z niej inne klasy, z których każda będzie miała tylko jedno zadanie. Wobec tego w ten sposób wydzielamy metody statyczne, których cel działania i kontekst jest inny niż dla metod instancji. Powstaje nam więc po prostu kolejna klasa z metod, które przedtem były statyczne.

    Klasa taka nie będzie raczej typowym obiektem, którego tworzymy kolejne egzemplarze, będzie operować tylko na raz zdefiniowanym wewnętrznym stanie. Będzie więć miała tylko jeden egzemplarz i dlatego nazwiemy ją singletonem. Należy zauważyć, że w obecnej implementacji odwołując się do jakiejkolwiek metody statycznej klasy tak naprawdę wywołujemy metody singletonowego obiektu klasy. Mechanizm zaczerpnięty z Scali umożliwia po prostu czyste rozdzielenie metod działających w kontekście obiektu w klasach wieloegzemplarzowych od tych, które działają w kontekście klas jednoegzemplarzowych. Sam z siebie ten mechanizm nie wnosi w zasadzie nic nowego oprócz tego, że promuje styl programowania oparty na separacji zadań i odpowiedzialności klas.

  30. @kkh

    Co do wielowątkowych api serwerowych. Jeżeli podepniesz php poprzez FastCgi albo właśnie przez ISAPI, zawsze będziesz miał wielowątkowe środowisko. To czy jest to realny problem czy nie z tymi lockami to nie wiem bo nie spotkałem się z tym. Myślę, że pewnym rozwiązaniem było by stworzenie interpretera php na zasadzie serwera aplikacji – wtedy locki były by wewnętrzne i w obrębie jednej aplikacji.

  31. Zyx pisze:

    Jeśli już, to taki projekt powinien być pisany od zera, a po drugie Twoje propozycje przypominają mi bardziej „pakujemy co się nawinie do jednego wora i mocno mieszamy”. O ile część z nich oczywiście ma sens, to przyczepię się do:

    3. Usuwania „goto i global” – z GLOBAL-em się zgadzam, z GOTO niekoniecznie. Zgadzam się, że ta instrukcja jest zupełnie nieprzydatna dla normalnych programistów, ale weź pod uwagę np. generatory kodu z jakichś bardziej abstrakcyjnych opisów. Gdyby nie GOTO, dodanie niektórych instrukcji do Open Power Template 2.1 byłoby niemożliwe, bo ich realizacja przy pomocy „wyższych” struktur kontrolnych byłaby tak nieefektywna, że wręcz nieopłacalna. Jak późniejszy użytkownik, TOBIE zwisa, co tam pod spodem siedzi, dopóki działa szybko, MI nie zwisa, bo ja muszę to zaimplementować.

    5. Bibliotekę standardową przydałoby się od zera przeprojektować, a nie ograniczać się do poprzesuwania funkcji.

    6. Typy proste – jak chcesz robić coś takiego, to masz 2190381093084395873249 innych języków działających w ten sposób. Pakowanie wszędzie obiektów bez zastanowienia się to bezsens. Ograniczyłbym się do podziału na typ skalarny i typ obiektowy z całkowitą blokadą konwersji między nimi.

    7. Brak referencji nie daje nam języka funkcyjnego, a czegoś takiego, jak „język funkcjonalny” w ogóle nie ma :).

    8. Statyczne pola – ich usunięcie jest warte rozważenia, natomiast statyczne metody… hmmm… już niekoniecznie. Jest to kwestia tego czy umie się z nich poprawnie korzystać. Czasem z punktu widzenia czytelności jakąś operację na dwóch obiektach tego samego typu lepiej jest zrealizować jako metodę statyczną, by uniknąć pytań typu „OK, a czemu wywołujemy ją z poziomu obiektu A, przekazując B za parametr, a nie na odwrót?”

    9. Po raz kolejny: czemu w takim razie nie używasz Rubiego lub Pythona, jak wolisz taką składnię? Ja nie wolę i powiem więcej: bardzo lubię precyzyjny styl oferowany przez języki wywodzące się z C i wręcz bym go uściślił, np. wyrzucając możliwość zapisania bloku kodu bez nawiasów klamrowych.

    10. Przeciążanie operatorów to zło. Można nim sobie naprawdę nieziemsko zaśmiecić kod, zwłaszcza jeśli będziesz się bawić w rzeczy typu „podmienianie domyślnej implementacji w obrębie przestrzeni nazw” czy wspomniane w innym podpunkcie „podmienianie klas typów”. Później ktoś inny będzie czytać go i kląć pod nosem, zastanawiając się, jak bardzo nap**** miał jego autor w głowie, gdy go pisał.

    12. Po co dwa mechanizmy służące do tego samego? Albo cechy, albo domieszki.

    Moja wizja jest taka, że język powinien być prosty, precyzyjny, a jednocześnie mieć dużą siłę wyrazu i ułatwiać życie tam, gdzie faktycznie ułatwi to życie. Jest trochę punktów średnio potrzebnych, a w ogóle nie wspominasz o czymś takim, jak współbieżność (i nie mówię tu o wielowątkowości), mechanizm pracy, zarządzanie pamięcią czy zagadnienia związane z bezpieczeństwem i tworzeniem aplikacji WWW.

    KKH -> eee…. PHP jest napisane w C, wszystkie rozszerzenia do niego też są napisane w C…

  32. @zyx

    Te propozycje to raczej lista możliwych opcji niż bardziej spójna wizja.

    7. Niektórzy mówią funkcjonalny inni funkcyjny. Z tego co czytam tu i ówdzie to zamiennie oba terminy są używane. Jeżeli chodzi o referencje, to samo ich usunięcie oczywiście nie stworzy nam nagle języka funkcyjnego. Natomiast brak referencji skłania bardziej do pisania „pure functions”
    8.Generalnie się zgadzam. Jednak w sumie jeżeli mamy takie metody statyczne o których mówisz to zawsze można je umieścić w przestrzeni nazw w której znajduje się jakaś klasa zamiast w samej klasie.
    9. Nie mówię o likwidacji klamr „{}” tylko nawiasów okrągłych. Pisanie kodu bez nawiasów klamrowych również bym uniemożliwił. Natomiast jak już pisałem, nawiasy okrągłe często psują czytelność, zwłaszcza w ifach, gdzie zwykle i tak warunek mieści się pomiędzy słowem kluczowym „if” a otwarciem bloku „{„.
    10. I zło i nie zło. Jest złe, jeżeli ktoś używa tego bez zastanowienia, np. w c++ używanie operatora przesunięcia bitowego w cout i cin (wtf!?). Natomiast dobro jeżeli używa się go w sposób przemyślany, wtedy ułatwia czytanie kodu. Załóżmy, że mamy klasę „Patyk”

    class Patyk {
        public dlugosc = 0;
    }
    $a = new Patyk;
    $a->dlugosc = 10;
    
    $b = new Patyk;
    $b->dlugosc = 15;
    

    Chcąc porównać dwa obiekty klasy patyk względem długości, możemy sobie napisać funkcje compare($a, $b) albo przeciążyć operatory porównania:

    
    //z funkcja
    $res = compare($a, $b);
    if($res == -1){
    echo 'wieksze $a';
    }
    if($res == 0){
    //...
    }
    
    //z operatorem przeciążonym
    
    if($a > $b){
    echo 'wieksze $a';
    }
    //...
    

    12. Z mixinami chodziło mi o możliwość miksowania traitów w czasie kreacji nowej instancji klasy, tak jak to jest w linku ich dotyczącym.

    Co do reszty rzeczy to są one bardziej związane z implementacją interpretera niż z samym językiem. Natomiast bezpieczeństwem każdy musi się zająć we własnym zakresie. Niestety na poziomie języka niewiele da się zrobić, poza zabezpieczeniem wewnętrznych funkcji przed różnego rodzaju błędami związanymi z pamięcią. Generalnie nie czuje się kompetentny w roli eksperta ds. bezpieczeństwa 😉

  33. KKH pisze:

    @Zyx

    „KKH -> eee…. PHP jest napisane w C, wszystkie rozszerzenia do niego też są napisane w C…”

    Nie czytałeś uważnie. napisałem:

    „A może BARDZIEJ otworzyć PHP na pisanie rozszerzeń w C? Ani manual, ani społeczność, ani materiał na zfce NIE PROMUJE pisania takich WSTAWEK. Może słabo szukalem, a może nikomu to nie jest do szczęścia potrzebne.”

    Nieprawda?

    (*) W codziennych projektach (projekty w PHP a nie rozszerzenia dla języka PHP) uzywa się wstawek w C? – nie albo bardzo rzadko.

    (**) Na egzaminach, rekrutacji itp. istnieje ten temat? – nie spotkałem się.

    (***) manual zachęca? To co ja widzę na „PHP at the Core: A Hacker’s Guide to the Zend Engine” nie zachęca. Masa białych plam i komunikat, że „This documentation is still under heavy development.”

    (****) społeczność zachęca? Z lektury blogów, forów, list dyskusyjnych nie wynika by zachęcała.

    A żywi ludzie piszący rozszerzenia są, czego dowodem istniejące rozszerzenia. Czyli równie dobrze można pisać w ten sposób wstawki do rutynowych projektów. CBDO? Nie. Subtelna różnica między: „jest fizycznie wykonalne” a „polecam do codziennej pracy”.

    A zatem śmiało, wyprowadź mnie z ewentualnego błędu. chętnie się czegoś nauczę. Napisaem nawet prowokujące: „Może słabo szukalem”.

  34. @kkh
    jeżeli jesteś zainteresowany pisaniem rozszerzeń do php to polecam książke sary golemon i serie na zend developer zone

  35. Zyx pisze:

    Dla mnie to brzmi zupełnie inaczej, rozszerzenie PHP to rozszerzenie PHP, a biblioteka PHP to biblioteka w PHP. Natomiast powiem Ci, dlaczego na co dzień się tego nie stosuje. C jest trudny, C jest niskopoziomowy, w C zrobienie wielu rzeczy, które są trywialne do zaimplementowania w PHP, wymaga niekiedy nawet miesięcy ciężkiej pracy. Wielu programistów boi się pisania większych rzeczy w C i traktuje ludzi potrafiących to robić z niemal nabożną czcią. Bo faktycznie wymaga to naprawdę niezłego ogarnięcia. Rozszerzenia napisanego w C nie odpalisz tam, gdzie nie masz fizycznej możliwości kształtowania konfiguracji serwera, zatem o ile nie tworzysz jakiejś biblioteki na własny użytek, musiałbyś rozwijać dwie równoległe implementacje: C i PHP. Kto ma na to czas? Kto ma na to pieniądze?

    Jeśli chcesz mieć takie coś, na wstępie wykreśl języki C za jego niskopoziomowość oraz C++ za swoje kalectwo i ułomność, której nawet nie śmie negować jego twórca. PHP musiałby być napisany w czymś zupełnie innym, ale niestety nie ma obecnie dobrze rozwiniętej alternatywy dla tych dwóch języków do szeroko rozumianego programowania systemowego.

  36. @zyx
    Zgadzam się z tobą prawie w 100% oprócz tego, że istnieje alternatywa dla C i C++ w zakresie pisania kodu niskopoziomowego / systemowego. Jest nią język D.Co prawda nie ma tak dużego wsparcia jak C/C++, natomiast już na pierwszy rzut oka wydaje się dużo bardziej przystępny od tego dobrze znanego nam tandemu.

  37. Przypomniała mi się jedna rzecz, która mnie strasznie w php irytuje, gdyby mogli coś z tym zrobić, bo irytuje mnie od wielu lat, wiele bugów przez to miałem. Otóż nie wyrzuca błędu gdy odwołuję się do klucza tablicy w czymś co tablicą nie jest! Przykład:

    $t = null;
    echo $t[0][‚title’]

    I NIC! Zero błędu, chociaż małego NOTICE, ustawiam najbardziej rygorystyczne raportowanie błędów: E_STRICT etc. A php i tak ten kod przeleci i uzna, że wszystko jest okej.

    Dość poważny bug ostatnio mi przez to powstał, ostatecznie kod php wygenerował mi taki html, nie generując żadnego błędu:

    !! Wiecie co to robi? nieskończoną pętlę requestów do serwera! No i wiecha gwarantowana 😉

  38. Wyrzuciło mi przykład:

    <img src=”” onerror=”this.src=””>

    <img src="" onerror="this.src=''">
    
  39. Fakt jest to poważne niedopatrzenie. Myślę, że takich drobnych kwiatków jest więcej. Zastanawiam się czy to jest zgłoszone jako bug.

  40. matipl pisze:

    A mi jest dobrze jak jest. Po co wprowadzać większe zmiany.
    Każdy język ma swoje zalety i wady – to jest piękne.
    W PHP dojdzmy małymi krokami do typów prostych i pełnej obiektowości, a nie zajmujmy się jak ma wyglądać pętla, czy jak przeczyścić php.ini

  41. @matipl:
    Jeżeli chodzi o php.ini, to jednak zmniejszenie ilości opcji w nim wyszło by raczej na dobre – mniejsze różnice między instalacjami to większy komfort dla dewelopera.

  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.