Daily Curious Perversion of Programming #10

 ( Chain-Q | 2009. július 28., kedd - 13:10 )

Na már megint Java (szerk: közkívánatra: mobil Java:) érdekesség, körítve a szokásos általános programozói zsenialitással.

Kezdjük ott, hogy szívzörejt kapok attól az apró, de nem elhanyagolható ténytől, hogy Javában nincsenek pointerek, de van NullPointerException. Ez valami gyönyörű, a Java gyüjtőfogalom alatt leledző masszív elkúrás esszenciája. (Tudom, gyakorlatilag "NullReferenceException"-ről beszélünk, mert referenciák vannak, nem pointerek. De azért a név beszédes, benne maradt, ilyen ez. Yuck. Meg yikes is.)

További szívszerelmem, ami mobilprogramozásnál igen fájdalmasan tud érinteni, hogy semmiféle módszer egy-egy objektum tényleges felszabadítására, azon kívül, hogy null-ra állítod az összes referenciádat ami valaha az objektumra mutatott, aztán majd ha a garbage collector arra jár, akkor 3 másodpercig szünetel az alkalmazásod, míg mindent felszabadít egyszerre. Ez különösen akkor baromi jó, ha játékot írsz, és elvárás, hogy pl. stabil 10 fps-t prezentáljon. Ehelyett 15 másodpercenként megáll 3 másodpercre, kis túlzással. Tökjó. Garbage collection FTW! De lépjünk tovább.

Természetesen az igazán fun oldala a fenti dolgoknak akkor mutatkozik meg, amikor egy olyan programozónak kell C/C++-ból Java-ba átírni valamit, aki igazán egyikhez sem ért (tehát kvázi fingja sincs róla, hogy mi történik a rendszer mélyén, amikor a kódja fut).

Ebből lesznek az ilyen zseniális kódok, hogyaszondja, felszabadító függvény, kilépéskor:

public void DoCleanup() {

    if (x_myFoo != null)
        x_myFoo = null;

    if (x_myBar != null)
        x_myBar = null;

    if (x_myBlah != null)
        x_myBlah = null;

    if (x_myEeek != null)
        x_myEeek = null;

    if (x_myOMG != null)
        x_myOMG = null;
}

Tökjó. Első blikkre az ember röhög egy jót, és nem érti, hogy mi értelme van ellenőrizni a pointereket referenciákat, ha úgyis null-ra lesznek állítva. Ha már null, akkor meg nem fáj neki, hogy mégnullabb lesz. De aztán jönnek a reflexek, hogy valószínűleg ez nem ilyen egyszerű probléma. A kód eredetije ugyanis egy C/C++ kód volt, amiben egy ilyen felszabadítós blokk saccra így nézhetett ki:

    if (x_myFoo) {
        delete x_myFoo;
        x_myFoo = NULL;
    }

Namost, itt természetesen van értelme ellenőrizni előtte (szerk: Vagy mégsem? Lásd a hozzászólások között...), plusz van még egy fontos szempont: a delete, ha jól értem, meghívja egy objektum destruktorát is... Igen, természetesen a Java kódban is megvannak az egykori destruktorok, szorgalmasan átportolva, csak a fenti nűánsz miatt sohasem hívódnak meg. Apró problémák, újabb vicces bugok okozói. Így jár, aki elhitte, hogy "Jávában" nem kell felszabadítani semmit.

Tanulság: Tökjó, amikor a projekt indulásakor a szenyor szoftver endzsinírök kiadják az ukázt, hogy márpedig a kódstruktúrát változtatni azt ám nem szabad, mert hát a "Jáva" az majdnem Cé, tehát semmi szükség rá. És az ember, aki a feladatot kapja, ezt még el is hiszi. Végülis ja, majdnem C. Például mindkettőben vannak kapcsos zárójelek... Argh.

(Egyébként fordítottjával is találkoztam már, Java expert programozóval, aki elhitte, hogy a C majdnem ugyanaz, mert ugyanúgy kell írni a forciklust. Na, ő meg persze pointerkezelés címszóval csinált vicces dolgokat. "... de ez még hosszabb sztori".)

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

C++-ban a delete-et kiadhatod nullpointerre is.

KisKresz

Sejtettem, de a C++ verziót se én írtam. :)

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

Amúgy valószínűleg a fordító kioptimalizálja a fölösleges ellenőrzést.
Na, persze, azért nem árt ismerni a nyelvet, amin programozik az ember... :-)

KisKresz

A fordito, az tudni fogja, hogy az felesleges ellenorzes szerinted? Marmint, a blokkon belul hasznalva van a valtozo, amit ellenorzol, ketszer is, a delete meg belul egy stdlib hivassa fordul (szerintem), ami csinalhat akarmit, mar leforditott binaris kod, sokszor egy DLL-ben kint. A fordito tehat annak a tartalmara nem alapozhat (bar persze masodik gondolatra meg alapozhat persze, mert megsem sima hivas csak, hanem jol definialt nyelvi elem). Mindenesetre, szerintem lazan bennemaradhat az a check. :) Ha csak nem vagyok lemaradva forditotechnologiabol. De legalabbis fordito fuggo az biztos. De most lusta vagyok C++ forditot izzitani, es leforditott kodot nyalazni. :P

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

Mondjuk, reménykedem benne. :-)

KisKresz

Elvben minden objektumnak van destroy() fuggvenye, illetve ha jol tudom, meg lehet surgetni a gc-t is.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

"protected void finalize()
Called by the garbage collector on an object when garbage collection determines that there are no more references to the object."

Ez azért nem pont ugyanaz mint a C++ destruktor... Szerk: Például implicit hívódik meg, majd valamikor. Igen, meghívhatom a System.gc()-t rögvest utána, de ez nem pont a tökszép megoldás. Plusz egy nagyobb kódban nincs rá garancia, hogy már nem lesz referenciája az adott objektnek máshol.

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

+ nem csak az adott objektumot szabadithatja fel amit epp legyalaztal (plane ha tobb szalu), hanem a teljes nyilvantartast vegig nyalja es mindent amit talal.

---
pontscho / fresh!mindworkz

Hja. Emiatt olyan telefonokon, amin komplexebb dolog is fut a JVM-ben, semmint mondjuk egy játék, hanem pl. több alkalmazás egyszerre, kimondottan (dokumentáltan) ellenjavallt a System.gc()-t hívogatni a habokra.

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

Lehetséges, hogy a Java nem alkalmas arra a feladatra, amire használod?

Várj, másként kérdezem: lehetséges, hogy egy dilettáns döntötte el, hogy milyen nyelvet kell használnod ebben a projektben?

Ha a telefon (ami a fejlesztés célplatformja) csak Java-ban írt programokat képes futtatni, akkor nincs sok választásod. Egyébként szerintem a Java semmire sem alkalmas, tehát engem nem kell meggyőznöd, hogy erre nem jó a Java. :D

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

rotfllol

irjal mindent C++ban akkor :) szerinted mennyivel lenne jobb mondjuk szerveroldalra? (hint: semmivel. sot.)

Nnna, megjott a rezidens Java fan, alig vartam. :) Egyebkent segitek, a C++-t is utalom. :P

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

nem java fan vagyok, csak megvan mindenre a helye.

mobilprogramozashoz epp nem ertek, de azt, hogy itt VMbe futt a cucc, es GC van, az nyelvi feature, es nem bug. tessek tuningolni a JVMet, ha nem jo a default, de nem fikazni*. a referenciak meg szerinted hogy vannak megvalositva? megsugom: pointerekkel. ezert van NPE.

*: standard JVM tuningban tudok segiteni, mobilokon nem tudom hogy megy ez, sosem akartam ilyen szarokra fejleszteni. :)

Idézet:
referenciak meg szerinted hogy vannak megvalositva? megsugom: pointerekkel.

Azert azt erzed, hogy ezzel nem mondtal ujdonsagot.

Idézet:
mobilokon nem tudom hogy megy ez

Kimondtad a kulcsmondatot. De azert kosz a felajanlast... :)

Szerk: hogy informaciotartalma is legyen a hozzaszolasnak, mobilon ugy megy ez, hogy van egy JVM a telefonon, es kuss. Az van. Arra kell fejleszteni. A szoftvert nem a JVM-mel egyutt deployoljuk, hanem benne van a telefonban gyarilag. Nem fersz hozza. Ha szerencsed van, futtatja a cuccod, de erre sem fogadhatsz azert nagy osszegben. Es altalaban hiperlimitalt meg azon tul is, hogy a J2ME-ben amugy sincs semmi, es meg az is crippled, meg a fele bugos. (Nem mukodo Vector class, telefont resetre fagyaszto Graphics hivasok, regebbi telefonokon jellemzo 80K .jar meret(!) limit, 40K, 64K, 80K, 96K (kilobyte, igen) es hasonlo memoriahasznalati korlatok, stb.) Szerinted ezekutan van barmi esely a JVM "hangolasara" egy mobil eszkozon? Hangosan rohogni azert er? Egyebkent igen, szar. Eze' fizetnek lassan 4 eve viszont. Your point? :)

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

Ez esetben hangosabban kene ordibalnod a melohelyen a kodminoseg miatt. Ha tenyleg ennyire necces korulmenyek kozt dolgoztok, akkor duplan at kell gondolni minden leirt kodsort. Szerintem.
--

()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.

Been there, done that. De attol meg a mar meglevo kodban meg benne vannak az ilyen okossagok, amikbol aztan sztorik lesznek, ha belejuk akadok. :) Egyebkent modern telefonokon azert nem ennyire szar a helyzet, de itt sem lehet nagyon ugralni.

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

My point: azert mert adott, specialis esetben szopsz, a Javanak megvan a piaci szegmense, meg a felhasznaloi bazisa. es nem feltetlen a J2MErol beszelek. remelem erzed Te is, hogy nem ez a fo piac :)

Ha az eszkozok szamat osszehasonlitjuk, amikben alapbol van Java tamogatas, lehet, hogy a J2ME a No.1... :) Persze a J2SE/J2EE-sek (es ugy altalaban a nem mobil programozok) szeretnek lenezni minket, meg elbagatelizalni az egesz mobil dolgot. Voltunk mar "kicsik", "telefonszerelok" meg amit csak akarsz, a "nektek konnyu dolgotok van, mert telefonra nem lehet bonyolult dolgokat irni" cimu okossagokrol nem is beszelve. En valasztottam persze, sz'al en rohogok az ilyen szemellenzos megnyilvanulasokon, csak mondom. :P

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

en nem mondom, hogy oda ne lehetne bonyolult dolgokat irni. viszont az nem hiszem, hogy a nyelv(!) sara lenne, hogy a JVM amin epp futtatod, nem konfiguralhato (GC pause time issuekra gondolok)

Az elobb meg az volt, hogy a GC az nyelvi ficsor. :) Egyebkent a nyelvvel is van eppen eleg bajom, foleg mert buta mint a fold. Meg az egyeb "C-szeru" (sic!) nyelvinkarnaciokhoz kepest is.

Peldaul: tobbiranyu elagazasban nem lehet megadni intervallumot, if-nel nem lehet megadni ertekkeszletet a kifejezesekhez (pl. if (blah_value in [foo, eek, dzs]) then, mint Free Pascalban, pl.)). Persze egyik sem megoldhatatlan, eleg ha "maskeppen" fogalmazod meg a problemat, de azert nekem hianyoznak.

Igaz a "nagy" Java-n "szinte mindenre" van kesz class meg API, ami megoldja a legtobb bajodat, de attol meg a nyelv nem lesz fejlettebb, mert ennyi erovel assemblybol is hivogathatnad az uberalles frameworkot ami korulotte van. Plusz nekem mobilon ettol nem lesz jobb, kicsit se. :) Persze mar megtanultam elfogadni a Java-t mint munkaeszkozt minden okossagaval egyutt, de szeretni valoszinuleg sose fogom. Ez van. Manapsag mar ugysem a nyelv szamit, hanem hogy mekkora alap fuggvenylibrary van hozza, meg mennyire tudja kinyalni a segged az IDE es a toolset ami hozza van. A programnyelvek fejlodese egyebkent kvazi megallt, mar csak egymas masolasa meg a rutinkonyvtarak hizlalasa zajlik. (Na ezert meg majd mindjart kapok a funkcionalis programozas hiveitol, tobbek kozott... :)

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-

A GC nyelvi feature, de azért az implementációja lehet bugos...

Szerk.: Nem is a bugos a jó szó. Arra akarok kilyukadni, hogy több, különböző algoritmus van szemétgyűjtésre, ez is folyamatosan fejlődik, amennyire én tudom, szóval nem az alapelvvel van baj, hanem az implementációval.

KisKresz

Öö. Ha már úgyis ezzel (kell?) dolgoznod 4 éve és úgy tervezed, hogy a közeljövőben is ezzel fogsz... miért jó neked, hogy utálod? :) Semmi se tökéletes és olyan úgy sincs ami minden feladatra alkalmas. Szeresd meg, ne szenvedj és légy boldog :)

(Persze értem én az életérzést, hogy fikázzuk ami "bent" van, aztán otthon leülünk a FreePascal elé és akkor jó, meg, hogy te így vagy boldog.. :)

En nem szenvedek, csak eppen nem az eszkozben, hanem a feladatban talalom meg azt, amiert erdemes csinalni. Ezek a postok meg deklaraltan a dolog elkuras reszerol szolnak, szoval nyilvan van az eremnek masik oldala is.

Tehat nem ertem a kerdest. :) Jobban mondva ertem, hogy te ezzel a fenti "megszeretem inkabb" dumaval nyugtatod magad, miota nem Amigazol, de nem vagyunk egyformak... :P

-=- Mire a programozó: "Na és szerintetek ki csinálta a káoszt?" -=-