Java na webovém serveru: porovnání Javy a PHP

Dnes na chvíli vybočíme z praktické linie tohoto seriálu a budeme se místo další práce na naší aplikaci věnovat obecnějšímu srovnání Javy na webu s jiným používaným jazykem, a to konkrétně PHP. Podíváme se na oba jak z hlediska jazyka, tak i z pohledu nasazení na server a dostupnosti hostingu.
Seriál: Java na webovém serveru (16 dílů)
- Java na serveru: úvod 8. 1. 2010
- Java na webovém serveru: první web 15. 1. 2010
- Java na webovém serveru: práce s databází 29. 1. 2010
- Java na webovém serveru: práce s databází II 12. 2. 2010
- Java na webovém serveru: lokalizace a formátování 19. 2. 2010
- Java na webovém serveru: autorizace a autentizace 26. 2. 2010
- Java na webovém serveru: autorizace a autentizace II 5. 3. 2010
- Java na webovém serveru: porovnání Javy a PHP 10. 3. 2010
- Java na webovém serveru: Vlastní JSP značky a servlety 17. 3. 2010
- Java na webovém serveru: posílání e-mailů a CAPTCHA 24. 3. 2010
- Java na webovém serveru: píšeme REST API 7. 4. 2010
- Java na webovém serveru: SOAP webové služby 14. 4. 2010
- Java na webovém serveru: hlasování a grafy v SVG 28. 4. 2010
- Java na webovém serveru: Komentáře a integrace s Texy 9. 6. 2010
- Java na webovém serveru: AJAX formuláře 23. 6. 2010
- Java na webovém serveru: implementujeme Jabber 30. 6. 2010
Nálepky:
Historie PHP sahá do roku 1994, kdy Rasmus Lerdorf vytvořil sadu skriptů v Perlu a vydal ji jako balíček „Personal Home Page“, což byl původní význam zkratky PHP. Od této sady skriptů po aktuální verzi 5.3 udělalo PHP velký pokrok (místy bouřlivější, než si jeho uživatelé přáli). Dnešní název jazyka se vykládá jako rekuzrivní zkratka „PHP: Hypertext Preprocessor“.
Na jazyce Java se začalo pracovat už v roce 1991 a první veřejná verze byla uvolněna roku 1995. Jejím autorem je James Gosling. Ke svému názvu Java údajně přišla podle slangového označení pro kávu, kterou programátoři rádi pijí. I tento jazyk se průběžně vyvíjí a dnes je ve verzi 6. Za vývojem Javy stojí firma Sun Microsystems (dnes součást Oracle Corporation).
Programovací jazyk
Programovací jazyky dělíme do skupin podle různých kritérií. Např. kompilované vs. interpretované, silně vs. slabě typované, staticky vs. dynamicky typované, objektové vs. procedurální. Podívejme se, jak se v těchto ohledech liší Java a PHP.
Kompilované vs. interpretované
PHP je skriptovací interpretovaný jazyk tzn. jeho skripty nasazujeme na server tak, jak je programátor napsal a zde se interpretují. (což ne všem vyhovuje – např. se bojí, že někdo jejich úžasný program ukradne – a tak se uchylují k různým obfuskacím, které znesnadňují čtení takových skriptů).
S Javou je to trochu složitější. Zdrojový kód napsaný programátorem není možné interpretovat – je třeba ho nejdříve zkompilovat do tzv. bajtkódu (mezikód) a až ten se interpretuje pomocí JRE. Java se tedy zároveň kompiluje i interpretuje – oficiálně se pokládá za interpretovaný jazyk, protože její „zkompilované“ třídy nejsou ve strojovém kódu a neběží přímo na procesoru – je nutné je interpretovat. Formálně tak oba jazyky spadají do stejné kategorie. (PHP ve skutečnosti interně převádí skripty rovněž do mezikódu, čehož využívají mnohé akcelerátory či „bytecode cache“ – pozn.red.)
Za zmínku stojí nástroj HipHop, který slouží k překladu PHP do jazyka C++. Tudíž i PHP může být za určitých okolností kompilované.
Statické vs. dynamické typování
Statické typování znamená, že datový typ proměnné (např. Integer
nebo String
) uvádíme už při její deklaraci. Tudíž typy jednotlivých proměnných známe už v době kompilace a díky tomu odhalíme řadu chyb dříve než v provozu – kompilátor takový program odmítne přeložit. U dynamicky typovaných jazyků dochází ke kontrole až při běhu aplikace. Díky tomu lze psát pružnější (ovšem často taky méně přehledný) kód, ve kterém jedna proměnná nabývá hodnot různých datových typů.
Java je staticky typovaný jazyk – všechny proměnné musíme deklarovat včetně jejich typu, nedeklarované proměnné nemůžeme používat. Zatímco PHP je jazyk dynamicky typovaný.
V PHP tak klidně můžeme napsat následující kód:
if ($a) { $b = 1; } else { $b = "ahoj"; } echo("b = $b");
Až v době běhu, v závislosti na hodnotě $a
, je možné rozhodnout, zda $b
je číslo nebo text. Kdežto v Javě si musíme předem rozmyslet, jaký datový typ bude proměnná b
mít a deklarovat ho.
Silné vs. slabé typování
Toto kritérium se s tím předchozím někdy nesprávně zaměňuje. Silné typování není totéž, co statické, a slabé totéž, co dynamické. Silné typování znamená, že jazyk kontroluje typy proměnných za běhu a odhaluje jejich chybné použití. Java je silně typovaný jazyk. PHP slabě typovaný.
Možná si teď říkáte, že to ani jinak být nemůže – když je Java staticky typovaná, musí být i silně. Není to však pravidlem. Příkladem staticky ale slabě typovaného jazyka je C:
#include <stdio.h> int main () { int a = 123; const char* b = "ahoj"; printf("%dn", a + b); return 0; }
Můžeme „sčítat“ čísla a znaky, ale výsledek asi není to, co bychom očekávali.
Jednotlivé druhy typování nelze obecně považovat za výhodu nebo nevýhodu, každý z přístupů má své zastánce. Já osobně dávám přednost silnému statickému typování. Jednak část chyb odhalíte už při kompilaci a jednak pomáhá psát přehlednější a spolehlivější aplikace. Např. v naší aplikaci máme třídu Podnik
, která má proměnnou cisloPopisne
. Tato proměnná je typu int
a kdekoli v programu se můžeme spolehnout, že v ní bude pouze číslo. Kdyby se do ní uživatel zkoušel dostat pomocí HTTP POST parametru např. řetězec, došlo by k chybě (na rozhraní JSP a Javy).
Další vlastnosti
Oba jazyky jsou objektově orientované (Java od samého začátku, PHP až postupem času, ve verzi 5 byla objektová funkcionalita zásadně přepsána). Dodnes je Java „objektovější“ jazyk – např. ani při psaní „Hello World“ programu se zde nevyhnete práci s třídami.
Oba jazyky jsou otevřené a volně dostupné komukoli (i pro komerční použití). V tomto ohledu má náskok PHP, které je open source od počátku – zatímco k otevření zdrojového kódu Javy došlo až v roce 2006 (licence GPL).
Čím se Java a PHP liší zásadněji je standardizovanost a styl vývoje. Java se rozvíjí v rámci tzv. Java Community Process, ve kterém vzniká specifikace tohoto jazyka/platformy. Tato specifikace se následně implementuje – nejznámější je implementace od Sunu, ale svoji implementaci má i IBM (a vedle nich existuje i řada necertifikovaných implementací). Oproti tomu vývoj PHP je poněkud živelnější. Formální specifikace neexistuje a jako „standard“ je třeba brát hlavní implementaci, která stojí na jádru Zend. Existují i další implementace jako např. výše zmíněný překladač HipHop nebo třeba Quercus.
Životní cyklus aplikace
Aplikace v PHP je tvořena sadou skriptů a její nasazení na server spočívá v jejich nakopírování do příslušného adresáře. Celou dobu se nic neděje a až ve chvíli, kdy přijde HTTP požadavek od klienta, aplikace „ožívá“ – PHP volané webovým serverem interpretuje příslušný skript. Po dokončení HTTP požadavku a odpovědi skončí i běh skriptu a aplikace kromě místa na disku nezabírá žádné další zdroje. Aplikace se tedy načítá s každým HTTP požadavkem znovu.
Webová aplikace v Javě se skládá ze sady JSP stránek, zkompilovaných Javových tříd a případných dalších knihoven. Aplikace se obvykle nasazuje v podobě .war souboru (v podstatě přejmenovaný ZIP archiv). Při nasazení (deploy) aplikace na server dojde k rozbalení tohoto archivu a ke kompilaci JSP stránek. Z nich se nejprve vygenerují javovské třídy ( .java
) a následně se zkompilují na bajtkód ( .class
). Aplikace je inicializována a běží po celou dobu, dokud ji ze serveru neodstraníme (undeploy) nebo alespoň nedeaktivujeme (pokud to server umožňuje).
Z těchto odlišných způsobů vyplývají i možnosti sdílení dat. V Javovské aplikaci v JSP můžeme definovat JavaBeanu pomocí značky jsp:useBean
:
<jsp:useBean id="registraceUzivatele" class="cz.frantovo.nekurak.web.RegistraceUzivatele" scope="session"/>
Tím jsme vytvořili instanci třídy RegistraceUzivatele
a nastavili jsme ji jako hodnotu proměnné registraceUzivatele
. Tato proměnná je platná pro dané sezení uživatele ( scope="session"
). Rozsah platnosti můžeme omezit jen na daný HTTP požadavek ( scope="request"
). Nebo naopak rozšířit na celou aplikaci ( scope="application"
), potom je daný objekt sdílený mezi požadavky všech uživatelů.
V PHP si musíme vystačit s proměnnými sezení $_SESSION
a další stavy aplikace je potřeba ukládat v databázi nebo souborech. Aplikace ve smyslu nějaké ucelené entity tu vlastně neexistuje, protože se jedná o sadu více či méně provázaných skriptů.
Pokud vás nenapadá, k čemu je to dobré, podívejme se na malou ukázku. Nedávno jsem např. psal jednoduchý chat, resp. webové rozhraní k Jabberu. Tento problém lze elegantně vyřešit pomocí EJB, což jsou komponenty běžící v aplikačním serveru a pro nás je zajímavé, že jsou schopné „dlouhodobějšího života“ podobně jako webové aplikace v Javě. Kostra takového EJB vypadá následovně:
@Singleton @Startup public class Jabber1 implements Jabber1Remote { … @Override public void posliZpravu(String mistnost, String prezdivka, String zprava) throws Jabber1Vyjimka { … } @Override public Collection<Zprava> getZpravy(String mistnost, int poradoveCislo) throws Jabber1Vyjimka { … } @PreDestroy public void odpoj() { for (Spojeni s : spojeni) { s.odpoj(); } } @PostConstruct public void inicializuj() throws JabberotovaVyjimka, JMSException, NamingException { pripojXMPP(); } }
Využili jsme tu nové vlastnosti EJB 3.1 a jedná se o trochu specifický případ – klasické EJB 3 nemusí být Singleton a nemusí se vytvářet jeho instance hned po nasazení aplikace (může se vytvořit ad-hoc, až když si ji někdo vyžádá).
Po nasazení komponenty Jabber1
na aplikační server se vytvoří právě jedna instance této třídy (díky anotacím @Singleton
a @Startup
) a díky anotaci @PostConstruct
se spustí metoda inicializuj()
, která naváže spojení s XMPP serverem (Jabber). Toto spojení si držíme po celou dobu života komponenty – tzn. do doby než ji vypneme nebo ukončíme aplikační server. Není tedy vázané na nějaký HTTP požadavek. Ostatně EJB komponenta může na serveru existovat i bez jakékoli webové aplikace.
Webová aplikace si potom tuto EJB komponentu najde pomocí jejího JNDI jména (stejně jako v naší aplikaci přistupujeme ke komponentám PodnikEJB
nebo UzivatelEJB
) a volá její metody pro odeslání zprávy do chatovací místnosti nebo pro vyzvednutí historie zpráv.
Příjemnou vlastností, kterou nám tato architektura přináší, je abstrakce. Pouhou změnou konfigurace můžeme aplikaci rozdělit na dvě části – webovou část provozovat na jednom serveru a EJB komponentu na druhém. Nemusíme si vymýšlet žádný vlastní komunikační protokol – o komunikaci se postará aplikační server (Glassfish např. použije protokol CORBA/IIOP), a z pohledu naší aplikace je vše transparentní – s EJB komponentami pracujeme stejně, ať už se nacházejí na lokálním serveru nebo nějakém jiném.
Zaujaly vás možnosti Javy a chcete se dozvědět o tomto jazyce víc? Akademie Root nabízí školení Základy programovacího jazyka Java a Pokročilejší kurz jazyka Java, na nichž se naučíte, jak tento multiplatformní objektově orientovaný jazyk používat.
Hosting
Zprovoznit si lokálně LAMP nebo třeba aplikační server či pouhý webový kontejner a vedle toho databázi vyjde přibližně nastejno. Ovšem už v době návrhu a analýzy bychom měli myslet na to, kde naše aplikace poběží. V tomto směru má velkou výhodu PHP – je prakticky všude. Najít hosting pro Javu je trochu složitější, ale ne nemožné. V ČR seženete nejlevnější za cca sto korun mesíčně. Jedná se ale o sdílený hosting (společný Tomcat). Můžete si ale pořídit i VPS (virtuální server) za cca 300 Kč, ve kterém lze pohodlně provozovat aplikační server (nebo webový kontejner) podle svého výběru a s vlastní konfigurací. Vedle toho nejlevnější hosting pro PHP stojí pár desetikorun. Zajímavým řešením pro Javu může být služba Google Application Engine, která byla spuštěna minulý rok. Nevyužijete zde zdaleka všechny možnosti JEE platfomy a bude třeba psát javovou aplikaci psát poněkud střídměji, ale na druhou stranu ale Google nabízí poměrně zajímavé ceny, účtované podle intenzity využití (jak už to u cloudových služeb bývá). Pro malé aplikace může být zajímavé, že Google poskytuje „kolem 5 milionů zobrazení stránky měsíčně“ zdarma.
Závěr
Dnes jsme si na chvíli oddychli od praktických příkladů a stručně jsme si porovnali Javu s jiným používaným nástrojem (PHP) z hlediska programovacího jazyka. Vysvětlili jsme si rozdíl v životním cyklu PHP a Java aplikace. A na příkladu webového chatu jsme si ukázali výhody EJB komponent. Příště se zase vrátíme k naší aplikaci v Javě a budeme pokračovat ve vývoji.
Odkazy
- OpenJDK – Plně otevřená implementace Javy.
- PHP – oficiální stránka PHP.
- Java Community Process – proces rozvoje jazyka a platformy Java.
- Úvod do typování – pěkné vysvětlení v češtině na stránkách o Pythonu.
- New Features in EJB 3.1 – Novinky v EJB 3.1 (např. Singletony).
- HipHop for PHP – překlad PHP do C++.
- Java virtual machine – přehled implementací na Wikipedii.
- Google App Engine i s Javou – prezentace v češtině (i ukázka programování).
Celkom pekne zhrnutie. K tym kompilovanym vs. interpretovanym jazykom, dnes asi kazdy vyznamnejsi jazyk ktory bol povodne interpretovany ma uz aj nejaky kompiler. Tusim existuje aj java kompiler ale to som si fakt neni isty. Asi je ale najdolezitejsie aka je najrozsirenejsia implementacia daneho jazyka.
Na jave mi akurat tak trochu vadi taka obcas az prehnana prekomplikovanost aj jednoduchych veci a procesov.
Daj nejake prekomplikovanosti, poradime, pomozeme. Tusis spravne ze existuje Java compiler, ten tam aj vzdy bol (koli prenositelnosti kompiluje do pCode). A dnes existuju Java Virtual Machine (JVM) ktore potom tento kod prelozia za behu do nativneho kodu pocitaca (JIT Just-in-time Compiler).
V clanku sa mi nepaci ze webove aplikacie sa zhrnu pod JSP a EJB. Uz existuju aj nove kniznice a toolkity ako napr. GWT a pripadne pomocou Spring Remoting velmi jednoducho urobit servisnu vrstvu bez potreby pouzitia EJB.
To nebudeme hovorit o buducnosti v podobe OSGi containerov, inych sablonovacich systemoch ako je JSP pripadne generatoroch kodu. Rozumiem ze autor sa snazil to aspon trochu zovseobecnit dany problem ale Java je ozrutna problematika.
dc měl asi na mysli překladače z Javy přímo do nativního kódu, umí to třeba gcj (ale existují i komerční, třeba Excelsior JET). A takový JRockit (dříve BEA, dnes Oracle), ač „klasická“ virtuální mašina, žádnou interpretaci neprovádí a všechno nejdřív kompiluje do nativního kódu. Osobně si myslím, že v případě virtuálních strojů se dá těžko mluvit o kompilaci nebo interpretaci, spousta z nich je prostě „někde mezi“.
S druhým odstavcem naprosto souhlasím. I když budoucnost v podobě OSGi mne děsí, to je jeden z těch příkladů překomplikovanosti. Modulový systém Javě chybí jako praseti drbání a možná ještě víc, ale tohle podle mne prostě není ta správná cesta. Trochu doufám, že tady Rod Johnson vsadil na špatného koně :-)
Network OSGi – krasa. Sa na ten „cloud“ pripojis pekne z Eclipsu. Buildnes a stlacis reload. Ono sa to deployne do centralneho repository a reloadnu sa moduly. No krasa. Uvidime kam to bude viest.
Modulovy system pre Javu zalezi s akeho uhla sa na to pozrieme. Je Maven modulovy system? Na urovni vyvoja iste. Runtime modulovy system je napr OSGi a bezi na nom napriklad Eclipse takze je to uz v podstate overena technologia. Myslim ze niet cesty spat ;-).
Je to tak, OSGi je dneska v podstatě průmyslový standard, a tuším, že i JSRko pro Java Module System či jak se to jmenuje k němu přihlíží. Ale ta classloaderová magie… já prostě nevím.
Ten slabě typovaný příklad není zvolen moc šťastně.
Tak zaprvé, stačí do toho printf místi %d dát %s a výsledek bude korektní (za předpokladu, že ten integer bude třeba 2).
A navíc pro Javu je taktéž definovaná operace sčítání mezi stringem a integerem (i když s jinou sémantikou). To z jazyka ještě nedělá slabě typovaný.
Slabě typovaný je ten, jehož překladač/interpretr dělá ad hoc konverze typů tak, aby to explicitně nemusel dělat programátor. Třeba céčko skoro pokaždé převede pole na ukazatel na první prvek.
Ono statické a slabé typování opravdu nejde moc dohromady, takže někteří autoři dokonce žádné ortogonální rozdělení slabého/silného + statického/dynamického typování nezavádí a říkají, že existují typové systémy statické, dynamické silné a dynamické slabé. Tuším, že jsem to takhle četl v Programming Language Pragmatics, ale nejsem si teď jistý. Každopádně jestli existuje nějaký staticky a slabě typovaný jazyk, pak je to Céčko :-)
long a = 1000*1000*1000*1000;
(a má nyní hodnotu –727379968)
Silné typování mi proto připadá spíš jako falešný pocit bezpečí. U toho PHP aspoň člověk od začátku ví, na čem je.
silne typovanie je predsa o tom, ze do toho longu nepriradis string, nie aku hodnotu tam (ne)priradis
Je to jen banální příklad implicitní konverze int->long, způsobující nepříjemnou chybu, která se navíc projeví pouze v závislosti na konkrétních hodnotách proměnných, a to až za běhu programu, nikoliv při kompilaci.
Chyba bude i v tomto případě (int->float) úplně stejná:
int b = 1000;
float a = b*b*b*b;
(a má nyní hodnotu –7.2737997E8)
Tím chci říct jen to, že každý kód je potřeba testovat, a jakékoliv spoléhání na kontroly překladače (‚je to přece silně typované, tak je to bezpečné‘) se může vymstít.
„Tím chci říct jen to, že každý kód je potřeba testovat, a jakékoliv spoléhání na kontroly překladače (‚je to přece silně typované, tak je to bezpečné‘) se může vymstít.“
Nepochybně, ale silné typování pomáhá mimo jiné:
* chyby najít co nejdříve
* vhodně napovídat metody apod.
* popřemýšlet nad správným návrhem (občas lehce „kopne“ správným směrem)
* refaktorovat kód
* dokumentovat (u slabého typování to můžete uvést tak leda do poznámek, ale nezískáváte tím jiné výhody)
* při odstranění třídy, metody(, …) zjistit, že je stále používána
Není sice všelékem, ale je celkem užitečné a příjemné. Ano, dobrý programátor by IMHO měl zvládnout používat oboje. Stejnětak by IMHO měl dobrý programátor zvládnout programovat bez IDE. Ale pokud chce být maximálně produktivní, pak pro to nevidím důvod.
Menna a typova kontrola je k nezaplateniu. Naviac slabsim programatorom pomaha v niecom comu ja hovorim „Coding by accident“. Napisem nejaku premennu, dam bodku a potom hladam v zozname co by sa najviac hodilo ;-).
Dobry priklad je ale odstranenie metody. Ak to urobim v Jave a da sa to skompilovat tak na 95% je to uz funkcne. Ked urobim to iste v PHP tak preklikavate cely system?
„Ked urobim to iste v PHP tak preklikavate cely system?“
V případě TDD je to trochu přehnané, ale pokud testy z nějakého důvodu nejsou, pak asi není moc jiných cest.
Samozřejmě, i v Javě je Reflection API, já to používám velmi výjimečně (radši mám zpracování anotací pomocí handlerů typu http://projectlombok.org) a třeba ve čtvrt mega zdrojácích se nemusí objevit jediné jeho použití. Všechna použití si pamatuju* (nepočítám nějaké debugovací použití typu getClass().getName() apod., což by vadit nemělo), protože každé potenciálně problematické použití předem důkladně zvažuju. V J2ME na místech, kde mám uvést jméno třídy jako String, používám konstrukci MyClass.class.getName(). Pak se již jistota, že to bude po odstranění oné metody funkční, blíží 100%.
*) Samozřejmě že v projektech, na kterých se podílí více lidí, toto patří do dokumentace.
Hmm, tak to je jako rict, ze jedinou jistotu kterou mate je, ze zadnou jistotu nemate ;-)
Jsem zvědav na porovnání výkonnosti, potřeby systémových prostředků atd. Bohužel my s Javou máme ohledně provozu jen ty nejčernější zkušenosti. Jakmile s aplikacemi pracuje více uživatelů, rychlost klesá limitně k nule. Problém s verzemi Javy je skoro stejný jako u PHP, takže pak už porovnáváme objektový model, štábní kulturu atd. V tom je PHP silně propadající, nicméně to neznamená, že pokud si na to zvyknete, že to není celkem dobrý sluha a těžko hledat lepšího (pro web)…
Podělte se o jaké aplikace se jedná, jaké je nastavení systémových prostředků, verze Javy apod. Protože to jak to popisujete není nutně chyba jazyka.
no dejme tomu aplikace typu spisová služba, oběh dokumentů či GIS aplikace. Problém je v tom, že podobně napsané aplikace v PHP či .NET nevyžadují tak nabušený server. Jakmile je to řešení v Javě, tak požadavky na paměť výrazně narostou. Je to logické vzhledm k filozofii Javy, ale občas je to enormní, pokud s aplikací pracuje několk stovek uživatelů najednou. Nebudu asi zabíhat do detailů, jestli je to aplikačním serverem, způsobem komunikace s persistentním uložištěm atd.
Java je prostě super, logická a přehledná, trochu ukecanější než PHP, nutí vás víc domýšlet každý krok a nutí vás k objektovému modelu. PHP je jednoduchý nenáročný (na naučení i na prostředky) scriptovací jazyk, který se už trochu zlepšil a můžete v ně programovat jak úplně prasárny, tak klasicky sturkturálně nebo celkem slušně objektově a na 99% aplikací vám to bude stačit. howg a pěkný večer
V čem se principiálně liší filozofie .NET a Javy?
Požadavky na paměť u Javy určitě jsou, už jen kvůli JIT, což je ale v tomto případě vyváženo optimalizacemi. Je teda taky možné zvolit např. AOT JVM.
nelisi sa prakticky v nicom. C# a v podstate starsia .NET platforma bola opajcnuta od javi. Dokonca aj niektore nazvy metod maju rovnake ;)
Právěže je to s trochou nadsázky taky můj názor.
Ad problem s verzemi: Pokud se dobre pamatuji, PHP nekolikrat vydalo novou verzi v citelne mire zpetne nekompatibilni. U Javy mozna nejake drobne zpetne nekompatibility byly (nejsem az tak dobry historik), ale rozhodne je na tom v tomto ohledu lepe, nez PHP.
Např. když v Javě 5 zavedli enum, některým lidem přestaly fungovat jejich dosavadní zdrojáky, protože tohle nové klíčové slovo v nich používali třeba jako název proměnné. Ale takováhle nekompatibilita je dost výjimečná a obecně je Java hodně konservativní. Za enum jsou všichni rádi a nová funkcionalita bohatě vyváží tu nutnost přepsat trochu ten starý kód (pokud měl člověk fakt smůlu a tohle slovo pro název proměnných používal).
Soudit, jestli je i v PHP nekompatibilita vždy vyvážena novými užitečnými funkcemi, nechám raději na ostatních (osobně mi přijde, že často ne, soudě alespoň podle reakcí PHP vývojářů).
enum
je asi tak nejzbytečnější rozšíření, co se do Javy 5 dostalo. Je to prakticky převod vzoru „typesafe enum“ do jazyka s minimální úsporou kódu, asi největší přínos je ve správně implementované serializaci. Ale enum-singleton prostě žeru :-)Do té doby ale většina vývojářů používala textové nebo celočíselné konstanty, jejichž problém je jednosměrnost a fakt, že nejsou nijak seskupené. Zjistit zpětně z hodnoty (třeba 1, 0, 5, „blabla“) o jakou konstantu se jedná je prakticky nemožné (leda pomocí relfexe procházet a porovnávat, ale to musím vědět aspoň třídu, ve které hledám). Taky když nějaká hodnota má jako parametr int/String musím se dívat do dokumentace, kde hledat příslušné konstanty – kdežto v případě enumu vím i bez dokumentace, co tam patří a nemůžu tam zadat úplnou blbost (jako třeba natvrdo zadané číslo, které nepochází z žádné konstanty), protože jinak by se mi program ani nepřeložil. Takže IMHO enumy v Javě užitečné jsou.
„typesafe enum“ jde sice použít, ale kdo ho skutečně používal? Většinou jsem totiž viděl kód zaneřáděný těmi textovými/číselnými konstantami.
To asi nebude chyba jazyka ani frameworkov. Java sa pouziva na velke enterprise aplikacie. My prevadzkujeme viacvrstvove Java clustre pre velke organizacie. Ziadny problem ktore zle napisaneho kodu neexistuje. A to niektore dostavaju pekne do tela. Importy 10MB XML suborov radovo 10.000 denne popri beznej webovej pravadzke nad databazou. Tisice uzivatelov/session online.
To jste to dnes poněkud odfláknul.
Co třeba tato témata:
– ukecanost. U PHP stačí nahrát jeden soubor .php a kód se provede. Javu je potřeba složitě nastavovat a ztrácet se ve změti xml
– rozšířenost. Na většinu serverů stačí php nahrát a jede to (PHP je de facto standard)
– rychlost vývoje. Pořádaly se různé závody jazyků (jedno zadání, lidé současně vystartují a měří se čas do výsledku) a Java na tom nebyla moc dobře (je ukecaná)
– podpora IDE. Java má spoustu geniálních IDE s podporou refaktoringu a dalších vlastností, PHP nemá nic pokročilého, protože to z principu jazyka tak hezky nelze
– frameworky pro web
– ORM
atd. atd.
Lze o tom vykládat hodiny a hodiny, to co jste v článku předvedl je bohužel hodně o ničem.
Já takovéto závody v bastlení považuju za naprosto irelevantní. Většina aplikací se udržuje delší dobu, nikdy není napoprvé bez chyb atd.
Java je „ukecaná“, Perl zase umí být extrémně kompaktní (a neudržovatelný). Já za rozumný kompromis pro web považuji Python nebo Ruby.
PHP jako jazyk nesnáším, protože je to fatk ošklivý bastl. Jenže ta dostupnost hostingů a všelijakých těch Drupalů je dost silný argument. Java je rigidní, ale zase má vynikající spolehlivost, možnost refaktoringu (podpora IDE). A tak bych mohl pokračovat u každé myslitelné technologie.
přesně tak
méně kódu == méně chyb
méně kódu == méně kódu, který je nutný refaktorovat a udržovat
Budu-li mít dva velmi podobné jazyky, jeden z nich bude méně ukecaný, je apriori lepší.
PHP je bastl jen pro ty, co v něm neumí psát čistý kód. Nutnost „babrat se v problémech PHP“ je věc, na kterou kvalitní vývojář v PHP narazí tak jednou za několik týdnů a většinou ji vyřeší za 1 minutu díky skvělému PHP manuálu. :)
Ad závody v bastlení – skoro bych se vsadil, že i dobře navržený kód, pokrytý unit testy bude v PHP napsaný dřív, než v Javě.
No jo. Ale projekty kde 10tky az 100vky developerov koduju jeden system niekolko rokov by sa v PHP asi nezvladli. Takze interpoloaciou dojdeme k tomu ze mozno na mensie projekty je PHP v poriadku ale ako vam rastie projekt a komplexnost tak aj uroven bastlenia prerasta nad znesitelnu hranicu.
Nechcem sa hadat, nepoznam PHP natolko dobre ale pokial viem tak pred par rokmi ked sme mi uz prevadzkovali enterprise systemy na Jave tak PHP este malo problem s poolovanim spojenia do databazy. Nehovorim o servroch, nastavovaniach, clustroch, session fail-over, … a podobne. Myslim ze porovnavat akykolvek PHP server s BEA pripadne IBM Java servrami a ich moznostami straca akykolvek zmysel. Bohuzial vacsinu vlastnosti tychto servroch si skutocny zivot vyzaduje.
Nech je Java akokolvek ukecana je ENTERPRISE a skutocne riesit velke napr. bankove systemy na PHP si neviem dost dobre predstavit.
Nevím, co považujete za Enterprise, my tu na PHP vyvíjíme např. řešení s 1 150 000 UIP měsíčně, škálujeme na serverech Amazonu a kód je pokrytý > 1000 unit testy o testy Seleniem ani nemluvě.
To je řešení, které přesahuje, řekl bych, většinu nasazení Javy na webu.
Java je stejně Enterprise jako třeba Cobol nebo Fortran. A já si Cobol ani Fortran neumím představit skoro na nic, to bych pro bankovní aplikace mnohem radši použil to PHP. :))
Takže to že to zvládá tolik lidí není kvůli PHP ale díky Amazonu. Nevidím důvod proč nemít aplikaci pokrytou unit testy a selenium testy.
Stejně tak není problém mít Java aplikaci dobře škálující. Navíc je tu výhoda podpory od Googlu, například GWT.
GWT je ta výhoda, kterou Java má oproti jiným jazykům. Pokud potřebujete v projektu napsat jak server část, tak i část HTML/CSS/JS, tak díky GWT nemusíte opustit Javu, ale v klidu to v ní napsat. Ušetříte hromadu času a výsledné řešení bude lépe udržovatelné.
Co to je za hloupost? Když bude aplikace špatně napsaná nebo jazyk pomalý, neuškáluje ji ani 100 Amazoních instancí. Takhle je to dost výkonné, že by to teoreticky utáhl jeden výkonný (tím myslím „žádná domácí skládačka“) server.
Když je aplikace špatně napsaná, tak má velmi pravděpodobně jistý limit kam může škálovat. Ale škálovat může, například vertikálně. Pokud je jazyk pomalý, tak je to jedno. Bude vás to stát víc peněz, víc počítačů ale možná těch 1 mil UIP dáte.
U horizontálního škálování jde o dvě věci, první zda používáte sessions. Pokud ano, má vaše aplikace dozajista limity. Druhá věc jak vypadá vaše datové úložiště. Dá se rozdělit na více serverů? Více zapisujících nebo jenom čtecích apod.
Pěkný příklad toho, že na jazyku nezáleží podává Facebook. I když už tak přemýšlí, jak jazyk zrychlit. Stojí to peníze. Stejně tak Twitter, odešel od Ruby když už servery byly dražší než práce programátora a přešel na Scalu, tak aby zlevnil svůj provoz. Opravdu to je, jen a jen o penězích, kolik serverů jste ochotni platit.
Je dobře, že vaše aplikace je výkonná – dobře napsaná. Nicméně váš první příspěvek mluvil o tom, že škálujete na Amazonu. Z toho jsem usoudil, že využívá vyrovnávání zátěže podle aktuální návštěvnosti a zvyšuje či snižuje počet zapojených serverů. Protože o tom, škálování je.
BTW, Scala jede na platformě Java a má podobný výkon. (Například o dynamickém Groovy* se to říct nedá.)
*) nemyslím experiment Groovy++
> Stejně tak Twitter, odešel od Ruby když už servery byly dražší
> než práce programátora a přešel na Scalu, tak aby zlevnil svůj provoz.
V kontextu debaty je to sice lhostejné, ale Twitter „neodešel“ od Ruby. To je poněkud nešťastné a reduktivní shrnutí jednoho z nejzajímavějších „incidentů“ z minulého roku.
Prosím čtěte:
* http://www.artima.com/scalazine/articles/twitter_on_scala.html
* http://blog.obiefernandez.com/content/2009/04/my-reasoned-response-about-scala-at-twitter.html
* http://al3x.net/2009/04/04/reasoned-technical-discussion.html
Twitter vyměnil část infrastruktury původně napsané v Ruby (a dle mínění několika významných účastníků debaty napsané špatně) za infrastrukturu přepsanou do Scaly.
Např. celá debata na téma „máme si napsat vlastní messaging system nebo použít RabbitMQ“ je velmi zajímavá a mnohovrstevnatá, bez jednoduchého a instantního závěru. Nebo celá debata o typování, která je pro nezaujatého čtenáře podobně zajímavá.
> GWT je ta výhoda, kterou Java má oproti jiným jazykům. Pokud potřebujete v projektu napsat jak server část, tak i část HTML/CSS/JS, tak díky GWT nemusíte opustit Javu.
Ale podobné věci existují i pro jiné jazyky.
Ale nejsou srovnatelné, co do možností a propracovanosti. Viděl jsem pyjamas pro python, redshift pro ruby a script# pro .net. Jen poslední jmenovaný by se mohl blížit.
Třeba pro Common Lisp existuje parenscript, pro OCaml třeba ocamljs. Pro Haskell existuje spousta různých řešení ve formě EDSL jako HJScript, jmacro nebo přímo jako backend kompilátoru Yhc.
„Stejně tak není problém mít Java aplikaci dobře škálující. Navíc je tu výhoda podpory od Googlu, například GWT.“
Už jsem si myslel, že pletete GAE a GWT, ale ne. Jen bych v daném kontextu spíše očekával zmínku o GAE.
> To je řešení, které přesahuje, řekl bych, většinu nasazení Javy na webu.
Vacsinu asi ano ale az taka exotika vo svete Javy to zas nie je. Zato vo svete PHP asi najvacsacia nie?
> to bych pro bankovní aplikace mnohem radši použil to PHP. :))
Tak to ste asi jediny lebo ja som o takom rieseni nepocul.
Největší?
A co třeba Facebook, Yahoo, Wikipedia?
J2EE jde škálovat u Googlu na Google Apps Engine. Ano, znamená to ve srovnání s klasickými J2EE řešeními určité omezení, ale pořád je to IMHO příjemnější než PHP.
>>> méně kódu == méně chyb
To je sporné, např. už jsem viděl asi sto pokusů, jak regulární výrazy zapsat delší formou, protože kratší zde pro mnoho lidí neznamená lepší, méně náchylné k chybám a podobně, ale spíš právě naopak.
Java se mi sice taky moc nelíbí a její zápis považuji za zbytečně rozvláčný, ale nedělal bych z toho závěry pro udržovatelnost a možnosti refaktoringu (ty jsou u Javy na velmi dobré úrovni). Na kvalitu kódu mají vliv jiné věci, než jestli string do souboru uložím pomocí jednoho nebo dvou příkazů…
„To je sporné, např. už jsem viděl asi sto pokusů, jak regulární výrazy zapsat delší formou, protože kratší zde pro mnoho lidí neznamená lepší, méně náchylné k chybám a podobně, ale spíš právě naopak.“
+1
Někteří lidé jsou vyloženě posedlí minimalizací kódu, někde si přečetli, že čím méně řádek, tím méně potenciálních chyb… jenže ono to neplatí. Když kód uměle nahustíme tak, aby se vešel na méně řádek, riziko vzniku chyb nesnižujeme – naopak spíš vzroste a kód se stává méně přehledným.
Hlavně nezáleží až tak na počtu řádků, jako spíš na počtu větvení, cyklů, jejich vnoření atd. A zároveň ukecanější kód nemusí být na škodu – pokud je napsaný dobře, je z něj na první pohled vidět, co dělá a co byl záměr programátora – zatímco z minimalistického „hackerského“ kódu to často vidět není.
PHP sice neumí nativně ,,server-wide“ proměnné skrze celý server, ale poměrně efektivně k tomu lze využít například Xcache – tím že ukládá do paměti, jsou data uložená skrze něj dostupná pro všechny relace. Primární využití Xcache je ale samozřejmě pro caching.
Skoda, ze se nepojednalo o vhodnosti jednotlivych platforem pro ruzna zadani. To mi v clanku osobne chybi. Ale jinak celkem pekne, diky…
No, mozna by stalo za zminku i toto:
http://quercus.caucho.com/
M.
Vždyť tam je: „Existují i další implementace jako např. výše zmíněný překladač HipHop nebo třeba Quercus.“
ale díky za odkaz, aspoň ho čtenáři nemusejí googlovat.
BTW: používáte někdo Quercus? Já jsem s ním párkrát experimentoval – poprvé to byla úplná tragédie, nepodažilo se mi rozchodit ani spojení do DB, fungovaly jen základní věci (jenže bez DB si většina aplikací ani neškrtne). Když jsem zkoušel nějakou pozdější verzi, tak se mi už spojení s DB navázat podařilo a rozjel jsem v tom i Drupal 6, ale byla tu potíž s češtinou – někde byla OK a jinde rozbitá – a nebylo to tím, že by se mršila na rozhraní DB/aplikace (některé texty z DB byla dobré jiné ne), pravděpodobně některé texty Drupal prohání nějakou funkcí a ta byla v Quercusu špatně implementovaná…
Stalo se, co jsem čekal – tedy, že se vylilo bahno na PHP od lidí, kteří o PHP a jeho schopnostech ví jen nutné minimum.
V podstatě jediné problémy PHP jsou:
a) parametry funkcí jsou nesystémové (což třeba já pomalinku řeším ve své knihovně Googy http://bitbucket.org/jiriknesl/googy)
b) PHP je vyvíjeno nesystémově a pomalu, co fungovalo v jedné verzi, v jiné nemusí bez varování fungovat apod.
Tací, co lijí bahno, nad PHP vývojáří vytváří image bastlířů, přitom dnes už je v PHP stále běžnější, že se využívají návrhové vzory, Test Driven Development, agilní metodiky, akceptační testy v Seleniu a další.
Ještě jedna připomínka:
„Dodnes je Java „objektovější“ jazyk – např. ani při psaní „Hello World“ programu se zde nevyhnete práci s třídami.“ – tohle mě pobavilo. Objective-C je objektovější než Java a žádnou třídu tam pro Hello World nepotřebujete. :) Obdobně Ruby – také objektovější než Java a taky se bez třídy pro Hello World obejdete. :) Já bych spíš řekl, že Java je méně produktivní, ale neřeknu to, protože já o ten flame vůbec nestojím. :)
“ Objective-C je objektovější než Java „
Tak ten byl dobrej .-)
No, ono to tak ale vazne je :)
> Já bych spíš řekl, že Java je méně produktivní, ale neřeknu to, protože já o ten flame vůbec nestojím.
To je dobre, ja tu ciham iba na to :-D.
Toho image as nezbavite tym ze zacnete odkukovat od Javistov co robia a budete po nich opakovat (ooo vy uz ste zacali aj testovat a dokonca v seleniu). Skuste si porovnat mnozstva a kvalitu kniznic, komercnych implementacii Javy, Java servrov, security, moznosti clustrovania, dynamickeho deploymentu, moznosti rekonfiguracie aplikacie pre prislusne prostredie (Nvrstvovy deployment), java zbernice (SOA), pravidlove enginy, … .
Zrazu sa vas pidi svet rozpadne. Mozno nic take nepotrebujete to ale neznamena ze robite s lepsim jazykom. V jave to tiez nemusite pouzivat ale … mozte.
c) chyba typu:
Takova chyba se velmi tezko hleda a v tom me PHP strasne vadi. Podobne jako
$this->promenna
je neco jineho nez$promenna
coz se hleda lepe, ale taky je to opruz.d) rozsahly PHP kod nejde oproti rozsahlemu Java kodu snadno refaktorovat.
Ide o to ze dobry programator to napise rovnako PHP ako aj v C++. Problem je ze nie je vela dobrych progratorov. Na jedneho dobreho pripada priblizne 10 priemernych. S pouzitim, generatorov, odskusanych frameworkov, Aspect Oriented Programming, code waving, … dokazem aspon trochu kludne spavat ze ta aplikacia splna aspon zakladne poziadavky na udrziavanie kodu, bezpecnost, skalovatelnost aj ked ju pise v podstate banda cvicenych opic. Na druhej strane neviem si predstavit platit partu profikov na vyvoj vsetkeho.
Refaktoring nerobime az tak casto ale minimalne orientacia v kode v dobrom nastroji je v Jave velmi jednoducha. Pre niekoho je Java velmi komplikovana a zlozita. Ked sa ale ja pozriem na PHP nevidim ziadny dovod v tom robit. Co by mi to ako malo priniest?
c/
Takova chyba se naopak najde hned.
Interpretr vam to nahlasi.
Staci zapnout error reporting a napsat funkci ktera chyby dava do DB. Je to par radku kodu, staci dat include v kazdem scriptu.
Přiřazení do jiné proměnné interpret neošetří, jen ji založí. S tím si AFAIK neporadí i Duby se svojí inferencí skoro všeho.
Jinak dělat error_reporting includem je… možné, ale máme tu IMHO lepší nástroje (.htaccess a php_value).
Tady je to ještě složitější, vizte http://php.vrana.cz/hiphop.php#d-9810 .
I statické typování jde dělat jinak, příkladem jsou například jazyky Scala, Duby a Groovy++ (všechny ze jmenovaných jsou pro platformu Java). V článku je tam menší nepřesnost.
No tak na platforme javy to nebezi. Da se to zkompilovat do bytecode pro JVM, ale s Javou jako takovou to nema nic spolecneho. Java je programovaci jazyk. Btw. pokud vim tak i PHP se da kompilovat do bytecode.
Jen jsme se neshodli na pojmu „platforma Java“, jinak asi myslíme to stejný.
http://en.wikipedia.org/wiki/Java_%28software_platform%29
Co je bytecode vím, už jsem se v tom i šťoural (reJ (rejava), BCEL, Javassist).
Never. Java je 1. platforma, 2. low-level jazyk pro tuto platformu. Možná tomu tak nechcete říkat, ale v takovém případě jste v těžké menšině.
> Java je staticky typovaný jazyk – všechny proměnné musíme deklarovat včetně jejich typu
Ne, staticky typovaný jazyk se vyznačuje tím, že se typy kontrolují v době kompilace. A Java je staticky i dynamicky typovaná (ne všechny typy umí ověřit v době kompilace).
Také by stálo za to říci, co je to typ.
> Silné typování znamená, že jazyk kontroluje typy proměnných za běhu a odhaluje jejich chybné použití. Java je silně typovaný jazyk. PHP slabě typovaný.
A PHP nekontroluje typy proměnných za běhu? Ale kontroluje a v případě potřeby provede implicitní přetypování, tomu se říká slabé typování. V podstatě každý jazyk, který někdy dělá implicitní přetypování je slabě typovaný. Silné typování nemá nic společného s kontrolou typů za běhu.
> Zdrojový kód napsaný programátorem není možné interpretovat
Možné to asi bude ;-)
> Můžeme „sčítat“ čísla a znaky, ale výsledek asi není to, co bychom očekávali.
Jenže nesčítáte číslo a znaky, ale číslo a adresu, přirozeně je výsledkem číslo.
„Jenže nesčítáte číslo a znaky, ale číslo a adresu, přirozeně je výsledkem číslo.“
Výsledkem je spíše adresa, to se používá ke trikům typu first++ apod. Konverze je tady v tom, že umožňuje automaticky konvertovat adresu na číslo.
Java je silně typovaná proto, že:
* neumožňuje udělat konverzi násilím s z toho vyplývajícím nedefinovaným chováním
* zřejmě neumožňuje provést jakoukoli potenciálně ztrátovou konverzi bez explicitního požadavku
* neumožňuje provést potenciálně neproveditelnou (zde tzn. hrozí ClassCastException) konverzi bez explicitního požadavku
> Java je silně typovaná proto, že … (zde tzn. hrozí ClassCastException) …
Ale ta výjimka bude vyhozena až za běhu (kompilátor na to nepřijde), tedy dynamické typování. Dle mého soudu nezáleží na tom, jestli to musím přetypovat explicitně, ale záleží na tom, že typová chyba nastane za běhu.
Aha, koukám, že reaguju na „Java je silně“ a ne na „Java je staticky“
Ale silně také není protože má implicitní přetypování, silně = bez implicitního přetypování.
Houby dynamické typování. Dynamicky je zjištěno, zda je přetypování správné, protože jinak to nejde.
Programátor v takovém musí explicitně uvést že a na co chce přetypovat.
Tedy, když už to jinak nejde, programátor se může s vědomím* jedné dynamické kontroly rozhodnout explicitně přetypovat.
*) Pokud o tom neví, tak si IMHO nezaslouží označení programátor.
> Dynamicky je zjištěno, zda je přetypování správné, protože jinak to nejde.
Jak jste přišel na to, že to jinak nejde?
> Tedy, když už to jinak nejde, programátor se může s vědomím* jedné dynamické kontroly rozhodnout explicitně přetypovat.
A tím je typová bezpečnost ztracena. Jelikož kompilátor není schopen ověřit typy (což je statické typování), tak jazyk není (čistě) statický. Java je statická i dynamická.
Jinak to nejde, protože za určitých podmínek může nastat kterákoli možnost.
Dobře, Java je převážně statická a pokud se to programátorovi hodí, může se místy na požádání chovat dynamicky.
> Jinak to nejde, protože za určitých podmínek může nastat kterákoli možnost.
Pokud může být návratová hodnota typu Int nebo String, pak bych vracel něco, co je ve funkcionálních jazycích známo jako součtový typ.
Kdybychom měli silnější typové systémy, tak bychom se mohli zbavit mnoha nebezpečných přetypování. Vždyť existují takové jazyky, kde úspěšná typová kontrola implikuje korektnost programu.
Takové jazyky rozhodně neexistují, už proto, že stoprocentně statická typová kontrola je ekvivalentní problému zastavení (a je tedy nerozhodnutelná) :-) Takže staticky typované jazyky samozřejmě mají dynamickou typovou kontrolu, a označují se za staticky typované právě proto, že mají i tu statickou.
Ale naprosto souhlasím s potřebou silnějších (statických) typových systémů – dnešní běžné objektové jazyky (Java, C#) jsou na tom fakt mizerně (jak je na tom Scala nevím, zatím se mi ji nechce moc zkoumat, na můj vkus to vypadá jako strašný akademický slepenec).
V čem je na tom Java mizerně? Pravda, nemá type inference (pro pohodlí) a někdy je potřeba přetypovat (metody typu clone()), ale až tak špatné to IMHO není.
Tak absencí typové inference to začíná (úplně by mi stačila ta lokální), pak tu jsou takové věci jako reference na metody (.NET má, i když na můj vkus trochu divné), typové parametry přístupné za běhu (
new T()
, .NET tuším má) a vůbec pořádné generiky ala Ada, nullable typy (.NET má, v Javě 7 se to tuším bude dát ošvindlovat přes anotace na typech), součtové typy, bezpečné přetypování (jazyková konstrukce proif (obj instanceof Clazz) { Clazz aObj = (Clazz) obj; ... }
), MyType (like Current
z Eiffelu), a když se rozšoupnu, tak třeba ještě pattern matching, rozšiřující metody, líně vyhodnocované typy nebo strukturní ekvivalence namísto jmenné. Zdaleka neříkám, že tohle všechno chci v Javě, to bych se musel zbláznit :-), ale dost z toho mi pekelně často chybí (hlavně pořádné generiky a nullable typy/součtové typy).inference: souhlas, právě se pohlížím po Duby.
genericita: IMHO je čistější použít Factory. Nevím proč, ale celkově mi to nějak spíše vyhovuje. Už jsem měl potřebu používat instanceof (dobře, v ObjectPascalu se to pro rozhraní jmenuje supports), ale to jde obejít předáním Class. Za určitých podmínek zde jde použít to málo type inference, co Java zatím má.
nullable: Jo, to by se mi líbilo.
bezpečné přetypování: Taky jsem o tom snil.
Ke konci už přestávám rozumět.
Líně vyhodnocované typy jsou IMHO spíš knihovní záležitostí než jazykovou (aspoň v podání Javy).
V Javě jde spousta věcí implementovat jako knihovna, ale zároveň je to v Javě hrozně problematické. Níže v diskusi zmiňujete lexikální uzávěry, což je například jedna z naprosto klíčových vlastností jazyka. Java má téměř plnohodnotné uzávěry od verze 1.1, kdy přibyly anonymní vnitřní třídy – jenže je to syntakticky tak odporné, že se to používá mnohem míň, než by mělo. Proto třeba v Javě 7 bude Automatic Resource Management, což je věc triviálně implementovatelná pomocí uzávěrů. Spousta jiných jazyků takové problémy nemá a knihovní řešení ledasjakých problémů naprosto vyhovuje – Java bohužel není ten případ.
> Takové jazyky rozhodně neexistují, už proto, že stoprocentně statická typová kontrola je ekvivalentní problému zastavení (a je tedy nerozhodnutelná) :-)
Ale já nikde nepsal, že ten jazyk bude ekvivalentní částečně rekurzivním funkcím :-) Ono to často ani není potřeba a stačí obecně rekurzivní funkce.
Podívejte se třeba na jazyk Epigram nebo Agda, to jsou staticky typované jazyky (a existují i další). Navíc je typový systém tak silný, že umožňuje kódovat libovolné výroky z predikátové logiky, takže když vhodně zapíšete typy, tak vám kompilace zaručí parciálně korektní program (vzhledem k typům). Epigram dovolí jen obecně rek. funkce a Agda zase umí kontrolovat to, že program skončí (resp. když to nevidí, tak vás varuje abyste program mohl přepsat tak, že to bude vidět; je pravda, že tam se ta konečnost nevynucuje).
> Takže staticky typované jazyky samozřejmě mají dynamickou typovou kontrolu, a označují se za staticky typované právě proto, že mají i tu statickou.
Tahle definice je dost častá, ale přijde mi divná. Představte si, že budu v jazyce provádět drobnou statickou kontrolu, že když uvidím dvě konstanty a mezi nimi operátor +, tak zahlásím chybu pokud oboje nejsou čísla, tedy už provádím statickou kontrolu typů. Znamená to, že jazyk je staticky typovaný?
Ta definice je častá asi proto, že je užitečná :-) To zavedení jediné statické kontroly může být klidně dost výhodné, ale za statický typový systém bych to fakt nepovažoval. Tohle už je teda podle mne čisté slovíčkaření, ale můj skromný názor je: typový systém je od toho typovým systémem, že kontroluje typy všech výrazů. Že je staticky nemůže zvládnout zkontrolovat stoprocentně už jsme si řekli, že zůstávají díry, které by staticky vyřešit šly, to se bohužel taky děje, ale takový už je holt svět :-)
Právě, že ta moje definice mi přijde užitečnější. Takové jazyky existují a odlišují se od ostatních vyšší bezpečností.
Výhodou mých definic je, že jsou jasné.
> Že je staticky nemůže zvládnout zkontrolovat stoprocentně už jsme si řekli …
Není problém udělat to, že když něco neumím staticky zkontrolovat, tak to prohlásím za chybu. Tím už v době překladu zaručím typovou bezpečnost.
Vaše definice jsou jasné, ale v mainstreamu programovacích jazyků nepoužitelné :-) Mezi statickou typovou bezpečností třeba Ady, Javy a PHP jsou obrovské rozdíly – ale vy byste je klidně šmahem hodil do jednoho pytle. To já tedy za užitečné nepovažuju :-)
Jinak, protože ve vyčíslitelnosti se nevyznám, zeptám se: když budeme uvažovat nějaký pořádný statický typový systém, o jak velkou třídu programů přijdeme, když nezkontrolovatelné věci prohlásíme za chybu? Čistě ze zájmu, já fakt nevím, ale odhaduju, že malá nebude.
> Jinak, protože ve vyčíslitelnosti se nevyznám, zeptám se: když budeme uvažovat nějaký pořádný statický typový systém, o jak velkou třídu programů přijdeme, když nezkontrolovatelné věci prohlásíme za chybu? Čistě ze zájmu, já fakt nevím, ale odhaduju, že malá nebude.
Pokud si vystačíme s částečnou korektností programů (program nemusí skončit), tak z hlediska vyčíslitelnosti o nic nepřicházím*, protože stále tam mohu naprogramovat třeba rekurzivní funkce (s typy nebude problém, neboť mi stačí přirozená čísla) nebo odsimulovat Turingův stroj.
Pokud požadujeme i konečnost programů, tak tam už se omezujeme na obecně rekurzivní funkce, a to navíc ty, o kterých to umíme dokázat (resp. typechecker s naší pomocí). Tady už samozřejmě přicházíme o velkou třídu programů, ale myslím si, že v praxi je velmi často žádoucí, když víme, že program pro konečný vstup skončí.
* Pokud bych předpokládal, že má počítač neomezenou paměť.
Vzdali ste to moc rychlo. Java nema dynamicke typy (napr .Net ma). Java JE STATICKY, SILNE TYPOVY jazyk. Keby bola dynamicky typovy, znamenalo by to ze premenne nemaju typ. Ano umoznuje pretypovanie ale podla definicie je podobne ako napriklad C++ staticky typovy jazyk.
Zo slovickami a moznostami sa mozete hrat ale definicia je definicia.
I v PHP proměnné mají typ, jen je určen za běhu. Podobně .NET.
Podle mě je C++ staticky i dynamicky typované. Napište sem tu Vaši definici statického a dynamického typování.
Moje je: Jazyk je (čistě) staticky typovaný, pokud typy kontroluje kompilátor a za běhu již nemůže nastat typová chyba. To znamená, že pokud se program zkompiluje, tak už typová chyba nenastane. Jazyk je dynamicky typovaný, pokud se typy kontrolují až při běhu programu, a tedy může nastat typová chyba za běhu.
> Keby bola dynamicky typovy, znamenalo by to ze premenne nemaju typ.
V dynamicky typovaném jazyce proměnné mají typy (to plyne z toho, že je typovaný).
Skuste relevantne zdroje v najhorsom pripade odporucam wikipediu. Mozte mi povedat priklad objektoveho staticky typovenaho jazyka podla vasej definicie? Taky neexistuje. V praxi su totiz niektore veci potrebne a preto kazdy jazyk obsahuje taketo nebezpecne konstrukcie.
Tieto pojmy sa pouzivaju uz dlhe roky a kazdy rozumie ze staticky typovany jazyk je na 99% staticky. Dokonca Java aj 100% ak nepouzivate explicit type casting co sa dnes vdaka generickym typom listin da velmi lahko dosiahnut.
> V dynamicky typovaném jazyce proměnné mají typy (to plyne z toho, že je typovaný).
Nie nemaju, nemylte si typ premennej s tym na co odkazuje. V dynamickych jazykoch rovnaka premenna moze odkazovat na rozne „hodnoty“ ktore maju typ.
Zbytocne si tu ale vymyslate pojmy a zbytocne ich krutite. Tak ako som napisal – Java JE STATICKY SILNE TYPOVY jazyk. PHP je dynamicky jazyk. By definition.
> Skuste relevantne zdroje v najhorsom pripade odporucam wikipediu. Mozte mi povedat priklad objektoveho staticky typovenaho jazyka podla vasej definicie? Taky neexistuje. V praxi su totiz niektore veci potrebne a preto kazdy jazyk obsahuje taketo nebezpecne konstrukcie.
Definujte prosím, co podle Vás znamená objektový jazyk.
> Tieto pojmy sa pouzivaju uz dlhe roky a kazdy rozumie ze staticky typovany jazyk je na 99% staticky.
Každý evidentně ne.
> Dokonca Java aj 100% ak nepouzivate explicit type casting co sa dnes vdaka generickym typom listin da velmi lahko dosiahnut.
Ale bohužel to přetypování v tom jazyce je.
> Nie nemaju, nemylte si typ premennej s tym na co odkazuje. V dynamickych jazykoch rovnaka premenna moze odkazovat na rozne „hodnoty“ ktore maju typ.
Dobře. Nicméně, nevidím důvod, proč by typ proměnné nemohl být definován jako typ hodnoty.
> Zbytocne si tu ale vymyslate pojmy a zbytocne ich krutite. Tak ako som napisal – Java JE STATICKY SILNE TYPOVY jazyk. PHP je dynamicky jazyk. By definition.
Tak mi sem dejte definici pojmů: silně typovaný, staticky typovaný a dynamicky typovaný.
Já si pod silně typovaným jazykem představím jazyk, který nepoužívá implicitní přetypování.
Přetypování v jazyce stále je:
* z historických důvodů
* kvůli speciálním použitím (např. metoda clone())
Přetypování v bytecode (instrukce checkcast) je navíc i kvůli genericitě.
> * kvůli speciálním použitím (např. metoda clone())
Kovariantní změny v typu návratových hodnot metod v podtřídách jsou bezpečné, takže není důvod přetypovávat z Objectu, když se může vrátit přímo to, co klonuji.
> * z historických důvodů
To je docela dobrý důvod, ale myslím si, že už např. v době vzniku Javy se mohlo mnoha problémům předejít, kdyby se tam udělal silnější typový systém rovnou (teď se mi to mluví :-)).
Dobře, nejen clone. Existují i další příklady:
* equals(Object)
* Mám GUI na zobrazení/editaci a chci umožnit zobrazit toho u potomka víc.
* s jedním dosti specifickým případem jsem se také setkal, ale nechce se mi popisovat souvislosti
V mnoha případech by pomohly typové třídy jako mají funkcionální jazyky, konkrétně třeba typy podporující rovnost jsou v Haskellu instancemi třídy Eq.
Pro OOP jazyky už je to horší. Resp. pokud dovolíte změnu typu parametru equal, tak už dědičnost neprodukuje podtypy.
> Přetypování v bytecode (instrukce checkcast) je navíc i kvůli genericitě.
Když by to udělali jako v CLR, tak by to taky nepotřebovali.
Tam, popravdě, nevím, jak to je.
„Moje je: Jazyk je (čistě) staticky typovaný…“
Podle téhle definice by staticky typovaný jazyk byl dost na nic, protože by v něm nešlo napsat např. následující konstrukci:
Případně by kompilátor musel rozumět všem těm podmínkám a kontrolám (instanceof), které programátor provádí a na základě nich si říct, že přetypování je možné – jenže ty kontroly mohou být daleko složitější, takže se obávám, že žádný tak chytrý kompilátor neexistují – „typovou chybu“ za běhu tedy nelze nikdy zcela vyloučit, ale důležité je, že např. tupě nevezme ten kus paměti, kam daný pointer ukazuje a nesnaží se ty bajty z paměti interpretovat jako jiný ty, než jaký to je (místo toho dojde k běhové výjimce).
> Podle téhle definice by staticky typovaný jazyk byl dost na nic, protože by v něm nešlo napsat např. následující konstrukci
Konkrétně s touto definicí není problém, ne? Protože to přetypování provádíte ve větvi, kde už je ten typ zřejmý a typová chyba nenastane (ano předpokládám, že se mezitím o nezmění).
Podobnou analýzu dělá třeba kompilátor jazyka Mercury. Samozřejmě kompilátor není úplně nejchytřejší a třeba konstrukci
vám neuzná (vynucuje se pokrytí všech možností), protože nevidí, že jiná možnost nenastává a je třeba ji změnit na
kde už je zřejmé, že jsou všechny případy pokryty.
Podobné je to při dokazování vět nebo algoritmů na počítači, kde ten dokazovací systém často něco nevidí a je třeba to prostě rozepsat.
„ano předpokládám, že se mezitím o nezmění“
Což neplatný předpoklad, protože hodnotu proměnné může změnit třeba jiné vlákno běžící současně a to kompilátor nikdy neodhadne.
V Javě je toto neplatný předpoklad, ale v čistě funkcionálních jazycích je platný.
Na Javě se často kritizuje její údajná „ukecanost“, padlo to i v této diskusi. Osobně s tím moc nesouhlasím, ale je pravda, že psát gettery a settery je někdy otrava.
Existuje ale zajímavá knihovna jménem Lombok, která tenhle problém elegantně řeší pomocí anotací.
Co je spatneho na getterech a setterech? Podle me to v mnoha ohledech zvysuje bezpecnost pri programovani(z hlediska programatora). A kdyz to maji byt jen jednoradkace, tak si je necham vygenerovat v IDE.
P.S. Jak koukam na ten Lombok, tak bych se to vazne bal pouzit.
Generování řeší pouze počáteční režii, čili ve výsledku je úspora prakticky nulová. Automatické generování getterů a setterů je výhodné pro triviální DTO (s ohledem na lokalitu budoucích změn) nebo třeba pro setterovou dependency injection.
Problém v Javě je jeden: anotační procesory nesmí modifikovat třídy, ve kterých jsou anotace uvedeny – takže Lombok se musí uchylovat ke kódu závislému na implementaci.
Ta závislost tu je, Lombok se snaží vytvořit řešení pro další v podobě Lombok.AST.
Myslím, že to je vhodné víceméně všude, kde zrovna nechci něco komplecnějšího, protože až se mi to přestane hodit, tak vyhodím @Setter a napíšu si svůj nebo si jen napíšu svůj (v případě @Data).
Souhlas, po anotacích pro generování getterů a setterů toužím už pár let. Nicméně, když tak koukám na tu diskusi ohledně implemetnace uzávěrů odkazovanou níže, musím smeknout – nevěděl jsem, že má Lombok až tak široký záběr. Ale protože jakés takés uzávěry budou v Javě 7, celkem to podle mne přestává mít smysl – i když nelokální návrat je paráda (nezkoumal jsem to detailně, ale v té diskusi o něm mluví). Díky za link!
Používat gettery a settery (místo veřejných proměnných) je samozřejmě správné, protože to umožňuje vložit připadnou další funkcionalitu, aniž by se měnilo „rozhraní“ tříd. Ale trochu nepraktické je, že tu další funkcionalitu vkládáme celkem výjimečně, takže hodně tříd zůstane s gettery a settery, které kromě čtení/zápisu nic jiného nedělají – tzn. hodně řádků kódu bez nějakého hlubšího významu. Osobně s tím problém nemám, beru to spíš jako kosmetickou záležitost – elegantnější by ale bylo, mít „property“ jako je má třeba C#.
pokud někdo tvrdí že je java ukecaná kvůli getterům a setterům, tak si asi nastřílel hafo gólů do vlastní branky, protože
Lombok toho umí i víc, například je celkem zajímavá anotace @Cleanup. Těším se také na podporu closures ( http://groups.google.com/group/project-lombok/browse_thread/thread/36d096d1ccc6da7b?hl=en ).
Jinak je zajímavé, že Javu jsem viděl jako ukecanou hlavně než jsem v ní začal psát. Myslím, že z těchto dvou důvodů:
* Není to až tak strašný.
* Našly se tu věci, které mi to vyvážily.
„PHP je skriptovací interpretovaný jazyk tzn. jeho skripty nasazujeme na server tak, jak je programátor napsal“
Nejsem odborník, ale viděl jsem už i předkompilované php asi do nějakého bytekódu (když jsem se před 7 lety staral o web na civilce).
„Zprovoznit si lokálně LAMP nebo třeba aplikační server či pouhý webový kontejner a vedle toho databázi vyjde přibližně nastejno“
Na starším, vytíženějším nebo virtuálním počítači to přibližně na stejno rozhodně nevyjde.
„nejlevnější hosting pro PHP stojí pár desetikorun“
Nikoli, nejlevnější hosting pro PHP je zadarmo.
Ja osobne jsem doiteroval k tomu ze je nejlepe veskere programovani aplikacni logiky delat v PL/SQL (konkretne PL/pgSQL).
Na webovem serveru se pak PHP i Java stavi do role sablonovacich systemu. Tudiz reseni typove kontroly je na nic – zobrazuje jen to co dostane z databaze.
Ano, nedovedu si predstavit naprogramovat L2J v PHP. Ale o tom serie clanku neni.
„PHP je skriptovací interpretovaný jazyk tzn. jeho skripty nasazujeme na server tak, jak je programátor napsal a zde se interpretují.“
1. dnes PHP uz standartne obsahuje ZEND opimizer, kod sa prelozi do bytekodu ktory sa uklada aj do cache samozrejme.
2. je moznost namiesto skriptov na server ulozit priamo bytekod vygenerovany cez ZEND encoder, ktory naviac umoznuje kryptovanie so zavislostou na domene, ip adrese, umoznuje casove obmedzenie funkcnosti skriptu a podobne
3. na servroch ktore preferujem sa v poslednej dobe objavuje aj IONCUBE encoder, je to podobne ako ZEND len o nieco lacnejsi