Přejít k navigační liště

Zdroják » PHP » V čem je PHP navrženo lépe než Java

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

Články PHP

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?

Nálepky:

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í.

Komentáře

Subscribe
Upozornit na
guest
115 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
klokane

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.

klokane

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…

LesTR

Ten komentář rozhodně není bezpředmětný. Titulek je více než bulvární, ale co taky jiného čekat že?

Kinkos

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/

Martin Hassman

Co znamená „více než bulvární“? Co to je?

Kinkos

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.

Martin Hassman

Také si myslím, že se nejedná o žádné překvapení. Proto mě to překvapilo 8-)

LesTR

To že se jedná o absolutně subjektivní porovnání, ale titulek zní tak, že tomu tak není.

Martin Hassman

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í?

Dodo

Rozhodne je bulvarny. Titulok sam o sebe tvrdi cosi, co nie je pravda a co ani clanok netvrdi.

Martin Hassman

To ale dotyčný netvrdí, já se snažím zjistit, co je ono „víc než bulvární“.

steida

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í.

foobar

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.)

Michal H

Díky za článek.

Jen si nemohu odpustit, k tomu přetypovávání objektů v php.

http://stackoverflow.com/a/3243949/1649965

icaine

V PHP žádné přetypování na třídy neexistuje.

Pretypovani ano, ale ne z tridy na tridu..

KarelI

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

David Grudl

Mně podobné diskuse nepřipadají úplně fajn ze dvou důvodů:

  • nikdo nemáme takřka žádnou šanci ony nehezké věci na jazycích změnit
  • lidi tohle berou velice osobně: na jedné straně bohorovné shlížení na ty, jejichž jazyk považujeme za podřadný, na druhou stranu iracionální obhajoba jazyka svého.

Stručně: diskuse je zbytečná a navíc není možná.

steida

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 :-)

Já

Od té doby co jsem se naučil Dart považuju Javascript a jeho odvozeniny za to nejhorší co lidstvo vymyslelo…

Jirka Kosek

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). :-)

mmx

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í.

icaine

A proto v PHP mame ===, kde uz si to nedela, co chce;)

jehovista

„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.

h

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.

jehovista

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.

podlesh

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.

jehovista

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 take a != "a" plati prave tehdy, kdyz se jedna o ruzne instance.

Tvoje tvrzeni:

a a "a" jsou různé instance, a == "a" by tedy mělo vždy vrátit
false. Že se to kvůli nějakým interním implementačním detailům většinu
času nestane …

nedava vubec zadny smysl

vaclav.sir

Začínající seniory? Co to je? :-O

Jakub Kulhan

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ě.

Nikol Ježková

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ů.

KarelI

Php je benevolentnější
no prave

člověk hned vidí, co vytvořil
v jave to vidi az za chvili nebo v cem je to jine?

Tomas Dvorak

Č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.

KarelI

Stejne porad nechapu, v cem je rozdil, asi bych potreboval priklad. Co je rychlejsiho nez jedna klavesova zkratka?

Nikol Ježková

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ý.

mikiqex

Také člověk hned vidí, co vytvořil

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).

DavidGrudl

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).

mkoubik

Mě třeba vytáčí array_map() vs. array_filter(), a to vůbec nemluvím o tom, že nefunguje $array->map().

mikiqex

Třeba str_replace(needle, replace, haystack) × substr(haystack, start, [length]) a strpos(haystack, needle) × explode(needle, haystack).

Udělal bych to jako neobjektový ekvivalent Javy/C#, tzn. String.replace(search, replace) bych zapsal jako str_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).

mikiqex

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.

Radek

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 ;-)

icaine

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")));

Vindis

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.

Radek

Ž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ě.

Vindis

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.

pp

„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.

MK

Většina z uvedených nevýhod mi přijdou spíše jako výhody :))

Tibor

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.

Luboš Račanský

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

Svaťa

A mně sa zas líbí callbacky.

PHP:

$o = new Bar;
$callback = [$o, 'foo'];
$this->foobar($callback);

Java:

Bar o = new Bar;
IFoo a = new BarAdapter(o); //implements IFoo
foobar(a); //foobar(IFoo object);

V Javě potřebuju kvůli kvůli každému callbacku interface a třídu navíc.

Anebo už ne? :-)

KarelI

ne

vaclav.sir

ba

lubosdz

Pridavam kritiku na:

  • string objects – zbytocne komplikovane riesena internacionalizacia,
    Programator je nuteny produkovat opakujuce sa nastavenia lokalizacii pre takmer kazdy string…
  • nepochopitelne zavedeny try .. catch local scope vo vnutri funkcie

Java je jazyk so zbytocne prekomplikovanou syntaxou a obrovskym bremenom spatnej kompatability.

KarelI

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?

lenoch

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)

icaine

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:)

Samuel

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?

svatal

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 :)

mschayna

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 :)

M.K

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.

Joh

V případě Stringů a equals je těch problémů víc.

if ("add".equals(operation)) { ...

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á.

Kinkos

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ýskyty equals() a přidávat toLowerCase().

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ě.

Koubel

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.

Martin Hassman

Článek tu rozhodně není proto, aby nutil kohokoliv někam přecházet 8-)

Daniel

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

lenoch

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!“

Kinkos

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.

lenoch

Ne, jedna se o tento prispevek:

import java.lang.reflect.Field; 
public class Main {

public static void main(String[] args) throws Exception {
    Class cache = Integer.class.getDeclaredClasses()[0];
    Field c = cache.getDeclaredField("cache");
    c.setAccessible(true);
    Integer[] array = (Integer[]) c.get(cache);
    array[132] = array[133];

    System.out.printf("%d",2 + 2);
}

}

Kinkos

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ě).

RH

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.

RH

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.

KitSaels
  • Anonymní funkce. Když jsem zjistil, k čemu jsou dobré, oblíbil jsem si je.
  • $this označuje instanční proměnnou. Paráda.
  • S hodnotou null moc nepracuji, ale funguje podle mých představ.
  • Volitelné parametry jsou super. Nahradí mi přetěžování.
  • Regulárními výrazy v PHP šetřím, proto problémy nepociťuji.
  • Používám pole, seznamy, slovníky i množiny. V PHP je na to array(). Sémantiku mám v názvu proměnné a to mi stačí.
  • Iterace používám čím dál méně poté, co jsem objevil skvělé funkce array_map(), array_filter(), array_reduce() a další. Smysl odlišného pořadí parametrů v array_map() pochopil ten, kdo někdy použil víc než dva.
  • Jednoduché přetypování Array na Object je skvělé, pokud potřebuji jako parametr předat Messenger.
  • Porovnání řetězců v Javě mě vypeklo, když jsem v testu porovnával a == „a“. V testu bylo true, ale pokud jsem „a“ dodal ze stdin, bylo false. Vím, proč tomu tak je, ale hledalo se to blbě.

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.

Martin Prokeš

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.

Martin Hassman

Go vs Swift – rozhodne máme zájem, pokud se najde někdo schopny to napsat.

Jiří

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.

Martin Hassman

Kdo se kde hádá, zda je lépe navržená Java nebo PHP?

xmx.

co treba clanek, nad kterym se tu diskutuje?

Martin Hassman

Ne, ten o tom není. Pokud to tam vidíte, zkuste si ho prosím přečíst znovu a lépe.

Jirka Kosek

A taky Rust

xmx.

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?

lenoch

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.

Martin Prokeš

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 :)

KitSaels

Na třídění přece nic takového nepotřebuji. Stačí mi použít slovník seznamů.

Tomáš Brukner

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„.

michal

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.

Dmitrij

Prosim :)tučný text

Zdeněk Troníček

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

for (String key : map.keySet()) {
  String value = map.get(key);
  ...
}

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.

v6ak

$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.

Radek

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

   public Optional<String> maybeString()

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

Optional<String> maybeString = maybeString()
if(maybeString!=null && maybeString.isPresent()){
....
}
David Šauer

Bohužel Radku, ani ve Scale se na to spolehnout nedá (podle API je to abstraktní třída):

scala> val a:Option[Boolean] = null
a: Option[Boolean] = null

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

v6ak

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:

  1. Jeden je implementační, narazil jsem na nějaký bug, tuším NullPointerException v hashCode(). Možná je to dnes již opraveno.
  2. Buď rozbitá zpětná kompatibilita se starým Option, nebo roztříštění na Option a „SafeOption“.
v6ak

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

Vojta

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.

Zdeněk Troníček

To jste si nevybral dobrou oblast, protože zrovna webové služby Java podporuje výborně. Krátký příklad RESTové webové služby:

@Path("/shares/{ticker}")
public class Share {
    @GET
    @Produces("application/xml")
    public XmlShare getInfo(@PathParam("ticker") String ticker) { ... }
    ...
}

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.

Blažoun

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.

public class Havran
{
    public Havran(Integer integer)
    {
        if (integer instanceof Integer)
            Vrana(integer);
    }

    public void Vrana(Integer integer)
    {}
}

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.

v6ak

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.

Blažoun

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ů“.

Daniel Kec

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 :-)

Lemming

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.

Taskkill

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

Miloš brecher

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.

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.