tifyty

pure Java, what else ?

Big Data: a magyar vállalatok már a rajtnál lemaradhatnak

Évek óta nem írtam a magyar nyelvű blogra, és most sem szakmai cikket írok. Megkértek, hogy a következő felhívást tegyem ki a blogra, hogy elérjük azt a 10-15 embert aki még mindig olvassa a magyar nyelvű Java blogot. Mivel több, mint 15 éve ismerem és tisztelem a DPG Consulting tagjait, dolgoztunk együtt elég nagy biztonsággal remélhetem, hogy amit most ajánlanak az is tisztességes, fontos, értékes, így nem tisztán “reklám” (nem is pénzért teszem ki, hanem mert hiszek bennük, és mert hiszek abban, hogy bár én elhagytam az országot de nagyon fontos, hogy otthon legyenek megfelelő szakemberek), hanem olyan információ, amelyikre érdemes odafigyelni.

Péter

Budapest, 2017. október 16. – A digitális gazdaság jelenében másodpercenként keletkező, szinte felfoghatatlan méretű adathalmaz megfelelő feldolgozása és strukturált analízise egy cég közép- és hosszú távú életben maradásáról dönthet. Aki lemarad, kimarad, a digitális darwinizmus korában a Big Data lehet a vállalati digitális transzformáció sikerességének, a versenyelőny megtartásának és növelésének egyik kulcsa. Egy nemzetközi oktatási tapasztalattal rendelkező, testre szabott gyakorlati képzést nyújtó hazai cég épp ezért – a Big Data-oktatásra, -rendszerek üzemeltetésére és IT-tanácsadásra szakosodott partnerével együttműködve – a komplex feladatra alkalmas adattudósok kiképzését tűzte ki céljául.
A Nemzeti Infokommunikációs Stratégiában foglaltak szerint az infokommunikációs hálózatok, eszközök, szolgáltatások és kompetenciák egyre komolyabban támogatják a magyar vállalkozások versenyképességének javulását. A vállalatok digitális ökoszisztémáinak kiépítésében és hatékony működtetésében közben kulcsfontosságúvá vált a „Big Data” által fémjelzett hatalmas adatmennyiség célzott, iparág-specifikus feldolgozása, egy tavalyi felmérés tanúságai szerint azonban a hazai vállalatok csaknem fele alig alkalmaz Big Data analitikát. A tradicionális üzleti adatelemző megoldások nincsenek felkészülve a Big Data által generált óriási adatmennyiség adekvát, versenyelőnyt biztosító, a mindennapi működést optimalizáló, adott esetben pedig egy kiaknázandó piaci rést azonosító feldolgozására.
A közkeletű vélekedéssel szemben nem csak az IT és az egyéb infokommunikációs területeket érintheti a Big Data szele: ma az üzleti működés szinte minden területét egyesek és nullák uralják, amelyek egyre monumentálisabb adatbázisokká hízva várják, hogy felkészült, megfelelően kiképzett elemzők és adattudósok fordítsák őket vállalatuk hasznára.
• A HR-vezetők például adatbázisok eleddig elképzelhetetlen mértékű elemzésével találhatják meg a vállalatuk növekedését és üzleti célját leginkább támogatni képes munkaerőt.
• A Big Data-elemzések segítségével egy kereskedőhálózat tisztában lehet azzal, hogy a kifizetett termékeken kívül a vásárló mire volt még kíváncsi, milyen útvonalon mozgott az áruházban (vagy webáruházban), és hogy milyen hatással volt rá egy meghirdetett akció, vagy épp más vásárlók véleménye.
• A biztosítótársaságok a vezetési stílus, a megtett útvonal és a közlekedési szabálysértések alapján személyre szabott gépjármű-biztosítási termékeket tudnak fejleszteni, a szolgáltatók pedig ügyféladatok célzott böngészésével tudnak előfizetőket/vásárlókat megtartani, személyre szabott ajánlatokkal megkeresni.
• A webes böngészési trendek vagy az időjárási előrejelzések alapján a logisztikai cégek hatékonyabban tudják készleteiket kezelni, az ellátási láncot szervezni és a szállítási útvonalakat tervezni.
Nagy Kálmán, a DPC Consulting Kft. oktatási igazgatója és az IVSZ Oktatási Munkacsoportjának tagja kiemelte: „És mindez csak a digitális jéghegy csúcsa. A Big Data nem IT-vízió, hanem üzleti valóság, ami az üzemeltetési és eszközaspektust összeköti a matematika és a statisztika aspektusaival. A terület újdonsága és összetettsége miatt minél hamarabb el kell kezdeni a magyar adattudósok képzését, ezért átfogó, nemzetközi tapasztalatainkon nyugvó, egyedi oktatási módszertannal és szakmai továbbképzések szervezésével támogatjuk a hazai kkv-k és nagyvállalatok piaci sikerességét. Akár ügyvezetőként, akár pénzügyi, marketing vagy HR-vezetőként, akár matematikusként, üzleti elemzőként, statisztikusként, fejlesztőként vagy üzemeltetőként jön el valaki a novemberi szemináriumra, a mindennapokban használható, gyakorlati tudást kap arról, hogy miként tudja kiaknázni az adataiban rejlő információt. Hogy milyen technológiák vannak jelen a piacon, milyen kompetenciák kellenek mindehhez, milyen informatikai infrastruktúrára van szükség az adatelemzéshez, és hogy a Big Data milyen kihívásokat, de egyben komoly potenciált jelenthet a vállalatvezetőknek és döntéshozóknak.”
A 2017. november 7-i datafest szeminárium budapesti helyszínen várja az érdeklődőket, több jegy vásárlása esetén csoportos kedvezmény igénybevételére van lehetőség. Az egynapos szemináriumot követően minden résztvevő kap egy digitális datafest dokumentumot, hogy a frissen szerzett ismeretanyagot a kollégáival is megoszthassa. Továbbá a résztvevőknek lehetőségük lesz arra, hogy a szemináriumot követően, egy megadott időpontban, online konzultáció keretében feltegyék a témával kapcsolatos egyéni kérdéseiket.
A kontinuitást és továbblépést pedig a 2018 elején induló ún. datafest bootcamp-ek jelenti, amelyek keretében tíznapos képzésre várják azokat a szakembereket, akik már most, vagy a közeljövőben Big Data-projekteken dolgoznának.
„Egyre több adatot tudunk gyűjteni és tárolni, méghozzá egyre olcsóbban. Az árcsökkenéssel és a számítógépek sebességének növekedésével egyre könnyebben elérhető egy vállalat számára, hogy szofisztikáltabb mintafelismeréssel tudjon adatot elemezni. Meglátásunk szerint az elkövetkező években a Big Data jelenti az egyik legnagyobb fejlődési potenciált, egyben exportcikket a vállalati informatikában és ügyvitelben, ennek megfelelően a magyar humán erőforrásnak is fel kell nőnie a feladathoz, mind vezetői, mind pedig üzemeltetői szinten” – tette hozzá Kazi Sándor, a DBArt Kft. Big Data szakértője, a datafest szeminárium előadója.
A datafest szemináriumról, a tematikáról és a jelentkezésről a rendezvény honlapja szolgál további információval: http://datafest.io/

###
Bemutatkoznak a datafest szakértői:
Nagy Kálmán, oktatási igazgató – DPC Consulting Kft.

Az informatikai oktatás veteránja. 1971-ben kezdett a Számalk elődjénél, a SZÁMOK-nál. Az első (mai szóhasználattal élve) bootcamp oktatást 1974 végén hirdették meg, amely kéthónapos programtervező-képzésére 4 kontinens 15 országából érkeztek résztvevők. Nagy Kálmán később az Oracle Hungary Kft. majd a Sun Kft. oktatási vezetőjeként dolgozott.
2008 óta a DPC Consulting csapatát erősíti, továbbá az IVSZ (Informatikai, Távközlési és Elektronikai Vállalkozások Szövetsége) Oktatási Munkacsoportjában képviseli a céget.
Kazi Sándor, a datafest szeminárium vezetője – DBArt Kft.
Big Data architect, -oktató és konzultáns
Az oktatás hosszú ideje fontos szerepet játszik az életében, egyetemista kora óta tanít, jelenleg a Budapesti Műszaki és Gazdaságtudományi Egyetemen Big Data eszközök, data science, valamint Python programozás témakörökben is oktat. A T-Systems-nél Database Developerként dolgozott, majd a Dmlab data scientist Big Data szakértője lett. Több mint négy éve foglalkozik adatelemzéssel, és ehhez kapcsolódóan gépi tanulással és statisztikával, valamint annak mindenféle technológiai és infrastrukturális válfajával, amit ma Big Dataként emlegetünk.
Ha épp nem tanít, a telekommunikációs, a kiskereskedelmi, a biztonsági vagy éppen az energetikai szektor szereplőinek megbízásából adatelemzési modelleken vagy az ezeket lehetővé tevő szoftver és hardver infrastruktúra kiépítésén dolgozik.
A szervezőkről:
DPC Consulting
A DPC Consulting Kft. már akkor a rajthoz állt, amikor mások még nem is tudták, hogy lesz verseny. 1998-ban, az Oracle partnereként vágott bele az oktatásba, majd 2002 és 2010 között hivatalos Sun Oktatási Központként működött. A DPC Consulting Kft. szakemberei 2002-ben, Magyarországon elsőként indítottak fejlesztői bootcampet JavaMaster néven. Ma már, DPC márkanévvel, saját fejlesztésű tréningcsomagjaikkal vannak jelen a piacon.
A DPC Consulting Kft. testreszabott, az egyes üzletágak szerteágazó igényeinek megfelelő, egyedileg összeállított ismeretanyagait speciálisan felkészült, nemzetközi tapasztalattal rendelkező oktatóik adják át. Magyarországon kívül számos országban, például az Egyesült Államokban, Angliában, Norvégiában, Írországban és Szingapúrban is rendszeresen tartanak szakmai konferenciákat, képzéseket és továbbképzéseket.
DBArt

A DBArt Kft. rendszerüzemeltetői, szoftverfejlesztői, valamint IT-szakértői szolgáltatásokat nyújt. A csapat jelentős kompetenciákkal rendelkezik adatbázis- és alkalmazásüzemeltetés terén. A Big Data és NoSQL technológiák mellett különösen jártasak az Oracle Database, az Oracle Weblogic és az Oracle Fusion Middleware témákban. Számottevő tapasztalattal rendelkeznek JVM-alapú üzleti alkalmazások és az ezekhez közvetlenül kapcsolódó technológiáikra épülő alkalmazások fejlesztésében. Az üzemeltetési és fejlesztési tapasztalatuknak köszönhetően egyaránt nagy gyakorlattal rendelkeznek üzemeltetés- és fejlesztéstámogatásban – üzemeltetési, infrastrukturális, valamint rendszerintegrációs oldalról egyaránt.

Ha nem fontos, ne csináld!

Sokszor hallom junior kollégáktól, hogy olyan projekten dolgoznak, ami nem fontos. Rettentően demotiváló, amikor azt látod, hogy a kódot, amivel rengeteget küzdöttél nem használják és kidobják. Kicsit olyan, mintha ásatnának veled egy gödröt, hogy másnap aztán betemethessed. (Aminek persze lehet értelme, mondjuk ha sírásó vagy.)

Eugène Ferdinand Victor Delacroix 018

Egyszer találkoztam egy matematikus programozóval, aki algo-trading algoritmusokat fejlesztett. Ez az, amikor a számítógépek egymással kereskednek a tőzsdén milliszekundumonként hajtva végre tranzakciókat. Elégedett volt a fizetésével, és intellektuális kihívásának is kiváló volt az újabb és újabb algoritmusok kitalálása. Mégis úgy érezte, hogy a munkája nem sok hasznosat teremt az emberiség számára. Úgy gondolta, hogy az algo-trading csak gépek egymás közötti versengése, semmi egyéb.

Mivel hosszan utaztunk együtt és volt idő a beszélgetésre elmondtam, hogy szerintem az alo-trading versengés ugyan, de nem a gépek között, hanem az emberek között, akik az algoritmusokat állítják elő, végrehajtják, karbantartják a tranzakciókat. Ilyen módon az algo-trading a gazdaságunk evolúciós folyamatának a része és nézetem szerint nagyban hozzájárul a tőke likviditásához, hogy a befektetendő pénz ott álljon rendelkezésre, ahol arra szükség van elősegítve az innovációt és a fejlődést.

A matematikus elég nyitott volt arra, hogy végiggondolja amit mondtam, és tulajdonképpen örült, hogy lehet egyéb értelme is a munkájának mint az, hogy a hó végén megérkezik a fizetés. Egy fél évvel később, teljesen véletlenül megint találkoztunk (mind a ketten gyakran utaztunk Budapest és Zürich között vonaton), és elmondta, hogy mióta másképp gondol a munkájára nem csak boldogabb, de attól, hogy lát magasabb értelmet az algoritmusok mögött, hatékonyabban is dolgozik.

Annak ellenére, hogy ez a történet részben kitaláció, részben autoszuggesztió, mégis rávilágít egy fontos pontra: jobban fog menni a munka, ha látod az értelmét. Agnosztikus lévén tudom, hogy az egész dolognak, mint élet, világmindenség meg minden semmi értelme, így az értelem megtalálása csak annak a kérdése, hogy milyen mélyre ásol. Ha sekélyes lelkű vagy elég lehet az is, hogy eleget fizetnek. Ha összetettebb a személyiséged, akkor olyan munka elégít ki, amelyiknél érted, hogy az miért fontos a cégnek, milyen értéket teremt, és hoz hasznot a tulajdonosoknak. Ha humanista vagy, akkor fontos lehet, hogy a munkád az emberiséget szolgálja, egy kis fogaskerék a haladás gépezetében. (Azért nagyon mélyre nem érdemes ásni, mert mentális problémákat okozhat.)

De ami fontos, hogy meg kell találnod a munkád értelmét. Ellenkező esetben az nem lesz hasznára senkinek. A szeniorok tudják.

Mit gondolhatott a költő

Volt már olyan, hogy csúnya kódot kellett refaktorálnom. Ez mindenkivel előfordul az élete során, talán csak a nepáli kecskepásztorok a kivételek, főleg ha birkák. Eleddig azonban ezek a csúnyaságok javarészt tapasztalatlanságból adódtak. Igen, akár az én tapasztalatlanságomból is: elő nem venném a kódot amit 2005-ben gyártottam. Mostanában azonban olyan kódokat látok, amelyiket nem gyárthatott kezdő junior. Meg van a súlya a kódnak, benne van a programozó egyénisége, gondolkodásmódja. Szinte már költészet.

Vannak egyszerűbbek:

String attrib = businessObject.getBusinessAttribute();
if( attrib == null || attrib.length() <= 0 ){
 ...

Már az is egy általánosan felteendő kérdés, hogy miért stringek az üzleti objektumok. Ez azonban általánosan elterjedt kódolási szokás, még abból a korból ered, amikor Perl-ben programoztunk (vagy nem). Végül is egy cím, egy irányítószám, egy bankszámlaszám, egy rendelési azonosító, egy láda térbeli mérete (pl. “22cm x 18cm x 11cm”) mind stringek (vagy nem). De mikor, és hogyan lehet egy string hossza negatív? A nulla hosszal nincs, gond, az is tiszta, hogy lehet a visszaadott érték null. De negatív hosszúságú string? CharSequence még csak csak lehetséges, na de string?

Mire gondolhatott a költő, amikor ezt írta? Mindig ezt a kérdést tették fel irodalom órán, és akkor sem értettem. Mondjuk arra, hogy éppen csikart a hasa, vagy kellett a honorárium a lakbér kifizetéséhez. Nem mindegy? Sokkal fontosabb, hogy milyen gondolatokat ébreszt a vers olvasása bennem. Szép ez a vers? Mert programkódnak csak limitáltan nevezhető, annál több benne a művészi érték. Mit gondoljak a tisztelt kollégáról, aki fentieket írta?

Valószínűleg megfontolt, és óvatos ember. Nem azt nézi, hogy egy string nulla hosszú-e, inkább arra kíváncsi, hogy pozitív számú karakter van-e benne. Biztos, ami biztos. Hátha egyszer szembe jön egy string aminek negatív a hossza. Az, hogy eddig még senki nem látott ilyet, nem bizonyítja, hogy valóban nincs is! Pont mint a jeti. (Már megint Nepál! Lehet ott valami!)

De a fenti kis kód maximum haiku-nak nevezhető. A következő viszont egy igazi szonett, amelyik felkészül a párhuzamosan futó szálra. Van olyan? Nem több szál, hanem egy. Egy szál, ami párhuzamosan fut. Még senki nem látott olyat? Az nem bizonyít semmit!

final ThreadLocal<MyType> lock = new ThreadLocal<MyType>();
	
  public void method() {
    if (lock.get() == null) {
      lock.set(this);
      try {
        init();
      } finally {
        lock.set(null);				
      }
    }
  }

Mit zárol ez a lock? Az adott szálat. Ha tehát az adott szál akarja még egyszer párhuzamosan futtatni a method() metódust, akkor az nem fog menni. Persze ki tudja mi van az init()-ben? Lehet, hogy rekurzívan vissza hív sok rétegen keresztül, és így varrja el a program a végtelen rekurziót. De nem, ezt megnéztük. Ilyet nem tesz. Annak egyébként lehetne értelme, hogy a szálhelyi (threadlocal) változó nem statikus. A rekurzív hívás (már ha lenne) ha másik objektumon hívná meg method() metódust, akkor ott egy másik szálhelyi változó állna strázsát az init() hívás előtt, és így beengedhetné. Tehát lehetne értelme a nem statikus szálhelyi változónak, ha éppen nem lenne az egész teljesen értelmetlen. Vagy én vagyok nepáli helikopter.

Hogy lehet ezt kezelni? Talán sztoikus nyugalommal, amit mi sem fejez ki jobban, mint egy haiku:

Ők programoznak,
Révedünk magunk elé.
Gyűlik sok maszat.

Karácsony előtti hangulat

Utolsó munkanapon, utolsó meeting első perceiben, még nem minden kolléga jött be a terembe, hangulat nem volt túl munkaorientált.

  • Zoli: Pár éve még mekkora truváj volt egy lézer pointer.
  • Péter: De ma már nincsenek pointerek, mert Java-ban programozunk.
  • Zsolt: De a kutyák között vannak.
  • Péter: Viszont ott a garbage colletion-t magadnak kell csinálni.

Hát mindenkinek boldog karácsonyt, aki akar az még dolgozzon, mi már elég fáradtak vagyunk…

Hibajegy besorolás

  • Foglalkoztatok a hibával amit tegnap jelentettünk le?
  • Nem. Még nem jutott rá időnk, magasabb prioritású hibákat kellett fixálni.
  • Ennél magasabb? Miről beszélsz? Ennél nem lehet fontosabb egy fix sem!
  • Akkor miért kozmetikai hibaként jelentettétek le?
  • Kozmetikai????? KOZMIKUS!!!!(eredetiben: cosmetic, cosmic)

Az sem volt feltűnő, hogy a “cosmetic” a ledobó dobozban a “minor” alatt van?

Eclipse vs. NetBeans

A Sonar és a csek sztájl esete kapcsán kérdezte meg sarkiroka, hogy

és eclipse vs netbeans összehasonlításra mit mondanál, ha az nem opció, hogy nem lehet összehasonlítani őket?

Szóval falhoz lettem állítva: nem tehetem meg, hogy ne hasonlítsam össze őket. Akkor viszont megér egy posztot, mert ez egy olyan téma, ami elég személyes, főleg véleményeket lehet megfogalmazni a cikkben, és valószínű, hogy lesz sok komment. Főleg, mivel olyan téma amihez annyira nem értek, így még az is előfordulhat, hogy hülyeségeket írok össze vissza.

Felület

Én magam NetBeans-szel kezdtem a Java fejlesztést, és csak később tértem át Eclipse használatra, főleg kíváncsiságból. Az első lényeges különbség, ami szembetűnik, főleg annak aki Windows-on fejleszt, hogy az Eclipse felülete sokkal natívabb. Nem meglepő, hiszem amíg a NetBeans swinget használ addig az Eclipse SWT-t, ami annyi mindent használ a natív window rétegből amennyit csak lehet. Ennek megfelelően natív implementáció szükséges minden egyes platformra, különben nem működik, viszont van mindenre. Sokan talán nem is realizálják, hogy mennyire fontos, hogy amivel nap, mint nap dolgozunk ergonomikus legyen. Egy szoftver grafikus felülete pedig mindenképpen ide tartozik, és ebben az Eclipse jobb.

Pilótavizsga

A második dolog, hogy egy kezdő számára a NetBeans egyszerű, mint egy faék, az Eclipse meg meg sem szólal, nem tudja, hogy hova nyúljon: pilótavizsga kell hozzá. Amikor naponta használod akkor már ez nem tűnik fel és talán nem is emlékszel rá. De az elején így van: ha csak elindítod, akkor nagyon nem érted, hogy hova kellene nyúlni. Olyan, mint az első szex. De utána már sokkal jobb, mint a NetBeans, legalábbis funkcionálisan, sokkal többet tud.

Repülő versus Autó

És ha pilótavizsga kell hozzá, akkor persze elvárható, hogy repüljön. És repül is. Nagyon sok plugin létezik hozzá, és ezekkel nagyon sok olyasmit tud, amint a Netbeans nem tud. Ha csak azt nézzük, hogy a google a “netbeans plugin” keresésre 3 millió találatot ad, míg az “eclipse plugin”-re 11 milliót: látszik a különbség. Én többet vártam, de ez sem elhanyagolható.

Build Ant vs. maven

A Netbeans és az Eclipse is tud ANT-tal buildelni, de a NetBeans elég natívan kezeli a maven-t is, míg az Eclipse-nek plugin kell hozzá. Valójában az Eclipse a maven-os projektek esetén (meg talán az ant-os projektek esetén sem) a külső built tool-lal fordít, hanem csak feldolgozza a megfelelő plugin, hogy megértse egy fordítás során mit kell csinálni, és utána ezt a saját belső build rendszerével lejátssza. Ennek az a következménye, hogy nem árt frissíteni a build dependenciákat, amikor a build fájl módosul. Hogy ant esetében ez mit jelent nem tudom, mert sosem raktam ösze ant-os projektet. Maven esetében a maven plugin “refresh dependencies” (vagy valami hasonló) menüt kell futtatni, és akkor szépen újra értékeli, hogy a build során mit és hogyan.

Persze el lehet indítani Eclipse-ből is a külső ant-ot vagy maven-t, de ez nem az amit az Eclipse szeret. És a kérdés, hogy miért? Mert elég körülményesnek tűnik a dolog a NetBeans-hez képest. Az Eclise nem is a standard java fordítót használja, hanem egy saját módosítottat, amelyikkel inkrementális fordítást lehet csinálni és így akár még arra is képes (csodákra persze nem), hogy debug közben a módosított forrás alapján folytassa a már futó processz-t. Mágikus, de nem az, csak rocket science.

Összefoglaló

Kezdőként használd a NetBeans-t, mert sokkal hamarabb jutsz vele dűlőre, és használd amíg megfelelő. Nagyvállalati profi környezetben viszont kicsi az esélyed, hogy egy életen át megúszd Eclipse nélkül. Jelenleg az a de-facto IDE standard, rád fogják kényszeríteni. Ha igazi guru vagy, akkor meg IntelliJ.

Sonar és a csek sztájl esete

Mostanában angolul interjúztatok. Java technikai interjú. Ezeknek megvan a menete, és nagyjából ugyanaz, akár magyarul folyik az interjú személyesen, akár interneten keresztül angolul. Mostanában ez a második a jellemző, és nagyon jó élmény, amikor kiváló koponyákkal találkozom. Ilyenkor az első pár perc után az interjú már nem arról szól, hogy megfelel-e az jelölt, inkább csak arról, hogy mennyire felel meg.

Pár napja nagyon vicces dolog történt, egy egyébként nagyon okos programozóval, aki Prágából jelentkezett. (Ez fontos.) Kérdezgettem minden féléről.

Az angollal sem volt gond, bár én sem oxfordi kiejtéssel beszélek, és a jelöltek sem, így akad néha félreértés, de ilyenkor – ha fontos – be lehet gépelni a skype-ba egy-egy szót. Kérdezem a sráctól, hogy milyen szoftvereszközöket használna egy profi környezetben. Ilyenkor jön a Eclipse, maven, ant, git, svn, Jenkins. Kérdezem: Sonar? Cobertura? FindBugs? Mindegyikről hallott valamit. CheckStyle? Erre a válasz, hogy szerinte a csehek ugyanúgy programoznak, mint bárki más nemzet fiai és lányai, nem tud róla, hogy lenne speciálisan cseh stílus…

Hogyan fűzzünk össze stringeket Java8-ban?

Na ez valami olyasmi, mint amit a petúnia gondolt, mielőtt becsapódott volna a földbe:

Jaj ne, már megint!

Szóval volt már erről szó. De hát volt időm, sajnos, és megláttamezt a cikket (eredeti) és nem bírtam megállni. Úgyhogy most haladok:

A Java 8-ban a library-k között van egy StringJoiner osztály. És van egy új statikus metódusa a String osztálynak. Kitalálod a nevét? join()! Ki hitte volna?

Objektum Internálás

Ez a cikk az eredeti angol nyelvű cikk alapján készült.

A Java a string konstansokat egy string medencében tárolja, mégpedig mindegyik stringet pontosan egyszer. Azaz, ha

String a = "I am a string";
String b = "I am a string";

akkor a két változó a és b ugyanarra a stringre fog mutatni. Nem csak azonos lesz a két string, azaz nem csak hogy az equal() metódus eredménye lesz igaz, de pontosan ugyanarra a string objektumra “mutat” a két változó. Java-ban megfogalmazva: a == b. Ez azonban csak stringek-re, kis Integer és Long értékekre igaz. Más objektumokra általában nem igaz, hogy ha ugyanaz az értékük, akkor azonosak is lennének. Ez néha kellemetlen. Például ha előveszünk egy objektumot egy perzisztencia tárolóból (adatbázis). Ha ugyanazt a rekordot többször is elővesszük, mondjuk mert nem tudja a program logika, hogy már elővettük korábban, akkor jó lenne, ha nem egy másolatot kapnánk minden egyes esetben, hanem ugyanazt az objektumot. Más szavakkal: ha ugyanazt az objektumot veszem elő a perzisztenciából akkor ugyanazt az objektumot akarom megkapni a memóriában is. Néhány perzisztencia réteg ezt megteszi magától. Például a JPA implementációk ezt a mintát követik. Más esetekben viszont az alkalmazás szintjén kell ezt megtenni.

Ebben a cikkben részletezek egy egyszerű intern pool (belső medence) implementációt, amelyik a stackoverflow topics cikkben is megtalálható. Ami plusz ebben a cikkben, hogy részletesen leírom a tervezési megfontolásokat is.

Ojjektum medence

az ellen nem véd

Az internáláshoz kell egy objektum medence. Amikor van egy új objektumunk, akkor megnézzük, hogy az objektum medencében benne van-e már egy olyan objektum ami egyenlő a miénkkel, és ha igen, akkor azt használjuk, a miénket pedig eldobjuk. Ha még nincs ilyen objektum a medencében, akkor beletesszük, és használjuk.

Két komoly dologgal kell foglalkozni amikor ezt megvalósítjuk:

  • szemétgyűjtés
  • sokszálú környezet

Amikor az objektumra már nincs szükség, akkor ki kell dobni a medencéből. Ezt a kidobást megteheti az alkalmazás is, de ez felesleges és elavult megközelítés. A Java-ban van szemétgyűjtő, ez az egyik nagy előnye a C++-szal szemben, és ha már van, akkor használjuk. Hagyjuk, hogy a szemétgyűjtő gyűjtse be az objektumokat. Hogy ezt megtehesse nem szabad erős referenciákat tárolnunk az objektumokhoz.

Referenciák

Ha tudod, hogy mi a puha, gyenge és fantom referencia, akkor ugorj a következő fejezetre. Ha nem, akkor sokkal szerencsésebb vagy, mint a csak angolul olvasók, mert itt van egy teljes cikk ezekről magyarul, míg az angol verzióban csak egy rövid kis fejezetben foglaltam össze, hogy mik ezek. Viszont angolul sokkal több helyen megvan egyébként is. Ezért meg ők a szerencsések. Mi mindannyian szerencsések vagyunk.

A JDK-ban van egy osztály java.lang.ref.Reference néven és van másik osztály, amelyek ezt az osztályt kiterjesztik:

  1. PhantomReference
  2. WeakReference and
  3. SoftReference

Ha elolvastad a dokumentációt, esetleg az egy évvel ezelőtti cikkemet, akkor valószínűleg érzed, hogy itt most a medence megvalósításhoz gyenge referenciák kellenek majd. Fantom nem lehet, hiszen azon keresztül nem lehet az objektumhoz hozzáférni, márpedig a medencéből kellenek az objektumok. A puha sem megfelelő, mert ha már nem kell senki másnak, akkor minek tartsuk az objektumot a medencében. Majd ha újra bejön, akkor újra beletesszük. Amúgy meg a puha referencia használata általában is ellenjavallt: ha cache tárolót készítünk (nem készítünk, hanem meglevő keretrendszert használunk) akkor sem kellene a Java rendszerre bízni, hogy mikor mit eviktál (dob ki). Az ilyesmit hatékonyabban elintézi a cash cache implementáció.

A gyenge referencia pont megfelelő, mert azon keresztül el lehet érni az objektumot, de nem befolyásolja a szemétgyűjtő működését.

WeakHashMap

Nem a gyenge referenciát fogjuk direktben használni, hanem a WeakHashMap-et, ami egy olyan Map, amelyiknek a kulcsai gyenge referenciát tartalmaznak a kulcs objektumokra. Amikor internálni akarunk egy objektumot, akkor összehasonlítjuk a medencében levő objektumokkal, és ha valamelyikkel egyenlő (equal) akkor megtaláltuk. A Map pontosan ezt teszi. Az pedig, hogy csak gyenge referenciákat tart a kulcsok felé lehetővé teszi, hogy ha az objektum már nem kell senkinek, akkor a GC begyűjthesse.

Most már tudunk keresni, ami jó. De nem elég keresni: találni is kell. A Map esetében a kulcsra keresünk, és egy értéket találunk. Ebben az esetben az érték ugyanaz az objektum, mint a kulcs. De magát az objektumot nem helyezhetjük be a map-ve értékként, mert akkor van egy erős referenciánk az objektumra a map-ból és így a GC nem tudja begyűjteni, ha már nem kell senkinek. Ezért magunknak létre kell hozni egy gyenge referenciát, és azt tenni el, mint értéket.

WeakPool

Először csak egy gyenge medencét készítünk, amelyik nem rakja el az objektumot, ha nem találta meg. Egyszerűen csak megmondja, hogy van-e ilyen objektum a medencében amilyent keresünk, és ha van, akkor visszaadja. Ha meg nincs, akkor beletehetjük, de ő maga nem teszi bele magától. Egy osztály csináljon csak egy dolgot.

Itt a forráskód. Ez csak annyit mond, hogy ha az objektum amit keresünk benne van a gyenge map-ben, és meg van maga az objektum is, nem csak a gyenge referencia, akkor a get(actualObject) azt vissza fogja adni. Ha nincs benne a map-ben, vagy már csak a referencia van meg (mert pont most ledarálta a gc), akkor null-t ad vissza. A put() meg elteszi az értéket.

public class WeakPool<T> {
  private final WeakHashMap<T, WeakReference<T>> pool = new WeakHashMap<T, WeakReference<T>>();
  public T get(T object){
      final T res;
      WeakReference<T> ref = pool.get(object);
      if (ref != null) {
          res = ref.get();
      }else{
          res = null;
      }
      return res;
  }
  public void put(T object){
      pool.put(object, new WeakReference<T>(object));
  }
}

InternPool

A feladatra a teljes megoldás egy internáló medence (intern pool), amelyet nem is olyan nehéz implementálni ha megvan a gyenge medencénk, a WeakPool. Az InternPool tartalmaz egy gyenge medencét és ezen kívül egyetlen szinkronizált metódus van csak az az osztályban.

public class InternPool<T> {
  private final WeakPool<T> pool = new WeakPool<T>();
  public synchronized T intern(T object) {
    T res = pool.get(object);
    if (res == null) {
        pool.put(object);
        res = object;
    }
    return res;
  }
}

A metódus megnézi, hogy a keresett objektummal egyenlő objektum van-e a medencében, és ha benne van, akkor visszaadja azt, ami a medencében van. Ha nincs benne, akkor beleteszi, és úgy adja vissza a most már a medencében található objektumot.

Multi-thread

A metódusnak szinkronizáltnak kell lennie, hogy biztosítsuk, hogy a pool-ban való keresés és az új objektum belehelyezése atomi művelet legyen. A szinkronizálás nélkül előfordulhatna, hogy két szál is azt találja, hogy nincs az általuk keresettel egyenlő objektum a pool-ban, és mind a kettő berakja a saját verzióját, ami akkor gond, ha ezek egymással is egyenlőek. Ebben az esetben amelyik másodiknak rakja el az objektumot annak a változata lesz a pool-ban, az első viszont a sajátját használja, mint intern-ed verziót. A szinkronizálás megoldja ezt a problémát.

Versengés a szemétgyűjtővel

Annak ellenére, hogy az alkalmazás különböző szálai nem okozhatnak gondot, mivel gyenge referenciákat használunk végig kell gondolni, hogy nem akadhatunk-e össze a szemétgyűjtővel.

Előfordulhat, hogy a gyenge map-ból megkapjuk a gyenge referenciát az objektumunkhoz, de mire a következő utasításban erre meghívjuk a get() metódust addigra az már null-t ad vissza, mert közben az objektumot begyűjtötte a szemetes. Ez még akkor is lehetséges ha a gyenge map úgy van implementálva, hogy null-t adjon vissza ha olyan objektumra keresünk, amelyiket begyűjtött a szemetes. (Egyébként így van.)

Ebben az esetben azonban a WeakPool implementáció null-t ad vissza. Semmi probléma. Így az ezt használó InternPool sem küzd ilyen problémával.

Ha megnézzük azokat a megoldásokat, amelyeket a fent említett stackoverflow cikkben, adtak, az következő kódot láthatjuk:

public class InternPool<T> {

    private WeakHashMap<T, WeakReference<T>> pool = 
        new WeakHashMap<T, WeakReference<T>>();

    public synchronized T intern(T object) {
        T res = null;
        // (The loop is needed to deal with race
        // conditions where the GC runs while we are
        // accessing the 'pool' map or the 'ref' object.)
        do {
            WeakReference<T> ref = pool.get(object);
            if (ref == null) {
                ref = new WeakReference<T>(object);
                pool.put(object, ref);
                res = object;
            } else {
                res = ref.get();
            }
        } while (res == null);
        return res;
    }
}

Ebben a megoldásban a programozó egy végtelen ciklust használ annak az esetnek a kezelésére, amikor a szemetes az objektumot éppen az ahhoz való hozzáférés közben gyűjti be, de a map még visszaadta a gyenge referenciát. Nem valószínű, hogy a ciklus végtelen sokszor lefusson (enyhe irónia), sőt valószínűleg az esetek kozmikusan nagy százalékában teljesítmény gondot sem okoz. Ennek ellenére a kód összetett, nem triviális a megértése.

Tanulság: egy osztály, egy feladat. Bontsuk szét a feladatot alap műveletekre, és az esetek igen nagy százalékában egyszerűbb kódot kapunk.

Sajnos még a Google guava projektje is ezt a ciklusos algoritmust használja. Amint azt az eredeti cikk JCG szindikált megjelenésére írta SH:

Why would you even create a shockingly inferior interner to Guava’s, let alone publish it in an article??
https://code.google.com/p/guava-libraries/source/browse/guava/src/com/google/common/collect/Interners.java?r=cb72618c27773e8aa91238eca87b5e63f08b010f#66

Vagyis: “Minek készít valaki a Guava interner megoldásánál sokkolóan gyengébb megoldást, és még publikálja is?” (Válasz az JCG cikk után angolul.)

Érdemes megnézni a Guava kódot a fenti linken, lehet belőle tanulni, annak ellenére, hogy erős meggyőződésem: nincs szükség a ciklusra a megoldáshoz, és lehet olvashatóbban is kódolni. De feladat adott: ha valaki tudja, hogy miért kell mégis a végtelen ciklus, és miért nem jó az a megoldás, amit ebben a cikkben leírtam, írja meg!

Összefoglalás

Annak ellenére, hogy a Java a string konstansokat pool-ba rakja (ráadásul a permgen-be, amíg még van olyan),
és hasonlóképpen pool-ba rakja néhány primitív típus objektum megfelelőjét néha szükséges egyéb objektumok internálása is. Ezekben az esetekben az internálás nem automatikus, az alkalmazásnak kell azt megtennie. Ez a két osztály alkalmas arra, hogy ezt megtegyük, akár másolt tésztával (copy/pasta) akár repository függőséggel

        <dependency>
          <groupId>com.javax0</groupId>
          <artifactId>intern</artifactId>
          <version>1.0.0</version>
        </dependency>

a központi maven repo-ból. A könyvtár minimális, csak ezt a két osztályt tartalmazza és Apache licensszel használható (vagyis open source erősen). A forráskód a GitHub-on található.

Szavazás

After we managed to have a pool, now lets to have a poll! (Ezt nem tudom lefordítani.) Kérlek, hogy a következő kérdésre őszintén válaszolj:

Agilis, nem tervez!

Volt már erről szó, de most hallottam egy jó hasonlatot. Egy projektről mondta valaki, hogy olyan szintre fejlesztették a nem-tervezést, hogy építkezési hasonlattal élve ásattak velük egy gödröt 12 sprint alatt, majd az utolsó, 13. sprintben át kellett volna vinni a másik telekre. (A nyarakról nem is beszélve.)