NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: Jak se v PHP obejdete bez statického typování?

V předchozím kvízu, Online test znalostí PHP, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Pavel Jelínek:29.1.2017 14:40

Zdravím,

Jelikož v PHP jsem samouk a nedělal jsem v něm žádný projekt, chtěl bych se zeptat: PHPčkáři, jak můžete žít bez compile-time kontrol? Kdyby má následující úvaha byla správná, již dávno by tvůrci PHP do jazyka přidali níže navržené věci. V čem se tedy pletu?

Můj návrh je tak radiální, že možná vyzní až absurdně - ale pokud mně řeknete jeho nevýhody a vady, bude to pro mne cenné rozšíření obzorů.

=============­=================
= Motivace
=============­=================

Na jazycích typu Pascal, C, C++, C# apod. se mně líbí, že při kompilaci testují existenci každé použité proměnné (či funkce, třídy apod.) a že také testují typovou správnou každého přiřazení, včetně aktuálních parametrů podprogramů (tím myslím i metod, delegátů atd.).

To, co tyto jazyky testují při překladu, lze v PHP ověřit jen proklikáním celé aplikace - a to ještě navíc není pravděpodobné, že se zavolají úplně všechny metody a v nich všechny if/case větve. Zejména ty, které obsluhují nějaké chyby. Jak tedy mohu vědět, že v těchto zřídka volaných větvích nemám chybu, třeba malý překlep v identifikátoru?

V kompilovaných jazycích se refactoring dělá velmi snadno: Pokud cokoli změním (typ či název proměnné, dědění jednoho rozhraní od jiného atd.), pak mně všude vyskáčou chyby kompilace a já je opravím. U většiny změn se dá dobře předvídat, zda mohou či nemohou způsobit chybu, na kterou mě kompilátor neupozorní. (Spolu s nebezpečnou změnou parametrů či chování metody schválně mírně změním i název metody, abych jej musel opravit u všech volání a mohl přitom promyslet, zda jsou i nyní správná.)

Takže jak bez toho PHPčkáři žijí? Logicky bych řekl, že:

  1. Buď všude používají tak důkladné unit testy, které odhalí chybu i v té nejvzácněji používané větvi (formátování datumu s přestupným rokem atd.). Ale to je dřina a ne komfort. Divil bych se, kdyby toto řešení bylo pro tvůrce PHP dostatečným argumentem.
  2. Nebo tyto chyby vývojářům najde jejich IDE prostředí? To se mně zdá nepravděpodobné, když přemýšlím nad syntaxí PHP.
  3. Nebo prostě žijí bez toho a při každém uploadu na produkci se děsí, zda to uživateli nezhavaruje na nějakou chybu, která se při testech neobjevila?

Jiná odpověď mne nenapadá. Pokud nějaký fígl neexistuje, pak se divím, proč tvůrci PHP již dávno nerozšířili jazyk o compile-time kontrolu. Efektivita vývojářů by se tím zvýšila a nemalá námaha tvůrců PHP by se tak mnohokrát vyplatila.

=============­=================
= Verified proměnné
=============­=================

Kdybych byl na místě tvůrců PHP a chtěl novou verzi rozšířit o komfort statického typování (který je v kompilovaných jazycích samozřejmý), udělal bych to takto:

Dosavadní kód PHP by fungoval vesele dál, ale existovala by i alternativní syntaxe, která vynutí výrazně více kontrol v runtime:

Proměnné definované dosavadním způsobem by se nazývaly "unverified", protože chybí kontroly při překladu. Bylo by možno definovat i verified proměnné příkazem třeba "string $a = ...". Nebo jejich typ odvodit: "var $a=...". V jedné funkci/metodě by bylo povoleno používat oba druhy proměnných.

Pokud jde o názvosloví, verified proměnné by mohly začínat také znakem "$", nebo pro odlišení jiným speciálním znakem - anebo žádným. Nevím, co z toho je nejlepší; to poslední by vedlo ke sbližování jazyků (PHP, Java, C#).

Jako verified by mohly být deklarovány všechny druhy proměnných: lokální, parametry, členské proměnné tříd atd. Platil by tam princip z kompilovaných jazyků: proměnnou jednou deklaruj a pak dle libosti přiřazuj a čti. A viditelnost proměnné by - jak je běžné v C a C# - skončila při opuštění bloku (ne metody), což učiní kód delších metod čitelnější. Navíc destruktor zavolaný v předem daném místě kódu, podobně jako Dispose() v C#, se dá použít vedle uvolňování zdrojů i k bezpočtu dalších triků.

=============­=================
= Typové kontroly
=============­=================

S verified proměnnými by nešlo dělat nic, o čem v compile time není jasné, že je to legální. Například předat proměnnou jako parametr funkci, která očekává bool, by šlo jen tehdy, pokud by příslušný typ měl implicitní přetypování na bool. Totéž by platilo, kdyby se do verified proměnné přiřazoval výsledek funkce, která má definovan návratový typ.

Implicitní a explicitní přetypování bych převzal doslova z C#. (Jelikož nedělám Javu, tak nevím, který z těchto jazyků je vhodnější jako předloha.) Kdyby se co nejvíce nových prvků převzalo doslova z nějakého rozšířeného jazyka, pak se sníží zátěž pro multi-jazykové programátory, kteří by se jinak museli učit nazpaměť mnoho rozdílů.

Pokud verified proměnná je typovaná na objektovou třídu, pak z ní lze volat jen metody, properties atd., které v compile-time existují. (Kromě magické metody __get by tedy musel existovat i jiný způsob deklarace properties, bližší C#.)

Kdokoli chce, může dále volat tyto věci dynamicky, ale musí předtím referenci na objekt přiřadit do unverified proměnné.

Takže veškeré současné vymoženosti PHP (existující funkce, třídy atd.) by zůstaly zachovány, ale programátor by je mohl volat pomocí verified proměnných, které mnoho věcí kontrolují.

=============­=================

Zde bych udělal hranici mezi první a (smělejší) druhou částí mého návrhu. Zajímá mne, zda je rozumná ta první půlka - a až potom má smysl uvažovat případně o níže uvedených radikálnějších věcech.

=============­=================
= OOP
=============­=================

Ze C# by se mohla převzít nejen pravidla pro upcast a downcast, ale i genericita (včetně constraints), ko- a kontravariance, typy delegátů - např: bool MujTypDelegatu(strin­g, &int) - a jejich typová bezpečnost. Myslím, že by se tím zásadně usnadnil refaktoring větších aplikací (také je pravda, že IDE pro PHP téměř neznám, takže nevím, jak moc podporují refactoring).

Typ Array toho v současném PHP umí hodně (je optimalizován pro více druhů přístupu); možná by se kód zpřehlednil, kdyby se místo něho používaly generické kontejnery podobné těm ze C#. To navrhuji proto, že nyní není u každého pole ihned zřejmé, zda se používá jako prostá posloupnost, tříděný slovník klíč->hodnota nebo ještě jinak.

=============­=================
= Verified třídy a funkce
=============­=================

Přemýšlím, zda by nebylo účelné zajít ještě dál: Kromě verified proměnných povolit i verified třídy, metody a funkce. Že je programátor zamýšlí jako verified, to by se překladači sdělilo např. klíčovým slovem "verified", nebo raději tím, že by byly deklarovány syntaxí z C / C# (tím myslím dvojtečku za názvem třídy a vynechání slova "function").

Verified třídy by mohly kontrolovat řadu věcí, například že konstruktor volá předkův konstruktor, pokud ten není bezparametrický. Verified metody by mohly kontrolovat typovou správnost výrazů typu:

$a = implode('-', sqrt($b));

Podle mého návrhu totiž platí, že pokud proměnné $a a $b jsou verified, pak se kontroluje typová správnost jejich přiřazení, ale nikoli přiřazení výsledku sqrt() do funkce implode(). Nenapadá mne teď lepší možnost, než říci, že pokud alespoň jednat z těchto dvou funkcí (a stejně tak, kdyby místo nich byly metody) je verified, pak i u tohoto přiřazení kompilátor vyžaduje existenci implicitní konverze. To by opět odhalilo řadu nesrovnalostí již při překladu, mj. platnost konverze objektového typu na druhý (upcast, kovariance...).

Je tu mnoho věcí, které by se musely domyslet a přesahují rozsah této úvahy - například zda i u verified funkcí povolit volání f(...$a), nebo převzít pravidla z C# pro proměnné s variabilním počtem parametrů.

Pokud je žádoucí, aby se moderní jazyky jeden druhému podobaly co nejvíce, pak by se mnou navržené rozšíření syntaxe mohlo zároveň použít ke sblížení jazyků.

Při té příležitosti by bylo možno projít celou syntaxi moderních jazyků a zamyslet se, zda něco podobného nezavést do verified podprogramů v PHP. Napříkad kontrolu, že žádná větev funkce nevynechává return. Existenci výčtových typů. Atd. atd.

=============­=================
= Závěr
=============­=================

Jelikož jsem uchvácen jazykem C# a ve znalosti PHP mám široké mezery, je klidně možné, že některý z mých nápadů, jak PHP posunout směrem k C#, je neobjektivní a dá se to dobře vyřešit nějakým fíglem i v současném PHP (bez toho radikálního rozšíření syntaxe, které navrhuji). Pokud mně řeknete, kde jsem takové chyby udělal - anebo kde můj návrh má nevýhody, které jsem si neuvědomil - pomůžete mně k růstu; předem díky :-)

Jinak končím úvodní otázkou: Opravdu ta absence kompilačních kontrol zkušeným PHPčkářům neschází?
Pavel

 
Odpovědět
29.1.2017 14:40
Avatar
Petr Čech
Tvůrce
Avatar
Petr Čech:29.1.2017 15:54

Také jsem uchvácen C# a když jsem přišel na nutnost používat PHP a začal jsem se ho učit, zděsil jsem se. Ačkoliv mám PhpStorm, což se odvážím tvrdit, že je snad nejlepší PHP IDE a skutečně toho dělá dost, stále mi připadá PHP jako neuvěřitelná mazanina a nechápu, jak v něm může někdo udržovat větší projekt za rozumné námahy.
Na část tvého dotazu odpovídá PHP 7, kde jakási typová kontrola funguje, ale stále to není vůbec dokonalé.
Nicméně se zděšením jsem zjistil, že někomu dynamické typování vyhovuje a považuje ho za svobodu. To znamená, že existují lidé, kteří rádi používají PHP v jeho originální formě.
Další věc je, že PHP prostě takové je a pokud se ti to nelíbí, měl bys přejít na něco jiného. To samozřejmě v praxi nefunguje, velké množství malých a středně velkých projektů je v PHP a tudíž se mu úplně vyhnout nedá.
Změny, co navrhuješ jsou tak radikální, že by se jednalo o jiný jazyk.
Také je to dáno "historicky", PHP je původně primárně skriptovací jazyk, až v poslední (trochu delší :D) době se začal používat jako třeba právě C#, ale na to původně nebyl dělaný.

Nahoru Odpovědět
29.1.2017 15:54
the cake is a lie
Avatar
Honza Bittner
Tvůrce
Avatar
Odpovídá na Pavel Jelínek
Honza Bittner:29.1.2017 16:04

Asi by sis měl zjistit co to znamená kompilovaný jazyk a co to znamená interpretovaný jazyk. To odpoví hodně na tvé otázky. Obě skupiny mají své výhody i nevýhody a samozřejmě existují i různé hybridní jazyky.

Jak již bylo řečeno, nová verze PHP 7 má možnost nastavit režim statických proměnných.

Každopádně nikdo tě v PHP určitě nenutí psát. Můžeš přejít na téměř libovolný jazyk, např. Javu, .NET jazyky, Python, nebo třeba Dart.

Nahoru Odpovědět
29.1.2017 16:04
FIT ČVUT alumnus :-) Sleduj mě na https://twitter.com/tenhobi a ptej se na cokoli na https://github.com/tenhobi/ama.
Avatar
Petr Čech
Tvůrce
Avatar
Odpovídá na Honza Bittner
Petr Čech:29.1.2017 16:57

Nikdo kromě trhu :D. Z velké části tedy, šlo by to i bez PHP, kdyby se chtělo

Nahoru Odpovědět
29.1.2017 16:57
the cake is a lie
Avatar
Neaktivní uživatel:29.1.2017 18:31

Podľa mňa statické typovanie môže znamenať aj výhody, aj nevýhody. Záleží to od toho ako jazyk používaš alebo na čo ho používaš.
Statické typovanie sa podľa mňa hodí na väčšinu vecí. Máš prehľad o tom, ako ktorá štruktúra vyzerá a podobne. Nidky sa ti nestane, aby si nevedel, ako bude výsledná premenná vyzerať po obsahovej stránke. Na druhú stranu, pokiaľ nevieš, s akými presne dátami ideš pracovať, to môže byť nevýhoda.
Dynamické typovanie je práve pre také situácie, kde si nie si istý, s akými dátovými typmi pracuješ (veľké pole a pod.). Ďalšou výhodou môže byť o trochu rýchlejší vývoj.
Ja som zástanca toho názoru, že statické typovanie je ďaleko lepšie ako dynamické vo väčšine prípadov. Vieš, čo kde je uložené, máš o tom prehľad. Proste dynamické typovanie je pre noobov :D
Sám v PHP 7 používam dátové typy a naozaj je to lepšie ako predchádzajúce verzie.

Nahoru Odpovědět
29.1.2017 18:31
Neaktivní uživatelský účet
Avatar
Odpovídá na Pavel Jelínek
Marian Benčat:29.1.2017 20:44

Je to moc dlouhé a tak jsem to moc nečetl,.. ale abych byl upřímný.. kdybych to četl, tak stejně tady jen chytnu záchvat smutku a rozbrečím se tady jako malej kluk,... uroním slzičku, že další uživatel PHP si uvědomil, že s tím asi není něco v pořádku..

K věci.. znám 2 druhy PHP vývojářů Špatné PHP vývojáře a výborné ex-PHP vývojáře. Věřím, že jsem se vyjádřil jasně..

Co se týče dynamického vs. statického typování.. Dynamické typování má opravsu šíleně moc nevýhod a ta největší je ohromný dopad na výkon, který tím dostane totálně na prdku a je to jeden z hlavních důvodů, proč žádný dynamicky typovaný jazyk NEMŮŽE nikdy být ani z dálky stejně výkonný, jako typovaný - proto jsou např., v javascriptu typed array, aby se to výkonově alespoň přiblížilo. V PHP šli opačnou cestou.. a i to nejprimitivnější pole dělají pomocí hashtably..

Statické typování má ale také svoje občasné nevýhody, které ale z pěkné části řeší například anonymní typy a tupple v C#. Osobně ale za tu nejhezčí kombinaci pro programátora považuji třeba Typescript.

Chápu ale, že vnitřně nelze zachovat obojí - tedy výkon a plnou použitelnost pro programátora, prtoo osobně považuji ideální kombinaci staticky typovaného jazyka s anonymními typy.

přináší to s sebou určitou režii navíc pro programátora, ale vrátí se mu to Milionkrát při debugu.

Nahoru Odpovědět
29.1.2017 20:44
Totalitní admini..
Avatar
Odpovídá na Neaktivní uživatel
Pavel Jelínek:1.2.2017 18:01

Rozšíření syntaxe PHP - děkuju všem za reakce.

Samueli, ano: Má své výhody a nevýhody - a proto by toto nové "PHP#" povolovalo obojí: dosavadní i staticky kontrolovanou syntaxi. Ať si každý vybere.

Tím "režimem statických proměnných" zřejmě myslíte declare(stric­t_types=1); ... Vyzkoušel jsem to a zhrozil jsem se. Ono to staticky nekontroluje nic, ani ň. Jenom to hodí runtime (nikoli compile) error, když funkci, která očekává třeba int, předám '3'.

Takže to ani trošku neřeší problém, který jsem nadhodil v úvodu úvodního příspěvku tohoto vlákna.
Pavel

 
Nahoru Odpovědět
1.2.2017 18:01
Avatar
Odpovídá na Honza Bittner
Pavel Jelínek:1.2.2017 18:06

Ano, Honzo, většina skriptovacích jazyků nenabízí komfort statického typování - ale je to opravdu tím, že výhody dynamického v dané situaci převažují? Není to způsobeno spíše historicky - tím, že skriptovací jazyky vznikly jako "lehká váha", kde lze jednoduchou věc docílit pár řádkami kódu?

A pak se ty úspěšnější skriptovací jazyky (jako PHP) velmi rozšířily, načež v nich lidé začali psát čím dál rozsáhlejší aplikace, takže by jim (nejen PHP, ale možná i dalším) mnou navržené rozšíření prospělo, ale nikdo se k tak radikální změně neodhodlal? Pletu se?

 
Nahoru Odpovědět
1.2.2017 18:06
Avatar
Odpovídá na Petr Čech
Pavel Jelínek:1.2.2017 18:18

Petře, máš pravdu, že by to byl (skoro) nový jazyk - ale mně připadá, že by vývojáři dostali do ruky mocný prostředek, který jim zefektivní práci. (Ano, já se nemusím hlásit na místo PHP programátora - ale můj nápad usnadní život těm, které ta firma nakonec najme.)

PHP je velmi rozšířené, je mj. na významné části webových freehostingů - takže kdyby to tvůrci OOP implementovali, bezpočet lidí získá to bezpečí kompilačních kontrol. Zatímco kdyby to někdo vydal jako nový jazyk (navrhuji název PHP# :-) ), pak jej bude mít k dispozici řádově méně lidí.

Myslíte tedy, že tvůrcům OOP mám o tomhle nápadu nějak říci? Ale jakým kanálem? Mám si vygooglit nějaká světové PHP fóra a zmínit to tam?

 
Nahoru Odpovědět
1.2.2017 18:18
Avatar
Pavel Jelínek:7.2.2017 5:48

Co myslíte - mám tvůrcům PHP navrhnout toto vylepšení syntaxe? A jakým kanálem?

 
Nahoru Odpovědět
7.2.2017 5:48
Avatar
Nahoru Odpovědět
7.2.2017 13:55
obsah kocky = r^2 ... a preto vlak drnká
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 11 zpráv z 11.