V čem je PHP navrženo lépe než Java

Existuje spousta článků, které kritizují návrh PHP, nejznámější je asi PHP: a fractal of bad design. Na ten jsem napsal jen poměrně krátkou reakci, protože se zbytkem článku v zásadě souhlasím. PHP je skutečně v mnoha ohledech špatně navržený jazyk. V čem je ale navržený lépe než Java?
Anonymní funkce
Java dlouhou dobu neměla anonymní funkce a tzv. lambda expressions zavedla až letos. Do té doby se používaly jen krkolomné anonymní třídy. V PHP jsou naproti tomu anonymní funkce už pět let (2 roky s podporou $this
) a do značné míry změnily, jakým způsobem se v PHP programuje.
Nutnost používání $this
V PHP se musí při přístupu k vlastnostem a metodám objektů vždy uvádět $this
. V Javě to není potřeba, tedy pokud název vlastnosti nekoliduje s názvem lokální proměnné. Zní to jako výhoda Javy, ale mně dalo dost práce, než jsem si na to zvykl. Při pohledu do kódu Javy často přemýšlím – je tohle lokální proměnná, vlastnost objektu nebo je snad deklarovaná v rodiči? Připomíná mi to doby register_globals
, kde jsem také často dumal, kde se nějaká proměnná vlastně vzala.
Hodnota null
V Javě je hodnota null
implicitně povolená u všech neprimitivních datových typů. Ošetření této hodnoty prolézá kódem jako rakovina. Existuje pokus o řešení v podobě anotace NotNull
, ale její použití a ostatně i definice jsou nejednotné. Jiný pokus o řešení téhle hrůzy je nově uvedená třída Optional
, místo které ale taky můžete dostat null
… V PHP naproti tomu jde do parametru s type hintem poslat null
, jen pokud je volitelný. Je velká úleva nemuset v těle funkce přemýšlet o tom, jestli mi náhodou někde nemůže přijít null
.
Volitelné parametry
Java nezná volitelné parametry. Místo toho si můžete nadefinovat více metod stejného jména, které přijímají různé parametry. V některých situacích se dají použít i varargs, které mimochodem do jazyka byly dohackované neuvěřitelným způsobem (lze je předat jako seznam parametrů nebo jako pole, takže pokud chcete předat jediný parametr obsahující pole, tak se pěkně zapotíte). Přetěžování metod obecně nepovažuji za dobrý nápad, často v kódu koukám na volání a lámu si hlavu tím, co se vlastně zavolá, a odpověď často poskytne až IDE. Přístup PHP, kdy jeden název může mít jen jedna metoda, mi vyhovuje mnohem víc. Jen je škoda, že pokud parametr může být různých typů bez společného předka, musíme oželet type hint. V tomhle se mi líbí Closure, kde se sjednocení různých typů používá zcela běžně.
API pro regulární výrazy
Java má hezký koncept explicitní kompilace regulárních výrazů. V PHP se zkompilované regulární výrazy automaticky kešují a programátor nad tím nemá kontrolu. To nevadí u krátkých skriptů, ale u dlouhoběžících aplikací (např. démonů) to může být problém, obzvlášť pokud někdo vytváří regulární výrazy dynamicky. Potíž s Javou je v tom, že funkce pro pohodlnou práci s regulárními výrazy String.matches
a String.replaceAll
přijímají regulární výraz ve tvaru řetězce a nikoliv jeho zkompilovanou podobu. To by mimochodem bylo jedno z mála smysluplných použití přetěžování. V Javě si tedy můžete vybrat, jestli budete používat pohodlné API s anti-patternem (za který se opakované používání nezkompilovaných regulárních výrazů považuje) nebo API nepohodlné. Mimochodem rozlišit metody přijímající řetězec nebo regulární výraz pomocí názvů replace
a replaceAll
nepostrádá notnou dávku zbabranosti.
Inicializace polí a map
Java dovoluje inicializovat pole konstrukcí {}
, bohužel to jde ale jenom u deklarace. Předávání pohotově vytvořeného pole by se hodilo třeba v testech. Pole si musíte přiřadit do proměnné a tu teprve poslat funkci. Že byste proměnnou přepsali nějakým jiným pohotově vytvořeným polem, na to rovnou zapomeňte a na inicializaci map raději ani nemyslete. Když chcete vytvořit třeba konstantu s mapou, musíte ji inicializovat ve statickém konstruktoru. Guava nabízí alespoň jednoduchou možnost vytvoření ImmutableMap
, na vytvoření Map
ale nic standardního není. V PHP jde pole inicializovat triviálně, včetně přiřazení klíčů.
Pole a seznamy
Java vznikla s podporou polí (array
), později doplnila také seznamy (List
). Obojí se používá v zásadě pro to stejné, některá API používají pole, jiné seznamy. Trochu mi to připomíná nejednotnost PHP v chování k nativním polím a ArrayObject
, zmatek v Javě je ale přeci jen o poznání větší.
Iterace
Java 1.5 přinesla jednoduchou možnost iterace pomocí for each. Pokud ale chcete procházet klíče i hodnoty mapy, tak se i s touto konstrukcí pěkně zapotíte. Asi nejčistší je použití metody entrySet
, která vrací Map.Entry
, na které můžete zavolat getKey
a getValue
. To by se místo:
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
}
… nemohlo psát třeba for (String key, String value : map) {}
? V PHP je iterace klíčů i hodnot polí maximálně pohodlná.
Zbytečné přetypování
V Javě je potřeba na mnoha místech zbytečně přetypovávat. Např. v tomto kódu:
if (x instanceof String) {
f((String) x);
}
To by si kompilátor nemohl domyslet, že x
nemůže být jiného typu než String
? Closure Compiler to zvládne. V PHP žádné přetypování na třídy neexistuje.
Kompilace
PHP skript spustíte a okamžitě běží. Java se nejprve musí zkompilovat, což je např. ve srovnání s Go neuvěřitelně zdlouhavý proces. Kompilace má svou výhodu v tom, že se při ní zaručeně dozvím o chybách, na které by se při běhu ani nemuselo narazit. V PHP tuto roli suplují lintery. Kompilaci a spuštění bych si představoval oddělené. Nerad bych se vzdával všech chyb, o kterých se díky kompilaci dozvím, zároveň bych ale chtěl mít možnost program rychle spustit. Java stejně zkompilovaný bajtkód optimalizuje při běhu, to by to nemohla dělat rovnou ze zdrojového kódu?
Porovnávání řetězců
Řetězce jsou v Javě objekty, takže se nedají porovnávat operátorem ==
. Místo toho musíte použít metodu equals
, takže místo $a != "a"
se obvykle píše podle mě zcela nepřehledné !"a".equals(a)
. Nejhorší ze všeho je, že Java používá tzv. string interning, takže program porovnávající řetězce pomocí ==
bude normálně fungovat až do té doby, kdy z ničeho nic fungovat přestane.
import *
Když PHP zavedlo jmenné prostory, tu a tam někdo naříkal, že nepodporuje import všech objektů z daného jmenného prostoru. Java tuto možnost má a v jednorázovém skriptu se docela hodí napsat si import java.util.*
nebo něco podobného. V seriózních projektech jde ale o anti-pattern, protože co se asi stane, když nějaký jmenný prostor přidá třídu, jejíž název už používáte z jiného jmenného prostoru (ideálně také přes hvězdičku)?
Vlákna a synchronizace
Může být užitečné vytvořit si více vláken, ale způsob, jakým se s nimi potom v Javě pracuje, je tak nízkoúrovňový, že bych se bez toho snad radši obešel. Mluvím především o potřebě synchronizace. Přístup PHP, kde všechno běží v jednom vlákně nebo procesu a o spuštění více věcí najednou se stará webový server, mi vyhovuje mnohem víc. Když už je někdy potřeba dělat víc věcí najednou v rámci jednoho skriptu, tak je to obvykle čekání na výsledek, a to jde v PHP poměrně snadno pomocí futures. Ostatně i v JavaScriptu plném callbacků najednou běží vždy jen jeden kód.
Závěr
Článek se jednostranně zaměřuje na nevýhody Javy ve srovnání s PHP z mého pohledu. Rozhodně nejde o nezávislé porovnání obou jazyků, ale spíše o ukázku toho, kde měli tvůrci PHP šťastnější ruku. Napadají vás další oblasti, kde je Java špatně navržená? Podělte se o ně v diskuzi. Naopak se prosím zdržte kritiky PHP, ať se zaujatý pohled článku zbytečně nerozmělní.
Jestli se Jakub pokoušel srovnat vlastnosti jazyků, tak mi nepříjde zrovna moc objektivní.
Připomína to spíše diskuze typu: odsazovat na mezery nebo tabulátory.
tak to se omlouvám, jsem přehlédl v závěru „Článek se jednostranně zaměřuje na nevýhody Javy ve srovnání s PHP z mého pohledu“
V tom případě považujte můj komentář za zbytečný a klidně ho odmázněte…
Ten komentář rozhodně není bezpředmětný. Titulek je více než bulvární, ale co taky jiného čekat že?
Mimochodem jedno srovnání Javy a PHP už vyšlo kdysi tady: http://zdrojak.root.cz/clanky/java-na-webovem-serveru-porovnani-javy-a-php/
Co znamená „více než bulvární“? Co to je?
Myslím, že z titulku článku, jména autora a názvu serveru je zcela zřejmé, co bude uvnitř – kromě lidí žijících mimo českou web scénu by obsah článku neměl nikoho překvapit.
Také si myslím, že se nejedná o žádné překvapení. Proto mě to překvapilo 8-)
To že se jedná o absolutně subjektivní porovnání, ale titulek zní tak, že tomu tak není.
Objektivní porovnání neexistuje, autor se o ně snaží – nevidím v tom problém. Ale stále jste nevysvětliv, v čem je to VÍC než bulvární?
Rozhodne je bulvarny. Titulok sam o sebe tvrdi cosi, co nie je pravda a co ani clanok netvrdi.
To ale dotyčný netvrdí, já se snažím zjistit, co je ono „víc než bulvární“.
Titulek není „Proč je PHP navrženo lépe než Java“, ale „V čem je PHP navrženo lépe než Java“. Netvrdí tedy, že PHP je v absolutním měřítku navrženo lépe než Java, ostatně hned v perexu na v mnoha ohledech špatný návrh PHP odkazuje včetně postoje autora.
Tak nějak mi z toho srovnání PHP a Javy vychází nejlépe JavaScript s Closure Compilerem a CoffeeScript syntax cukrem :-) Jinak díky za subjektivní srovnání.
Ako to robi ten Closure compiler? Viete niekto o kuse kodu, na ktorom to popisovane chovanie fungovat nebude? Pretoze sa mi (po osmich pivach) zda, ze schopnost stopercentne v dobe kompilacie detegovat „v tejto vetve bude x urcite String“ nebude lahsia ako rozhodovanie halting problemu.
K clanku samotnemu sa vyjadrovat asi nema zmysel, az sa mi nechce verit, ze to pisal Jakub Vrana, lebo to vyzera ako vyblitok stredoskolaka, ktory nepobera zakladne principy tych hrusiek a jablk, ktore zrovnava. (A zaujaty nie som, Javu nenavidim tolko, co PHP.)
Díky za článek.
Jen si nemohu odpustit, k tomu přetypovávání objektů v php.
http://stackoverflow.com/a/3243949/1649965
Pretypovani ano, ale ne z tridy na tridu..
Tak to vezmeme poporade :-)
Anonymní funkce – takze uz to vlastne nevyhoda neni, ze?
this – kod ma byt prehledny, metody kratke, pak na prvni pohled vidite, kde se promenna vzala a this je zbytecny balast. Kdyz uz zkoumate cizi kod, tak IDE pomuze…
null – nepochopil jsem, v cem je to spatne. Kdyz se divam do sveho kodu, tak proste nektere objekty nemusi existovat, to je vec navrhu. Stejne tak ohlidani vstupu aby to nezamorilo zbytek kodu.
Pole a seznamy – temer nenarazim na to, ze by neco chtelo array, asi je to vec nejakych dalsich knihoven. Z toho co pouzivam, tak jen String.split to vraci, to je fakt.
Kompilace – u me spusteni po editaci trva asi sekundu, s tim se da zit. Navic kompiler a IDE rozhodne usetri mnohem vic casu tou kontrolou, kdy vim, ze nema smysl poustet dokud tam je neco cerveny
Porovnávání řetězců – omlouvam se, ale zde musim do PHP – pripada mi silene, ze nekdo povazuje == v PHP (ktere dela zcela jine veci v zavislosti na hodnote operandu a nedodrzuje zakladni logicke predpoklady) za lepsi, nez uplnou kontrolu nad tim jak se porovnava. Ale ono je to priznacne, zazil jsem web v php, kterym string „03“ projde jako „3“, asi se to proste neresi. Berte to tak, ze existuje i svet, kde string je string a lidem zalezi na tom, jak jejich program zpracovava data.
Vlákna a synchronizace – soucasne pristupy uz resi paralelni zpracovani uplne jinak, to co zminujete je stara skola
Mně podobné diskuse nepřipadají úplně fajn ze dvou důvodů:
Stručně: diskuse je zbytečná a navíc není možná.
Když se diskuze udrží v přátelské rovině, tak je to ok. To ale PHPčkaři prostě nevysvětlíš… ne, dělám si prdel :-)
Zajímavé je, že stejně s Jakubem vydal dnes podobný článek tj holowaychuk medium.com/code-adventures/farewell-node-js-4ba9e7f3e52b.
Mne to přijde megaužitečné, protože fakt žijeme ve svejch bublinách. Žádnej sci-fi autor asi nepředpokládat, že v budoucnu (teď), se lidé budou sdružovat do tlup podle jazyka, který používají ke komunikaci se stroji.
Ale vážně, plain JS mne prostě sere, respektive už 4 roky ne, protože mám Closure Compiler a CoffeeScript syntax (jsem konzerva, vím). Hodně zajímavé věci se dějí v ClojureScript, a úplná bomba je elm-lang.org.
Je to všechno o nákladech, jasně. Ale představ si, jakej to je blaženej pocit, když nainvestuješ svůj čas, třeba do Go nebo Om, a najednou cítíš že píšeš násobně lepší kód. Panacea :-)
Od té doby co jsem se naučil Dart považuju Javascript a jeho odvozeniny za to nejhorší co lidstvo vymyslelo…
Já bych hlavně nepřeceňoval to, že člověk používá nějaký konkrétní jazyk. Jazyky se mění, je to spíše módní věc. To co dříve bylo doménou pár specializovaných jazyků, se časem stane mainstream, pak se to zas zavrhne a tak pořád dokola (např. OOP, FP, …).
Pro praktickou každodenní práci stejně záježí na tom, jak jsou dobré knihovny a IDE.
Ale moje nejlepší programy jsem stejně napsal v assembleru (bez knihoven i IDE). :-)
Když nechám stranou všechno ostatní, tak alespoň to porovnávání řetězců. Přiznejme si to, PHP si s nimi dělá co chce. Java je v tomhle ohledu konzistentní – vzhledem k tomu, že String není primitivní typ, == porovnává rovnost objektů, metoda equals jejich hodnoty. To mi přijde jako naprosto lepší, očekávané chování.
A proto v PHP mame ===, kde uz si to nedela, co chce;)
Pominu, že porovnávání přes
equals
se poměrně krkolomně zapisuje, ale hlavně i čte. Dobře, zvítězil purismus jazyka před pohodlím. Nejhorší na situaci v Javě je, že program porovnávající řetězce pomocí==
kvůli interním implementačním detailům většinu času funguje, ale spolehnout se na to nedá.„Nejhorší na situaci v Javě je, že program porovnávající řetězce pomocí == kvůli interním implementačním detailům většinu času funguje, ale spolehnout se na to nedá.“
Co je na tom proboha nejhorsiho? Stejne tak muzes rict, ze pridavani prvku do HashMapy z vice vlaken vetsinu casu funguje, ale spolehnout se na to neda. Nebo ze jsi stokrat pretypoval long na int a fungovalo to, ale po stoprvni dostavas blby vysledek. Jestli se nedokazes drzet pomerne konzistentnich kontraktu co jsou v Jave, tak se nedivim, ze ti je milejsi PHP. Objekty se proste porovnavaji metodou equals – to najdes tak do pate stranky kazde ucebnice Javy pro zacinajici seniory.
==
v Javě porovnává instance.a
a"a"
jsou různé instance,a == "a"
by tedy mělo vždy vrátitfalse
. Že se to kvůli nějakým interním implementačním detailům většinu času nestane, vnímám jako do očí bijící chybu.tohle je (stejne jako vyhrady u deskriptoru a metaclass v Pythonu) naprosto bezpredmetne pro 99.9% Java programatoru. Neni to do oci bijici chyba protoze v normalnim zivote neexistuje priklad kde by tohle hralo roli. Bud chces porovnavat hodnoty a pouzijes .equals() nebo instance a pouzijes ==, v obou pripadech je to konzistentni.
Je to proste dalsi kamen hozeny ve sklenenem svete PHP – kdyz chces pouzivat (nebo posuzovat ci o tom psat) nejaky jazyk, musis prozkoumat nejen navrh, specifikaci ci implementaci, ale i zkyvklosti, knihovny a pripady pouziti.
Aha, takze uz vidim odkud vitr vane… ty nechapes jak Stringy v Jave funguji a mas v tom zmatek. Jestli jsou dva Stringy ruzne instance, tak ti
==
nemuze vratit true. To co jsi napsal je hovadina.Před urážením druhých je vhodné si potvrdit fakta. Nastudujte si prosím v článku odkázaný string interning, případně si to vyzkoušejte:
Toto funguje a vypíše true, protože to jsou stejné instance.Pokud by to byly dvě různé instance, tak je výsledkem false.
Ano, pro někoho kdo nezná dostatečně dobře specifikaci může být velmi matoucí, proč to jsou stejné instance a kdy to tedy nebudou stejné instance. A můžeme to klidně i považovat za nevhodnou nebo dokonce chybnou specifikaci – ale to je věc názoru. Objektivně platí, že dle specifikace je to v požádk, funguje přesně tak jak záměrně má a tedy to není chyba.
Netvrdím, že to není podle specifikace. Tvrdím, že ta specifikace není dobře navržená.
A ono se snad jedna o ruzne instance? Prave kvuli interningu nejedna. Precti si jeste jednou svuj prispevek na ktery jsem reagoval a zamysli se nad tim.
a == "a"
plati prave tehdy, kdyz se jedna o stejne instance. A takea != "a"
plati prave tehdy, kdyz se jedna o ruzne instance.Tvoje tvrzeni:
nedava vubec zadny smysl
Začínající seniory? Co to je? :-O
Jazyk by mohl ušetřit něco práce a NPE, které se projeví zásadně až na produkci, mě taky štvou, ale co je největší problém Javy jsou „over-engeneered“ knihovny, které jsou plné AbstractPrdFactoryProviderProviderů. Programátor se na tohle aklimatizuje a pak to píše i ve svém kódu.
Zato třeba nepoužívání this všude považuju za výhodu. V PHP „$this->“ je akorát syntax noise. V Javě fieldy, static fieldy a lokální proměnné rozliší zvýrazňování syntaxe.
Kompilaci za mě provádí IDE při každém uložení souboru, JRebel (http://zeroturnaround.com/software/jrebel/), Spring Loaded (https://github.com/spring-projects/spring-loaded) a jiné provedou reload v JVM a je to. PHP je pro psaní skriptů, rychlý startup, udělat nějakou malou práci a konec. Java není pro psaní skriptů, ale dlouhoběžících serverů, proto kompilace a startup JVM se až tak moc neřeší. Při vývoji si naběhnu aplikační server a hotswapuji pomocí nástrojů výše.
Udeřila mi do očí věta „Java stejně zkompilovaný bajtkód optimalizuje při běhu, to by to nemohla dělat rovnou ze zdrojového kódu?“ To není tak úplně pravda, javac provádí některé optimalizace již při kompilaci (např. constant folding). Optimalizace za běhu jsou hlavně JIT, inlining apod., které dělat při kompilaci nebude tak efektivní, protože nejsou známé profilovací informace o spouštěném kódu.
Co se týče vláken a synchronizace, opět PHP a Java svět je úplně o něčem jiném. PHP je od začátku dělané jenom jako jazyk pro nějaký preprocessing odpovědi na HTTP request a kolem toho je celé stavěné. Java je general-purpose jazyk a spíš vím o více use casech Javy, kdy vícevláknovost potřeba je než není.
A když píšu webaplikaci v Javě, ať používám servlety či něco jiného, v 90 % případů nepotřebuji vědět, že existují jiná vlákna, které v JVM také běží. Framework za mě vytvoří thread pool, na kterém se zpracovávají requesty, connection pool pro připojení k DB a všechny synchronizační drobnosti nechávám na něm, takže když zpracovávám request, taky se na to dívám jako by všechno běželo v jednom vlákně.
První článek tohoto typu, co jsem četla. Nekonečné pošklebky javistů se mi nelíbí – nic není černobílé.
Ještě bych dodala, že začít programovat v php je mnohem jednodušší než v javě. Php je přívětivější a benevolentnější. Také člověk hned vidí, co vytvořil a je mnoho dobře dostupných návodů.
Čekal bych, že ta poznámka „člověk hned vidí, co vytvořil“ patřila hlavně k webovým aplikacím. Jasně, nepochybuju, že v PHP jde napsat a spustit jednoduchá dynamická stránka výrazně rychleji, než v Javě. A hosting pro PHP je pořád běžnější, než pro cokoliv jiného. Sám bych ale raději vždy volil Javu.
Jinak, pokud člověku vadí na Javě věci popsané v článku, může zkusit třeba Scalu.
Stejne porad nechapu, v cem je rozdil, asi bych potreboval priklad. Co je rychlejsiho nez jedna klavesova zkratka?
Ano webovým aplikacím. Celkově jsem chtěla jen poukázat na to, že člověk, který začíná spíš stráví php. Alespoň já jsem to tak měla.
Ani „benevolentnost“ php neznamená, že v tomto jazyce nelze psát dobře. Spíš to závisí na konkrétních týmech, lidech, návrhu. Oba jazyky mají v současnosti své místo, příznivce i odpůrce.
Článek mne zaujal, líbí se mi že neshazuje php a ukazuje i jeho světlé stránky. Haní ho kde kdo, přitom je celosvětově populární a hojně využívaný.
Když píšu servlet v Javě, tak se mi v Eclipse kód průběžně automaticky kompiluje. Není to, pravda, až tak okamžité, jako v PHP, ale nemusím se o to starat. Krom toho, lze předpokládat, že kód bude častěji spouštěn, než vyvíjen. A v takovém případě jasně vyhrává kompilovaný kód.
Osobně jsem odpůrcem benevolentního kódu, protože to umožňuje prasárny a občas je složité najít problém i s přispěním IDE (PhpStorm). V tom mi Java vyhovuje mnohem více a to píšu jako velký příznivce PHP – aktivně jej používám 14 let.
V neprospěch PHP hovoří i původ jako šablonovací jazyk, na který byly pokročilejší techniky naroubovány až dodatečně. Vadí mi i zmatené pořadí parametrů vestavěných funkcí, a to nemluvím jen o funkcí pro stringy (haystack, needle) vs pro pole (needle, haystack).
O zmateném pořadí parametrů vestavěných funkcí slýchávám často, ale není to jen urban legend? Můžeš dát pár příkladů? (A vynechme in_array).
Mě třeba vytáčí
array_map()
vs.array_filter()
, a to vůbec nemluvím o tom, že nefunguje$array->map()
.Třeba
str_replace(needle, replace, haystack)
×substr(haystack, start, [length])
astrpos(haystack, needle)
×explode(needle, haystack)
.Udělal bych to jako neobjektový ekvivalent Javy/C#, tzn.
String.replace(search, replace)
bych zapsal jakostr_replace(String, search, replace)
.Ale jazyk má být homogenní, stačí už jen to přehození parametrů, což se ale nejlépe ilustruje právě na
in_array(needle, haystack)
×strpos(haystack, needle)
.Sorry, to „a“ mezi substr a strpos bylo myšleno jako že jsou zápisy stejné, ne jako rozdělovník mezi dvojím porovnáním. Psal jsem to jako tři různé styly zápisu, kdy první je str_replace, druhý substr+strpos a třetí explode.
Autor pravděpodobně uměl nejdřív skvěle PHP a pak začal s Javou. U mě je to naopak, takže (kdyby se mi to chtělo sepisovat) bych vyjmenoval 1000+ věcí, kde je PHP podle mě zfušovaný jazyk.
Často je to to spíš dané snahou řešit nějakou věc v Javě pomocí přístupu, který člověk používá v PHP (a naopak). Je to stejně jak s cizími jazyky: máte to anglicky dobře, ale angličan by to takhle neřekl :-)
Na okraj: zrovna jsem včera musel v PHP psát něco jako
$value = $this->validate($this->evaluateExpr($this->obtainParam("param")));
a fakt jsem byl rád za všechny ty $this. Ohromě to kód zpřehlednňuje ;-)
Ano zprehlednuje (v ramci php urcite), protoze muze existovat globalni funkce validate.
Kdyby se this nepouzivalo, co by se volalo v nasledujicim kodu, funkce nebo metoda?
$value = validate(evaluateExpr(obtainParam("param")));
O tom to celé je. Kdo ví, jak jsou psány ty ostatní články, které kritizuji PHP. Ty články mohl psát člověk, který perfektně umí Javu a pak začne nebo zkusí PHP. A co udělá? Napíše článek, kde sepíše nedostatky jazyka. Tak proč by nemohl Jakub udělat to samé o Javě? Proč kritizovat jen PHP.
Jak jsi psal, jde o přístup. To co je pro někoho nevýhoda, tak je pro někoho jen vlastnost nebo i výhoda. Krásným příkladem je právě ten tvůj příklad. Pro tebe je to nepřehledný kód, ale já v tom nic špatného nevidím. Právě naopak. Vím k čemu se ty metody vztahuji. Ostatně $this má i své opodstatnění. PHPčko umožňuje do metody vložit funkci. Je to sice blbost, ale stát se to může. Pak má $this smysl – rozlišuje co je metoda a co lokální funkce. Ostatně Jakub tam píše o vlastnostech vs lokálních proměnách. To je to samé. Jak mám vědět, co je co a kde všude je použít.
Že si někdo na sebe naklade pasti (globální proměnné, funkce v metodě (to fakt jde?!)) a pak se do nich chytí imho není důvod k tomu, abych jak to tele musel pořád do omrzení psát a číst „$this->“. Ale je to věc v názoru, někdo trvá na psaní „this.“ i v Javě z těchto důvodů, někdo zase vlastnosti třídy pojmenovává třeba _vlastnost, aby to nepopletl s lokálními proměnnými. To byla jen taková poznámka na okraj, že se to dá vnímat různě.
Pěkný článek. A také krásná ukázka, že žádný jazyk není dokonalý. Každý má své výhody i své nevýhody. Od toho se pak vyvíjí vzájemná nevraživost mezi programátory různých jazyků. Budou hájit ten svůj jazyk, jak je supr, i když nějaké mouchy má, pokud si ovšem uvědomuji, že je má. A zároveň kritizovat ostatní jazyky, jak jsou o ničem a vyzdvihovat jen jejich nedostatky.
Je jedno jaký jazyk kdo použije a jaké nedostatky jazyk má. Podstatný je pouze hotový produkt. A pokud daný jazyk umí vyprodukovat požadovanou aplikaci, tak ho nelze odepsat.
Jen takové šťouchnutí. A vlastně ono to také může být další nevýhoda Javy. Hádám, že tento web je psán v PHP. A pokud javisti tvrdí, že je Java ten nejlepší, tak proč není tento web napsán v Javě? Prostředky na to jsou.
„anonymní funkce“: to $this je sice pěkné, ale koncept Javy mi připadá naprosto v pořádku. Anonymní třída i funkce jsou prostě závislé na rodičovské třídě. Kdyby tomu tak nebylo, není důvod ji tam cpát a ztěžovat tak testování.
„nutnost používat $this“: to je o názoru, podle mne je to naopak přesně to místo, kde si to má „kompiler domyslet“, jak v jiné části článku autor sám protichůdně upřednostňuje.
„Zbytečné přetypování“: nemusí tam být jen String, ale i jeho potomek nebo se tam má pracovat s nějakým implementovaným rozhraním
„hodnota null“: oba jazyky zdá se mi podporují totéž jen jinými prostředky (anotace NotNull)
„volitelné parametry“: nemožnost používat stejná jména pro více metod s jiným typem parametru pak vede k odpornému kódu, kde v PHP vynecháte typovou kontrolu parametru a uvnitř kódu to testujete a podmínkujete, vizte třeba zdrojáky Nette. Dal jsem si pole tříd, třídu nebo id? Atd.
„Iterace“: ty typy tam doplní IDE a na rozdíl od PHP přesně víte, s čím pracujete
„zbytečné přetypování“: stejně jako v minulém bodě, to přetypování zajišťuje, že víte s čím pracujete. Ve volání f() by to mohl udělat sám. Ale nebýt to použito jako argument funkce, mohl tam být potomek Stringu a tímto se omezila viditelnost metod (v PHP se ponechává původní, což pak ve zdrojácích zase valím oči já na ty šílené konstrukce podmínek if instanceOf xxx else…, kdy najednou volaný kód tuší o světě kolem více, než je zdrávo).
„kompilace“: při použití playframeworku to bude zhruba stejné, každé má svá pro a proti. V Javě si ale můžete vybrat, v PHP ne. I když pro HHVM si nejsem jist jak se s tím pracuje a zda to neotvírá nové možnosti.
„porovnání řetězců“: v PHP se tímhle dotýkáte rozdílu mezi == a ===, kdy mi subjektivně dělá potíže na to myslet, zda porovnávám hodnoty nebo instance. Přístup Javy má rovněž výhodu, že lze tu metodu přetížit a později měnit náhled na to, co je stejné, aniž bych měnil svět kolem.
Špatně se mi v Javě pracuje s poli a řetězci. To první proto ani nepoužívám, pro druhé jsou prostě hotové knihovny.
Většina z uvedených nevýhod mi přijdou spíše jako výhody :))
Vacsina clanku je vecou nazoru, a da sa akceptovat ako subjektivny pohlad, ale odstavec Vlákna a synchronizace je mimo. Java Servlet API alebo EJB maju uplne rovnaky single-threaded model ako PHP, kde sa programator nemusi starat o synchronizaci a o beh vo vlaknach sa stara server. Java navyse umoznuje aj pouzivat vlakna (takze napr. ten webserver moze byt napisany v Jave), navyse Java uz pomerne dlho obsahuje thread-safe collections, fork-join framework a dalsie abstrakcie, ktore pracuju na vyssej urovni ako primitivne locky a vlakna.
Můj pohled je ovlivněn tím, že na kód používající synchronizaci narážím poměrně často. Je hezké, že má Java i nástroje vyšší úrovně, ale jak jsem psal – bez těch nízkoúrovňových bych se snad radši obešel. Někdo má možnost volby a někdo se s tím nízkoúrovňovým kódem holt vypořádat musí.
Zájemcům bych doporučil další zdroje
Jednak k null přednášku Null References: The Billion Dollar Mistake
Jak Java obstojí v akumulátor testu Ostaně jaké je řešení v PHP?
A pak ještě 13 let starý článek od Paula Grahama – Přebal Javy
A mně sa zas líbí callbacky.
PHP:
Java:
V Javě potřebuju kvůli kvůli každému callbacku interface a třídu navíc.
Anebo už ne? :-)
ne
ba
Pridavam kritiku na:
Programator je nuteny produkovat opakujuce sa nastavenia lokalizacii pre takmer kazdy string…
Java je jazyk so zbytocne prekomplikovanou syntaxou a obrovskym bremenom spatnej kompatability.
try .. catch local scope – mozna mate na mysli problem nutnosti zavolat close na stream ve finally. Kvuli tomu se musel ten stream deklarovat vne try, ted uz to jde pomoci try (…) {} catch{}, rikaji tomu try with resources a je to od verze 7. Predtim to bylo opravdu na palici. Nebo jde o neco jineho?
Co máte na mysli tím komplikovaným řešením internacionalizace?
Jen jestli se nedela nekdy z architektury tak trochu svatny gral. Jazyk je naprosto odsouzen na zaklade toho, ze nedodrzuje postupy, ktere jsou zrovna trendy. Ale co je skutecne dulezite? Je to efektivita vyvoje a kvalita vyslednych aplikaci. Bylo by zajimave porovnat webove aplikace v ruznych jazycich napriklad z hlediska rychlosti a ceny vyvoje, snadnosti jejich udrzby, jejich bezpecnosti a rychlosti.
Jinak si myslim, ze programovaci jazyky by se daly rozdelit do dvou skupin, ktere bych nazval treba skriptovaci jazyky a „enterprise“ jazyky. Skripovaci jazyky se vyznacuji velkou volnosti pro programatora, jsou casto beztypove, muzete snadno cokoliv zmenit, treba i predefinovat zakladni prikazy jazyka, jsou mene „ukecane“ nez „enterprise“ jazyky. Umoznuji byt kreativni a vymyslet ruzne efektni zkratky, snadno se uci (lua, php4). To je vyhodne, pokud aplikaci dela jeden programator a neni prilis velka (ale ja se domnivam, ze do teto kategorie spada nadpolovicni vetsina webovych aplikaci).
Pokud se jedna o velky projekt, na kterem pracuji cele tymy programatoru a dlouhodobe se intenzivne vyviji, tak se dost zasadne meni pravidla. Moznost cokoliv zmenit a resit to mnoha ruznymi zpusoby je kontraproduktivni a na dulezitosti ziskava dodrzovani presnych pravidel a postupu, omezeni, ktera mohou nebo musi byt zabudovana uz v jazyce.
PHP proslo vyvojem od sablonovaciho jazyka, kde i register globals melo mozna svuj smysl, ke komplexnimu proceduralnimu jazyku pouzivanemu na siroke spektrum webovych aplikaci ve verzi PHP4 az k „javovskemu“ objektovemu modelu PHP5 umoznujicimu vyvijet velke, snadno udrzovatelne aplikace.
Ale oba typy jazyka maji svuj smysl a podle me vzdy budou existovat oba druhy. I do javy tenhle skriptovaci pristup mozna pronika prostrednictvim veci jako je scala (o jave moc nevim, takze se omlouvam, jestli kecam blbosti)
Priklad z praxe: Prisel za nama majitel pizza time (dnes damejidlo), ze by to chtel z Javy prepsat do php, protoze vyvoj sel strasne pomalu: „Ja jim reknu, ze neco potrebuju opravit a musim cekat i dva tri tydny, nez se to dostane na web“.
PS: To bylo tesne pred tim, nez nam to Cupr vyfouknul:)
Porovnanie PHP a Javy, hmm, to si si vybral slabého protivníka:-) Čo tak python, ruby, clojure, alebo nejaký iný jazyk pre mimo-korporátne prostredie?;-)
IMHO je najsilnejšia výhoda PHP, ako jednoduché je s ním začať, ako rýchlo sa dá niečo jednoduché spraviť (pridať výpis dátumu do statickej stránky napr.).
Toto je silná vec a to phpčku beriem. No mám pocit, že veľké projekty sa až tak príjemne v PHP neudržiavajú (to neznamená, že to nie je možné, ani že neexistujú kvalitné veľké PHP projekty).
Článok sa zaoberá hlavne syntaxou oboch jazykov. Áno, príjemná syntax poteší, ale fakt sú veci spomenuté v článku (nech už na ne máme akýkoľvek názor) tie kľúčové, podľa ktorých si vyberáte jazyk?
Jakube, neverím, že obsah Tvojho článku sú dôvody, pre ktoré používaš PHP. Mňa by úprimne zaujímali tie skutočné dôvody. Nenapíšeš niekedy článok PHP vs Python? Alebo PHP vs Clojure?
PHP už zase tak moc nepoužívám. V době, kdy jsem začínal s tvorbou webových aplikací, šlo o zdaleka nejpohodlnější způsob jejich tvorby. K Pythonu mám celkem neutrální vztah. V některých oblastech je zbytečně komplikovaný (např. metaclass nebo deskriptory) a verze 3 podle mě zvolila zbytečně akademický přístup. Clojure neznám.
Díky za připomenutí, čeho všeho jsme se vyvarovali, když jsme si vybrali kotlin (taky nad jvm, umožňuje používat javove knihovny) místo Javy. Vyjmenuju jen body, které pro kotlin neplati: anonymní funkce, null, volitelné parametry, inicializace polí a map, pole vs seznam, iterace, přetypování a porovnávání řetězců. Za minimální cenu (oproti přechodu na php) zmizelo 8/13 nevýhod :)
Vyjmenované body, které řeší Kotlin, jsou shodné i s Groovy, který zase jako nadstavbový jazyk nad JVM používáme u nás. Musím se na ten Kotlin podívat, jestli je tak dobrý jako Groovy :)
Groovy je moc dynamické a proto také výkonnostně omezenější než kotlin. Když v JB chtěli něco, co nahradí Javu tak Groovy také bylo na seznamu ale nakonec vypadlo, určitě se toho na tohle téma dá vygooglit.
V případě Stringů a equals je těch problémů víc.
Když někdo udělá refaktor kódu a změní typ proměnné „operation“ ze Stringu na nějakou více popisnou třídu, tak tenhle řádek kódu bude kompilátor dál tiše považovat za správný, návratová hodnota ale bude od teď navždy false. Zjistit se to dá třeba přes FindBugs. Tohle a nutnost řešit null hodnoty svádí k tomu udělat si někde svoji globální metodu stringEquals(String a, String b). Na tu pak když narazím v kódu, tak si nikdy nejsem na 100% jistý, co vlastně přesně dělá.
Když někdo napíše kód, co jsi uvedl, tak si o problémy vlastně říká sám :-)
Používat příliš obecné typy jako String, int, char atd. pro věci, které nejsou text/číslo/znak/atd. je špatná praktika – zvlášť když jazyk nabízí lepší prostředky jako enumy a třídy.
1) měl bys použít enum nebo vlastní třídu, která lépe popíše daný objekt (operaci), než obecný String, do kterého jde namastit cokoli (což znamená, že bys všude měl ošetřovat i neznámé hodnoty a neustále validovat).
2) místo IF/ELSE můžeš použít switch, který ti ty typy ohlídá
3) když už používat String + IF (nebo když chceš získat obecně booleovský výsledek), tak si aspoň napiš funkci, která provede porovnání, přesně tak, jak chceš – a např. si vzpomeneš, že
"add"
je totéž co"ADD"
, tak to budeš mít hezky na jednom místě v té funkci a nebudeš muset přepisovat všechny výskytyequals()
a přidávattoLowerCase()
.Java ti stejně jako kterýkoli jiný jazyk nezabrání psát blbě a prasit – ale ve srovnání s jinými jazyky k tomu navádí mnohem méně.
Takovéhle články v dnešní době nemají význam. Kdo dělá weby (a to je třeba zdůraznit, na nic jiného se PHP moc nedá použít) v PHP tak asi težko bude řešit jejich převod do Javy. A když už tak pod JVM, protože to přináší přidanou hlavní přidanou hodnotu oproti PHP a tam dnes existuje spousta lepších řešení než legacy Java. Naopak je to stejné, kdo dělá věci v Javě, nebude přecházet na PHP.
Článek tu rozhodně není proto, aby nutil kohokoliv někam přecházet 8-)
Dlhe roky som v PHP vyvýjal plnohodnotné desktop aplikácie, teda nazor ze PHP sa na nic ine neda pouzit okrem webu, je jednoducho chybny
Jinak v jave se zrejme daji delat taky dost zakerne veci. Napriklad tady http://www.okoun.cz/boards/java?f=20140518-202006 se nejakym zahadnym zpusobem predefinovava vysledek 2+2 ;) Viz prispevek „This is evil!“
Jednak je to v Groovy a ne v Javě (byť oboje nad JVM). A jednak, pokud to čtu správně, tak tam předefinoval operátor +, aby dělal něco jiného.
„Evil“ mi to nepřijde, program dělá to, co jsi mu řekl, že má dělat.
Jestli by měl jazyk umožňovat předefinování oprátorů, je zase druhá věc – Java jde spíš cestou jednoduchosti a bezpečnosti – zatímco Groovy ti dává, zdá se, víc volnosti a možností (odpovědnost je na tobě). Díky tomu, že nad JVM lze provozovat více jazyků a vzájemně je kombinovat, tak si vlastně každý může vybrat, co mu vyhovuje.
Ne, jedna se o tento prispevek:
}
njn, tak že se přes Reflection a prasárny typu
setAccessible(true)
něco rozvrtáš, to už je tvoje blbost. Reflection je tu spíš pro autory různých netypických frameworků než pro aplikační programátory, kteří by se pak mohli divit, že se „Java najednou chová divně“.Pokud jde o bezpečnost, může ti v takovém konání zabránit SecurityManager (viz zdroják/javadoc k té metodě).
Hovorit, ze PHP je lepsie ako Java za to, ze v Jave sa multivlaknovost pouzivat MOZE, ale v PHP to nejde je pri najmensom smiesne. V tom je prave ta sila Javy.
P.S.
Momentalne pracujem v Jave, ale v PHP pracujem dlhsie a pracuje sa mi v nom lepsie. Mal som len velke vyhrady k tomuto konkretnemu bodu.
Když by se v Javě dala řešit třeba obsluha IRQ, taky bych to nepovažoval za její výhodu.
A za co by ste to povazoval? Za nevyhodu? Vsak ked to pouzivat nechcem, tak to pouzivat nemusim, preco by mi malo vadit ze to tam je?
Multithreading v Jave je super, zasadne mi ulahcuje kazdodennu pracu.
PHP sice není nejlépe navrženo, ale od verze PHP 5.3 je to už docela slušný kus software. Pokud se držím nějakého postupu, tak těch chyb moc nenadělám a zbytek odchytí testy. Stejně jako v Javě si mohu testovanou třídu spustit přímo v editoru, navíc se zapnutými notickami.
Nevidím potřebu nahrávat skripty na server dřív než po integračních testech – do té doby server není potřebný. Pokud je nutný, tak PHP od verze 5.4 má svůj vlastní HTTP server, který si mohu spustit nad libovolným adresářem a ladit dle potřeby.
Flamewar Java vs. PHP je v dnešní době tak trošku zbytečná, ne? Divím se, kolik lidí se tu na to ještě chytlo. Je to stejně hloupé, jako by bylo hašteření Cobol vs. Fortran nebo Perl vs. Pascal. Nebo možná rovnou parní stroj vs. vodní kolo.
Ať si každý píše v čem chce, je to jeho věc, z velké části daná tím, jakou aplikaci a v jakém kontextu vůbec chce psát. Že je Java i PHP plná nesmyslných konstrukcí je dané dobou jejich vzniku, dlouhou historií a nutností zachovat jakousi zpětnou kompatibilitu. Vývoj dnes probíhá jinde a místo stokrát přemletého nostalgické mektání bych si rád přečetl raději něco jako „Go vs. Swift“, kde opravdu můžeme kritizovat blbě navržená místa a podivovat se, jak autoři jazyka uvažovali.
Go vs Swift – rozhodne máme zájem, pokud se najde někdo schopny to napsat.
Scala, Dart, Hack.. je toho víc. Zahraniční servery jsou toho plné, ale češi si řekli NE. Místo toho se budou hádat, jestli je lépe navržená Java nebo PHP. Přitom z logiky věci – u PHP se o akademický návrh jazyka odborníkem, uvědomujícím si všechny důsledky, nikdy nejednalo. Je to slepenec „jak to lidi chtěli“ ve stylu pejsek a kočička vaří dort.
Kdo se kde hádá, zda je lépe navržená Java nebo PHP?
co treba clanek, nad kterym se tu diskutuje?
Ne, ten o tom není. Pokud to tam vidíte, zkuste si ho prosím přečíst znovu a lépe.
A taky Rust
ja jakekoliv uvahy nad navrhem jazyka php povazuji za zbytecne. Treba takova spicka ledovce:
# null neni vetsi nez -1
xmx@nn:~$ php -r ‚NULL > -1 && exit(0) || exit(1);‘; echo $?
1
# ale je roven nule
xmx@nn:~$ php -r ‚NULL == 0 && exit(0) || exit(1);‘; echo $?
0
# a taky je mensi nez -1
xmx@nn:~$ php -r ‚NULL < -1 && exit(0) || exit(1);‘; echo $?
0
# jak je to dlouho od chvile co nam preskocilo?
Fakt zabavna vec, pokud zkusite napsat nejakou specializovanou tridici metodu…
ono to porovnavani v php je vubec takove usmevne. Napriklad:
xmx@nn:~$ php -r ‚“foo“ == 0 && exit(0) || exit(1);‘; echo $?
0
xmx@nn:~$ php -r ‚“foo“ == TRUE && exit(0) || exit(1);‘; echo $?
0
xmx@nn:~$ php -r ‚0 == TRUE && exit(0) || exit(1);‘; echo $?
1
jasne mohl bych pouzit ===, ale. Dalsi wtf faktor, === porovnava typ a hodnotu, ale pouze pokud datovy typ neni objekt. Pokud to nahodou objekt je, pak === porovnava, jestli jsou stejna instance. Pokud bych chtel u objektu porovnavat typ a hodnotu, musim pouzit ==. Wtf?
No kratkym hledani ve me vyvolava dojem, ze porovnavani v jave taky nebude uplne pruzracne jednoduche http://perso.ensta-paristech.fr/~diam/java/online/notes-java/data/expressions/22compareobjects.html
Jina vec je treba, ze java ma int a Integer se kterymi se jinak pracuje, jinak se prevadeji na string, musite je konvertovat mezi sebou… http://stackoverflow.com/questions/564/what-is-the-difference-between-an-int-and-an-integer-in-java-and-c. Kdyby to melo php, tak vsichni rvou, co je to za prasarnu.
Ale o to nejde. Nikdo asi nechce tvrdit, ze php predstavuje pripad krystalicky cisteho navrhu. Java je navrzena urcite podstatne cisteji. Taky je blbost srovnavat javu a php, uz proto, ze zaber javy je mnohem sirsi – php je specializovane pro web.
Ale zamyslet se bez zaujatosti a emocionalni mlhy nad vyhodami a nevyhodami ruznych jazyku, muze byt podle me uzitecne a myslim, ze neco takoveho je pointa tohohle clanku.
Je pravda, ze v poslednich letech mame mnoho novych technologii a jazyku pro web – ruby, node.js, dart. Nove jazyky maji typicky cistsi navrh, nez jazyky dlouhodobe vyvijene, ale zase imho trpi detskymi nemocemi – jak jsou nasazovany na siroke spektrum problemu, tak se musi vyporadavat s vecmi, ktere uz v zavedenejsich pristupech jsou davno vyresene. Takze i kdyz je dobre znat nove trendy, tak bych byl mozna trochu pro urcity konzervativismus.
Viz SplInt a spol… Ale prakticky se to nepoužívá, protože to je v extenzi.
Ruby je dvacet let stará věc z roku 1995. Stejně jako PHP. Nebýt handicapu, že vzniklo v Japonsku, všechno mohlo být dnes klidně úplně jinak. Jen si to představte, ty miliony zmařených životů programátorů PHP :)
Na třídění přece nic takového nepotřebuji. Stačí mi použít slovník seznamů.
V prvé řadě chci poděkovat za zajímavý článek, který se seriózně pokusil o téma obvykle vyvolávající flame – a myslím, že úspěšně. Jako u každého názoru jsou zde věci, se kterými souhlasím (equals), se kterými už méně (kompilovatelnost), ale je tu jedna věc, která si, myslím, zaslouží upřesnění – a tou je část o vláknech a synchronizacích.
Je potřeba uvědomit, že paralelismus je obtížný. Paralelismus není o pár klíčových slovech navíc, není to o dalších algoritmech, které se člověk musí naučit nazpaměť – je to o novém způsobu uvažování. Relativní jednoduchost a spousta jistot sekvenčního přístupu je pryč. Prokládané výstupy, nedeterminismus běhu programu (s tím spojené obtížné debugování), deadlocky a race condition jsou běžnými a netriviálními problémy. Nastupuje potřeba synchronizovat, díky které lze tyto problémy řešit (či obejít). A to ideálně ne moc, aby nakonec z paralelního programu nebyl sekvenční. Z těchto důvodů, když učíme programování, tak se vyhýbáme paralelismu jako čert kříži – na paralelismus (a distribuované systémy) máme samostatné předměty a dokonce i obor (FI MUNI).
Z toho důvodu je potřeba konstatovat, že díky možnosti pouze jednovlákovému zpracování se PHP vyhnulo velké spoustě problémů, které by bylo potřeba jinak řešit – a které Java řešit musí. A Java to řeší nejen jednoduchými (nízkoúrovňovými) synchronizačními primitivy – mutexy, podmínkovými proměnnými, synchronized. Je nad tím postaveno spoustu tříd – synchronized kolekce, thread pooly, a i ve článku zmíněné Futures – díky kterým lze psát i vysokoúrovňově. Na druhou stranu kvůli snaze synchronizovat co nejméně je občas dostačující (a mnohdy i vhodné) používat i nízkoúrovňové konstrukce – proč nepoužít atomické počítadlo nebo kritickou sekci, pokud mi bude stačit?
Pokud na úlohu stačí sekvenční program, je vhodné ho tak napsat. Paralelismus se dá dělat i na úrovni programů, kdy jeden a ten samý sekvenční program dělá jasně oddělenou část úlohy (*) – příkladem budiž třeba paralelní konverze obrázků či videí – a to lze jak v PHP, tak v Javě. Pokud je však potřeba složitějšího přístupu, tak je potřeba se smířit se synchronizačními možnostmi, které jazyk poskytuje – a ty jsou v Javě jak na nízkoúrovňové, tak vysokoúrovňové.
(*) Takovéto úlohy se nazývají „embarrassingly parallel„.
Děkuji za názor s chladnou hlavou. Podle mě ty nízkoúrovňové konstrukce program tak komplikují, že bych se bez nich raději obešel, stejně jako se obejdu bez obsluhy IRQ, i když ta by někdy taky mohla stačit. Je pravda, že pokud aplikaci navrhuji od základu, tak si mohu vybrat, jaký mechanismus použiji. Ale když pracuji na už existující aplikaci, tak se prostě musím potýkat s tím, co navrhl někdo přede mnou (dokud pnutí nebude tak silné, že to někdo předělá). Takže zdaleka ne vždy mají všichni na výběr.
V Jave je spousta vlastnosti ktere v dnesni dobe nedavaji smysl ale mam pocit ze jste trefil sotva do jedne, vy pisete o vlastnich preferencich. Me ten seznam nedava smysl.
V závěru článku je výzva, ať se v diskuzi podělíte o další oblasti, ve kterých je Java podle vás špatně navržena. Tak sem s nimi!
Prosim :)tučný text
https://en.wikipedia.org/wiki/Lint_(software)
V Javě lze inicializovat pole při vytváření. Např. lze volat metodu takto: printArray(new String[] { „x“, „y“ });
Pokud vám vadí, že tam člověk musí psát new String[], tak to má samozřejmě svůj důvod, který je skrytý v runtime typu pole. (Pokud si nejste jistý o čem mluvím, podívejte se na ArrayStoreException).
Iterace přes prvky mapy: používám
a nevidím v tom problém.
„Java stejně zkompilovaný bajtkód optimalizuje při běhu, to by to nemohla dělat rovnou ze zdrojového kódu?“ – to by dělat mohla, ale s výrazně jiným výsledkem, než když to dělá za běhu. Nemějte obavu, že to inženýři u Sunu zhruba před patnácti lety nezkoušeli.
$this – na jednu stranu je ta konzistentnost PHP fajn, na druhou stranu je „$this->“ syntaktický bordel. Zajímavý kompromis by bylo něco ve stylu Ruby a zavináče – @foo je instanční field, zatímco foo je lokální proměnná. (Bohužel v tom dělají nepořádek metody.)
Optional a null: Pokud se Optional chytne, bude to super. Ve Scale používám Option, což je skoro totéž. Možnost hodit tam null tu sice je, ale v praxi to není moc problém. (Navíc se to nejspíš projeví někde nahlas.) Ale hlavně, pokud máme všude Optional (nebo Option) a nikde null, tak se mi s tím mnohem lépe pracuje díky různým metodám jako filter, map, flatMap apod.
Varargs – tady si PHP s Javou nemají moc co vyčítat. Java to má zpackané, PHP to přímo ani nepodporuje.
Pole, seznamy a inicializace: Dívám se na to tak, že pole jsou pro lowlevel a legacy záležitosti, pro ostatní jsou kolekce. Proto pro pohodlí jsou IMHO hlavní kolekce. Dá se použít například Arrays.asList (funguje jako varargs, byť snad az od Javy 7).
Z tohoto hlediska nemám problém Array vs. List u Javy, zatímco v PHP se obvykle bojím použít něco jiného než array, protože to sice bude na první pohled sedět, ale má to drobné odlišnosti (např. ==) a popravdě nevim, která funkce přijímá ta „objektová pole“ a která ne.
Porovnání řetězců: Asi je o něco lepší java.util.Objects.equals(str1, str2), což řeší i hodnotu null. Jinak v zásadě souhlasím.
Optimalizace přímo od javac – to je otázka nalezení vhodného tradeoffu, rozhodně se nedá říct, že jiný přístup by měl jen výhody. A pokud chceme jinou variantu toho tradeoffu, máme tu nástroje jako ProGuard nebo alternativní JVM.
Konstrukci import něco.* sice nefandím, ale není to takový problém. Pokud je tu nejednoznačnost, najde ji už kompilátor.
To optional je bohuzel v Jave dost zmrsene,
Problem je ze to neni jazykovy konstrukt ale trida jako jakakoli jina. Tzn i tam kde metoda deklaruje
mi misto Optional muze prijit null. Ano je to chyba navrhu metody, nicmene nic to nemeni na tom ze se na to neda spolehnout tak jako ve scale. Tim padem tam nevidim moc vetsi prinos napriklad oproti anotaci @Nullable kde me stejne linter upozorni ze si nekontroluju vysledek na null. Tohle se Jave nepovedlo a trochu se bojim ze nakonec skoncime u
Bohužel Radku, ani ve Scale se na to spolehnout nedá (podle API je to abstraktní třída):
Prostě úzus říká nepoužívat null, pokud nejde o kompabilitu s předchozím kódem. Jak ve Scale, tak zřejmě už i v Javě: http://java.dzone.com/articles/no-more-excuses-use-null
Bohužel ve Scale je v tom teoreticky o něco větší nepořádek. V Javě máme null (nechceme), Optional.none() (chceme) a Optional.of(someValue) (chceme). Ve Scale máme null (nechceme), None (chceme), Some(null) (nechceme) a Some(someValue) (chceme). Oproti Javě tedy máme navíc Some(null).
V praxi v tom nevidím až takový problém – omylem se tam null jen tak nedostane, zbývá jen možnost, že by to udělal zlomyslný programátor.
Jinak proti Nullable má Optional/Option jisté výhody – máme metody ifPresent, map, filter, flatMap, …
Ve Scale by teoreticky mělo jít napsat Option tak, abychom povolili jen None a Some(someValue) a nefungovaly hodnoty Some(null) a null. Chce to mít value classes, což je relativně nová fíčura (2.9 nebo 2.10, z hlavy nevím), určitě je to novější než Option. V praxi jsou s tím ale dva problémy:
Tak jsem si to SafeOption vyzkoušel napsat, není to až taková sranda. Něco funguje, ale zatím bych to nechtěl používat. Bug s hashCode u null hodnoty ve value class zatím ve Scale nebyl opraven.
https://github.com/v6ak/scala-safe-option
Zmínil bych ještě předhotovené věci v PHP, jejiž zpracování v „ručně“ je v Javě prací pro vraha – namátkou webové služby, práce s databází, práce s GUI – u všeho se musíte spoléhat na generátory a pokud vám to vygenerují špatně nebo jinak, než chcete, je pro běžného programátora skoro nemožné to změnit.
Volán web služeb je typický případ – v PHP zvládne i naprostý laik, v Javě abyste si kvuli tomu prostudovali celou specifikaci, přečetli X dokumentací a vyzkoušeli Y tutorialů jen proto, abyste zjistili, že žádný z nich nefunguje ve vašem IDE nebo nelze použít pro váš případ.
To jste si nevybral dobrou oblast, protože zrovna webové služby Java podporuje výborně. Krátký příklad RESTové webové služby:
Vcelku mi přijde, že to je srozumitelné i při prvním čtení (člověk nemusí nic studovat, aby tomu rozuměl). Samozřejmě za předpokladu, že ví, co je to REST, XML a HTTP.
Javě jsem se věnoval už docela dost, i když se teď zabývám C#. Dovolil bych si přidat ke článku pár svých připomínek.
Používání this
Používání this (a super) je good practice. Netřeba měnit návyky.
Hodnota null
Jmenuje se to Null Object Pattern. V OOP standard.
Kompilace Regex
Regex nikdy není ideální volbou pro operace náročné na výkon.
Inicializace polí a map
V Javě žádný zmatek okolo kolekcí není, Java Collection Framework má jednoznačnou strukturu. Pole se využívají primárně pro případy, kdy je výkon kritický. Zvláštní je, že zrovna syntaktický cukr okolo EntrySet vám připadne jako důležitý rozdíl mezi Javou a PHP. Přitom PHP žádný vestavěný ekvivalent HashMap s konstantním přístupovým časem nemá.
Instanceof
Nevím, jak máte nastavené prostředí, ale dobře to asi nebude. Následující kód se na JDK 1.8 bez problémů zkompiluje. Dále doufám, že rozdíl mezi staicky a dynamicky typovaným jazykem vám ve škole zvládli vysvětlit.
Runtime optimalizace
Můžete mi vysvětlit, jak by asi fungovalo runtime optimalizace kódu v ve fázi kompilace? Něco jako super.getCrystalSphereWithAI().optimizeUntilAwesome()?
import *
Pokud se mi sejdou dvě stejné závislosti, musím je od sebe odlišit. Ne problema ani v „seriózních“ projektech.
Multithreading
Tady už si snad děláte legraci. Absence důležité vlastnosti jazyka je pro vás výhodou? Navíc reálný web server, který by neuměl pracovat vícevláknově, mi není znám.
Závěr
Tvůrci jazyka Java nemají „štastnější ruku“, ale JCP a JSR.
Podmínka integer instanceof Integer je v tomto kontextu ekvivalentní s integer != null.
Zkompilovalo by se to, i kdybyste místo public Havran(Integer integer) měl public Havran(Object integer)? To je totiž ta situace, o jakou zde jde. A zřejmě právě proto Jakub nechápe, co jste tím příkladem chtel říct. A já to taky nechápu.
Až na úplně obyčejné pole, které je obdobou LinkedHashMap.
Příklad s instanceof nedává žádný smysl.
import * je v seriózních projektech (např. v Google) zakázaný.
Takže už je možné používat libovolné objekty jako klíče, nebo stále jen int a string? Co se týče instanceof, prosím tedy o objasnění původního příkladu. O importech se přít nebudu, tady má zjevně každá firma jiné konvence. Nicméně bych poznamenal, že balíčky nemají skutečnou hierarchii a import* se tedy nechová rekurzivně. Importuje všechno v daném balíčku, ale ne už třídy ze „sub-balíčků“.
Píšete jen o kompilaci do bytekódu, ale bytekód se narozdíl od php neinterpretuje ale dál překládá pomocí JIT do binarky, to dělá Javu oproti PHP mnohem rychlejší. Mimochodem FB si kvůli tomu nedostatku udělal vlastní VM s JIT pro PHP. Dá se tedy říct, že to největší nasazení PHP se inspirovalo z kvalitne navržené Javy :-)
V Javě dělám a žádná z těch věcí mi nepřijde jako zásadní problém. Buď na ně mám přesně opařný názor (this), nebo nejsou tak časté, aby byly příliš na obtíž (anonymní funkce, regexpy, …) případně ukazují na neznalost autora (vytvoření pole bez přiřazení do proměnné).
Je zajímavé, že jedinou věc, která mi na Javě opravdu fest vadí a se kterou bych 100% souhlasil autor opominul: Neexistence výstupních proměnných.
No nedokážu pochopit, jak někdo může tvrdit, že radši bude všechno dělat v jednom vláknu. Nemám nic proti autorovi, zbytek článku mi přijde vtipně a celkem fajn podaný, ale to zmínka o vláknech, to se jako autor tak moc „vodvázal“ až si prostě řekl, no tak co bych ještě neshodili.NE NE a NE, někdo kdo nemá ponětí o efektivním využití zdrojů nemá co kecat do vláken, za mě velké nepochopení. Jsem rozhořčen. Čus
Proti vláknům jako takovým nic nemám, ale jejich používání v Javě považuji za příliš nízkoúrovňové. Nechci ručně řešit synchronizaci, chci od toho být odstíněn. Webové aplikace v PHP také obvykle využívají více vláken nebo procesů, ale stará se o to už webový server.
Jsem velký fanoušek PHP, byť mě některé nedotaženosti hodně se***. Je to jazyk, který asi odpovídá mému mozku a dobře se mě v něm přemýšlí, kód je přehledný. V PHP se dá napsat velmi rychle jednoduchá aplikace nebo web i složitější aplikace. Jako velký problém pociťuji absenci jednoho dobře udělaného webového PHP frameworku – místo toho člověk vybírů mezi Zendem, Nette, Symphony nebo Laravelem. Vyzkoušel jsem leccos, ale u PHP už jsem docela dlouho.