Dnes budu psát o zpětné kompatibilitě v Javě. Předem upozorňuji, že nejsem expert na dané téma, spíš si chci jen ujasnit myšlenky. Takže když někdo narazíte na chybu v mých jinak bezchybných myšlenkách, tak to prosím pěkně rozmázněte v diskuzi pod článkem. Rád se něco přiučím.
Co to tedy je zpětná kompatibilita? Zpětná kompatibilita je, když moje staré programy běží i v novém prostředí. Kdo chce vznešenější definici, ať si ji laskavě najde sám. Jednoduchý příklad. Vezmu starou hru pro DOS a pustím jí ve Windows. Když poběží, vím že byla zachována zpětná kompatibilita, když ne, tak si přečtu skvělý článek od Joela, v kterém vysvětluje proč tomu tak není.
V Javě se její autoři snaží zpětnou kompatibilitu zachovávat. Ale aby to nebylo tak jednoduché, tak hlavně binární. To znamená, že program zkompilovaný pod Javou 1.4 spustím v JRE verze 6. Super. Samozřejmě naskytnou i výjimky, ale je velká pravděpodobnost, že ten program poběží. Což potěší naše zákazníky. Ti mohou program, který před lety draze zakoupili, používat i na nejnovějších JRE.
To je binární kompatibilita. Ale co zdrojáky? Ty by teoreticky měly být taky kompatibilní. Měl bych být schopen zkompilovat staré zdrojové kódy novým JDK. Tady už můžu narazit na víc problémů. Naštěstí se je SUN snaží vyjmenovat v dokumentaci (Java 5, Java 6). Takže to vypadá, že i na straně zdrojových kódů by mělo být vše v pořádku. Tedy až na pár obskurních případů.
To by bylo taky super, kdyby to ovšem byla pravda. V té dokumentaci se tak nějak zapomněli zmínit, že přidávají metody do existujících rozhraní. Nejlépe je to vidět na třídě java.sql.Connection. Pokud jenom používáte instance tříd implementujících toto rozhraní, tak je všechno v pohodě. Pokud si ho ale troufnete implementovat sami, narazíte na problém (viz. tento chudák). V nové verzi vaše implementace nebude úplná, bude jí chybět pár metod. Pokud namítáte, že není moc časté implementovat si JDBC driver, tak si představte, že chcete vytvořit prachobyčejný wrapper. Třeba kvůli logování. To je věc, s kterou už se v životě můžete setkat. Váš wrapper bude skvěle fungovat do té doby, než se ho pokusíte zkompilovat pod novou verzí. Kompatibilita na úrovni zdrojového kódu jde do háje. Nejen to. Představte si situaci, kdy ten wrapper bude zkompilovaný ve staré knihovně, kterou jen používáte. Když zavoláte třeba Connection.getNClob(), tak to samozřejmě spadne. To už není tak super.
(Měl bych brzdit, aby se na mě Roumen zas nenaštval.) Ono udržet zpětnou kompatibilitu a zároveň jazyk rozvíjet je hodně těžké. Možná i nemožné. Můžeme si vybrat to nebo ono, obojí mít nemůžeme. Proto se ozývají hlasy, že by Java měla zpětnou kompatibilitu zahodit. Já s nimi nesouhlasím. Občas se totiž pohybuji mezi konzervativními klienty. Nedávno se mě jeden člověk od AS400 zeptal něco v tomto smyslu. „My máme program v Cobolu, který je asi dvacet let starý. Nejen že jsme schopni ho dodnes provozovat, ale i upravovat. Je něco podobného možné i v Javě?“ Jako odpověď jsem blekotal něco v tom smyslu, že když bude mít všechny knihovny a kompilátor a JRE tak asi ano. Ale moc jistý si nejsem. A to jsme naštěstí nezabrousili do témat jako je podpora starších verzí atp. (pokud se chcete vyděsit, klikněte zde).
Takže abych to uzavřel, zpětná kompatibilita je dobrá věc. Nikdy se ale nedá udržet na 100%. Tedy dá, ale jen za cenu stagnace. Jak tak sleduji situaci kolem vývoje Javy, tak stojíme na křižovatce. Rozhoduje se jestli chceme stagnovat nebo se chceme vyvíjet. Nerad to přiznávám, ale jsem spíš pro tu stagnaci. Respektive velmi opatrný vývoj. Pokud chcete nové cool věci, používejte třeba Groovy. To mi připadá jako rozumný kompromis. Konzervativci zůstanou u Javy a ti ostatní se mohou vrhnout na neprobádaná pole skriptovacích jazyků. Když je budou pouštět v JVM tak se za nimi možná časem vydají i ti konzervativci.
Jak jsem videl nadpis, tak mi bylo jasne, ze uslysime o SQL Connection 😉
On je problem zpetne kompatibility sirsi, nez jenom otazka, zda se to zkompiluje novou Javou a pobezi na novem JRE. Dalsi level k problemum pridavaji knihovny a frameworky, ktere clovek pouziva. A prechod mezi versemi aplikacniho serveru muze byt adrenalinovy sport.
Pokud by te zajimalo, jak to vypada z druhe strany (tvurce frameworku, ne primo Javy), tak mrkni na netbeansovskou wiki o tvorbe APIs nebo si precti novou knizku Jardy Tulacha. Je z tooh docela pekne patrne, co vsechno se muze na prvni pohled bezpecne a pritom to muze zpusobit problemy. Na druhou stranu javax.sql.Connection mi prijde jako ocividna chyba od zacatku, navic pomerne snadno opravitelna rozsirenim do noveho interface. Je skoda, ze ji nikdo nechytil pred releasem.
No ja tak nejak doufam, ze tu knizku vyhraju svym nedosazitelnym vykonem v ApiFestu. A ano, mohl jsem psat o spuste veci, o knihovnach, o frameworcich, kdybych mel hodne mizernou naladu tak jsem mohl psat dokonce o XML parserech a jejich (ne)kompatibilite mezi ruznymi verzemi Javy. No nicmene jsem napsal to co jsem napsal. Druhy den po tom, co neco podobneho napisu si vzdy rikam, ze jsem to mohl napsat o hodne lip.
Do java.sql.DataSource taky pridali metodu :-(. Jinak ApiFest vyhrajes tak, ze najdes chyby na API nekoho jineho, ne tim, zer bude tvoje API neprustrelne. Nicmene je pravda, ze delat API zpetne kompatibilni je veci delani krvavych kompromisu ;-).
Neboj Dagi, hledani chyb u ostatnich mi opravdu jde.
Není náhodou zahazování zpětné kompatibility označování method, které budou v budoucnu odebrané, anotací depricated?
To banter: Zatím není. Deprecated říká, že je to sice zastaralé, ale že to právě kvůli zpětné kompatibilitě nechávají a možná budou nechávat navěky. Alespoň tak to funguje v knihovnách, které jsou součástí JRE.
Trochu bych nesouhlasil se zaverem, tj. rozvijet nebo nerozvijet. Kdyby Java mela module system (dnes vyvijeno pod JSR-277 a JSR-291; snad jsem nezpletl cisla), pak by vec byla jednoducha. Clovek by mel 2 moduly ruznych verzi a bylo by. Dnes to bohuzel nejde nijak rozumne resit, nez mit vice jaru pro ruzne verze JDK ….
P.S.: No je jasne ze bez uprav neni mozne mit kompatibilni zdrojaky skrze vice verzi JDK a obecne vetsiny API.
Ale to mne nikdy tak nepalilo, jako persistence objektu, kde data ulozena ve vcerejsi verzi nemusi byt (bez znacne namahy) citelna dnesni verzi.
P.S.: Osobne k implementaci JDK rozhrani pouzivam Proxy. Takze tohle mne nastesti nehrozi :D.
Zase tak moc bych se s tím nenervoval 🙂 Když už máš nějaký starý program, který chceš zakonzervovat a nešťourat do něj*, tak k němu prostě přibalíš JRE v požadované verzi.
“Ti mohou program, který před lety draze zakoupili, používat i na nejnovějších JRE.”
To je sice fajn, ale jaký má X let starý program význam pro byznys? V rámci inovací** se program čas od času překompiluje pro novou Javu.
Nedávno jsem narazil na starý program, jehož autor si jednu proměnnou pojmenoval enum. Nejdřív jsem se trochu zalekl, když mi projekt v Netbeansech zčervenal, ale pak jsem se jen pousmál: to za starých časů nebývalo.
IMHO by se Java rozvíjet měla, jen ne nějak překotně, zbrkle. Souhlasím, že to chce najít rozumný kompromis – oba extrémy jsou špatně.
BTW: co opačný problém: spouštění dnes napsaných programů ve starých Javách? Jak moc berete ohledy na starší JRE? Já moc ne, kdo nemá aktuální Javu, ať si ji pořídí 🙂 Nehodlám se zabývat laděním programu pro 1.4.
*) “do věcí, které fungují, se nešťourá”
**) Překompilovat? Cože, vy od toho nemáte zdrojáky? Firma, která vám to napsala už neexistuje? Vítejte v closed source pekle 🙂
to franta : vcelku si ma pobavil. neviem ako dlho kodujes ale evidentne nemas prilis skusenosti s konzeravtivnymi zakaznikmi ala banky, poistovne a podobne. V niektorych dostat javu 1.5 (a mam skusenost dokonca s 1.3 ktoru odmietaju upgradnut) na masiny je robota skor pre psychologov alebo policajnych vyjednavacov ako pre cloveka z IT 🙂
Tvoja otazka aky vyznam ma program stary X rokov pre biznis je tak isto mimo misu. Pokial mam zakaznika, ktoremu bezi kontroling nad programami starymi X rokov (strojarstvo) tak aky vyznam ma ponukat mu (okrem financneho prospechu pre dodavatela) novy soft, ktory neriesi nic okrem toho co mu uz davno korektne bezi ?
To Benzin: Nejak jsem nepochopil jak to delas s tim Proxy. Docela by me to zajimalo.
dianod: asi jak kde – mám zkušenost z banky, kde je 1.5 standard, ale uznávám, že v nějakých zaostalejších ústavech mohou ještě používat starší verze. Nicméně tak jako tak je možné mít více verzí: i v tak konzervativních OS jako je třeba Solaris můžeš mít několik JRE.
U zakaznika muze stara verze bezet i jen proto, ze proste povysovat verze nepotrebuje, kdyz to bezi. My jedeme v jave 1.3. A v Anglii a USA jedou jeste IBM 360 s puvodnimi Coboly (informace stara 1-2 roky).
Čím víc nad tím přemýšlím, tím víc se mi postup Javy líbí.
Zkompiloval jsem něco a dal to zákazníkovi? Pak to pojede!
Byla přidána nová metoda? Pak se to celý pokusím zkompilovat a hned uvidím, co musím dopsat!
Jinak samozřejmě by bylo čistější vytvořit něco jako Connection2 a třídám, které chtějí používat novější verzi, udělat potomka. Ale zase by se to komplikovalo.
Já bych zachoval alespoň 100% binární kompatibilitu.
Nejsem odboník na C/C++ ale někde jsem četl, že některé kompilátory tu 100% binární kompatibilitu mají. Na druhou stranu extremizmus pythonu 3000 (nekompatibilita ikdyž na úrovni zdrojáků).
Nevím co je správné, na příkladu Cobolu je vidět, jak se doba mění. Dříve se zřejmě všechno nezahazovalo každé 3 roky…
Nevim, zda jsem byl tim zminovanym clovekem od AS/400 ja, ale urcite vim ze jsme na toto tema spolu kratce hovorili na konferenci COMMON. Ted jsem se mozna sam chytil do pasti (ne)kompatibility; mam (na AS/400) napsanou aplikaci, ktera je z casti v COBOLu a zcasti v Jave. Zatim jsem v bode 0, vyvojove prostredi pro oba svety mam aktualni, uvidime ale “za par” let…
Mohu doplnit svoji současnou zkušenost. Pracuji na aplikaci v Javě , která vznikla před cca. deseti lety. Je to na ní vidět, od té doby se vývoj v Javě hodně posunul kupředu. Důležité ale je, že ta aplikace je stále funkční, stále se upravuje a rozhodně nejsou žádné problémy z kompatibilitou.