A következő címkéjű bejegyzések mutatása: gyárlátogatás. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: gyárlátogatás. Összes bejegyzés megjelenítése

2013. február 27., szerda

Gyárlátogatás: az adatbázis

Rég voltunk gyárlátogatáson, gondoltam ismét belerúgok a műfajba, ezúttal az adatbázisok és használatuk területéről írok pár személyes élményemet. Mint mindig, nem arról lesz szó, hogy hogyan kellene, hanem arról, hogy mit csinálnak a szakik a gyárban.


Fellegvár


97 Dolog, amit minden Architektnek tudnia köllene (és mégse tudják), 23. bejegyzés: Legyen erőd az adatbázisod!
Ezt a sírjára vésném azoknak, akik nem tartják be :-) Az adatbázist nem bíznám az izgága programozókra. A DBA egy külön szakma, más mentalítást és más egyéniséget igényel, mint a szoftverfejlesztés. A legjobb tapasztalatom adatbázisokkal annál a munkahelyemnél volt, ahol külön DBA csapat volt. Ezek a csákók vágták az adatbázis minden paraméterét és rendesen lecsesztek mindenkit, akinek az alkalmazása nagy mennyiségű hülyeséget csinált. Persze nem klassz, amikor az embert lecseszik, de néha hasznos.

Az profi üzemeltető csapatból következik még egy dolog: nem akarnak sokféle adatbázis szervert üzemeltetni. Ha elöjössz azzal, hogy neked KakukkSQL kellene, mert a hétvégén kipróbáltad és most az a kedvenced, őseid legkevésbé sem magasztaló kontextusban kerülnek megemlegetésre.
Többnyire 1 cég 1 adatbázishoz ragaszkodik, de legalább abból az egyből elég jó szolgáltatást kapsz.

Ha így nézed a dolgot, marha fontos, hogy az alkalmazásod több adatbázissal is jól szaladjon, amennyiben nem csak 1 ügyfélnek akarod eladni, illetve nagy ügyfeleket is szeretnél célozgatni, akik nem akarnak holmi közös felhőben lakni. Oké, talán ez egyre kevésbé tényező...

Szamócából fellegvár


Egy régi főnökömtől származik a mondás, ami mindig eszembe jut, amikor egy adatbázist rendesen tökön rúg egy alkalmazás:
"Ne aggódj, az Oracle végtelenül skálázható." Én meg kérdeztem mint egy hülyegyerek hogy "Tééélleg? És mennyiért?"

Ezt általában el lehet mondani, hogy kevés elképzelése volt az embereknek eleinte arról, hogy mennyit bír egy adatbázis szerver és a hardver mérettel ez hogyan változik, illetve az adatbázis mérete hogyan befolyásolja a teljesítményt. A fenti dologgal ma már nem hiszem, hogy bárki előjönne, de nekem úgy tűnik továbbra is kevesen tudnak arról bármit is, hogy az adatbázisuk miből mennyit bír. Konkrétan számszerűen, mert az akármennyi az nyilván baromság.

Indexelés és optimizálás


Sajnos nagyon kevés java fejlesztő néz bele akármikor is, hogy a lekérdezései mit is csinálnak konkrétan, pedig minden adatbázisban van valami query debugger funkció, többnyire explain-nek hívják. Ez azért lenne fontos, mert az adatbázis a munka nagy részét elvégzi, amit a hétköznapi ügyviteli rendszereink csinálnak, az valójában csak minimális feldolgozás rajta. Ha kicsit jobban bánunk az adatbázissal, az valószinűleg kategóriákkal többet fog javítani az alkalmazás teljesítményén, mintha felűberelnél a JLophas AS legeslegújabb verziójára, vagy mint ha a teljes alkalmazásban levadásznád a hülye "ez" += "az" konkatenációkat, a temp objektumokat, satöbbi. Sajnos ez van.

 

JPA&Co


Sajnos a perzisztencia frameworkok csak tovább növelik ezt a távolságot a fejlesztők és az adatbázis között. Annyi azért viszont biztos, hogy a JPA implementációk nem generálnak olyan idióta lekérdezéseket, mint egyes alkalmazások JPA nélkül. Most inkáb kihagynám a példát :-D de biztosan találsz a házad táján.

Kétségtelenül nagy előnye a portolhatósága és a gyors fejlesztés, de néhány dolgot néha optimalizálni kell, különben agyonveri az alkalmazásodat. Erre javasolnék egy patternt: csinálj egy általános JPA DAO-t, ebből származtass le szükség esetén DB-specifikus implementációkat és bíráld felül (gyakorlom a magyar nyelvet, az override-ra gondoltam) azokat a lekérdezéseket futtató metódusokat, amiket optimalizálni akarsz. A DAO-kat egy factory-val gyártsd le, ami az adatbázis típusától függően ad vissza egy implementációt.

Mégegy dolog: az automatikus séma generálás nem jó, mert az említett "erődítmény" tétellel ellentétes. Prototypinghoz természetesen kiválló, de az adatbázis adminisztrátorod megöl érte. Talán érdemes írni egy listát, hogy mit kell tenni amikor már komolyan gondolod az alkalmazás fejlesztését, és mondjuk így kezdeni: automatikus séma generálás kikapcs.

 

Cache vagy MQ


Egy gyakori probléma, amivel találkoztam, hogy az adatbázist cache-ként vagy üzenetek küldésére használták. Ennek az oka valahol az egyéb infrastruktúra hiánya és az ismeretek hiánya között volt általában, kicsit mindkettő.
Talán ida tartozik, hogy a Quartz is használ relációs adatbázist Job storeként és elosztott lockoláshoz. Határeset...
Mondjuk a Quartz-ról ma hajlamos vagyok azt gondolni, hogy antipatternek gyüjteménye.

 

Tárolt eljárások


Ez egy rettenetesen vitás téma az adatbázis adminisztátorok és a fejlesztők között. Több DBA-val találkoztam, akik megkövetelték vagy elvárták a tárolt eljárások használatát.
A java fronton ellenben a tárolt eljárásoknak nem igazán népszerűek. Illetve igazán nem népszerűek. Ennek több oka is lehet: elösször is egyetlen egy tárolt eljárás nyelv sem portolható. A java tárolt eljárások inkáb az előző évtized közepe tájám volt egy próbálkozás, csak a DB2 és az Oracle támogatta, PostgreSQL-re ketten írtunk rá támogatást, de őszintén egyikünk sem lett nagyon népszerű vele, évek óta leálltunk a fejlesztéssel.
Portolhatóság szempontjából a tárolt eljárás inkább akadály, mint segítség, a legtöbb persistence framework nem tud velük mit kezdeni.
A népszerűtlenség nagyobbik oka viszont nem a portolhatóság hiánya, hanem egyszerűen az, hogy a tárolt eljárásoknak az esetek nagy részében egyszerűen nincsen semmi előnyük, de nehezeben áttekinthetővé teszik a rendszert. Példának sajnos az oVirt-et fel tudom hozni, a legegyszerűbb lekérdezést is bele kell csomagolnunk egy tárolt eljárásba.

Igazából én egy csomó lehetőséget látnék tárolt eljárásoknak olyan téren, mint az interakciók számának csökkentése az adatbázis és az alkalmazás között. Pl insertOrUpdate, insertAndReturnId. Ilyesmi használatát nem emlékszem hogy láttam volna valakitől.

Tranzakciók


A tranzakciókkal is láttam pár buherát. Egyes rendszerek (pl ovirt is sajnos) egyenesen problémaként élik át a tranzakciók létét és bonyolult, bizonytalan kimenetű dolgokat csinál a kicselezésére.
A kedvenc trükk, amit láttam, mégis az volt, hogy az app egy bizonyos lekérdezésre nyitva hagyta a tranzakciót és a kapcsolatot, meg egy ResultSet-et is, és a következő http requestre tolta ki az eredményt html-be. Néha, amikor a második http request mégsem ütött be, akkor kicsit elakadtak a dolgok. Erre adta a rendszergazda azt a diagnózist, hogy "A program egyébként jó, de a tomcat egy rakás sz.., naponta újra kell indítani"
Ezek a trükközések elég hajmeresztőek, de nem ritkák.

A NoSQL forradalom


Nincs antipattern tapasztalatom a NoSQL adatbázisokkal, mert sajnos munkában még soha nem használtam őket, de alig várom. Talán oda jutott a dolog a tradícionális RDBMS modellel, hogy néhány dolgot, például a tranzakciókat (lásd fent) egyáltalán nem találunk hasznosnak egy olyan alkalmazásban, mint egy chat, alkalmazás logok, vagy szociális háló. Egy évtized kellett hozzá, hogy az internet ipar saját ötlettel áljon elő és elrugaszkodjon az inkáb a pénzintézetek igényeihez igazodott modelltől. Jelenleg annyi NoSQL adatbázis van, hogy nem tudom felsorolni őket és nem tudok mindegyikkel lépést tartani. Azt hiszem még évekbe fog telleni, amig letisztul a terep, pár kellemetlen élmény keletkezik elötte. Például a mongodb-ről hallottam pár forrásból, hogy végül felhagytak vele. Én még mindig hajtom, persze nem atomreaktort vezérlek vele. Egyébként nem hiszem hogy a mongo végül a kiesők között lenne, de pár másik ott lesz.

2012. június 13., szerda

Gyárlátogatás: KÓD_KONVENCIÓ

Hali, ismét gyárlátogatáson vagyunk, zsebrevágott kézzel körbevizslatunk az üzemben, megnézzük mit csinálnak a szakik. Gondoltam ma kicsit mesélnék arról, hogy miket láttam kód konvenciók háza-táján, milyen viták zajlanak, hol és mi fáj. Ne várjatok nagyon objektív megközelítést, ez az egész személyes élmények alapján.

A legtöbb kód konvenció csak a fejlesztők életét könnyíti vagy nehezíti meg. A forráskód fordítása után a tárgykódban már nincsenek se szóközök, se kommentek, se tabok, C nyelvben még a változód neve is eltűnik, java-ban is inkáb csak a mezőknek van jelentősége. Szóval ilyen szempontból a dolog kevés értéket jelent az ügyfélnek, aki végülis fizetni fog (reméljük) a termékért.

Nevek


C++-ból és hasonló területekről érkező szoftverfejlesztőktól gyakran láttam hungarian notation-hoz hasonló neveket. pl a mezőket sokan kedték aláhúzással, mint _name, vagy my prefixszel, pl myName. Régebben sokat láttam szigorúbb hungarian notationt java programozóktól is, pl volt olyan munkahelyem, ahol meg a paramétereket is 'a'-val (mint argumentum) kellet kezdeni.

A legviccesebbnek azt a konvenciót találtam, ahol az entitás osztályokat és azoknak a mezőit magyarul kellett elnevezni. Szerencsére ékezeteket nem akartak, de sikerült amolyan kicsi bábelt létrehozni a forráskódban, ugyanis a java többi része és library-k továbbra is angolul vannak.
if(fejleszto.isHulye()) ...

Egyes konvenciókat a java nyelvben én is teljesen figyelmen kívül hagyok, az egyik ezek közül amit a legtöbbször vágnak a fejemhez, a konstansok NAGY_BETŰS elnevezése, helyette a konstansokat is sima mezei camelCase írom. Akkor pár ok:

  • A NAGY_BETŰS konvenció a C nyelvből érkezett a java nyelvbe. Ott a prepocesszor makrókat ajánlott nagybetűsen írni, ugyanis komoly gubancok származhatnak belőle ha elfelejted. Java-ban udvariasan szól az eclipse vagy amit hajtassz, hogy "komám, az final". Nem mondod komolyan, hogy vim-ben írsz java kódot? Ja emacs, persze, de kis buta vagyok :-D
  • Enum-okat: Igen, ami az enumban van az effektive public static final, de miért kellene mindent nagy betővel írnunk benne? Mint egy állítólagos nigériai tábornok lányának a takarítónöjének a majma egy e-mailben.

Tab vs space
"te tab-bal tabulálsz?
bnzi-e vagy" - beteg-patkány-ember
A másik ilyen kérdés a space vs tab hitvita. Nem szeretnék senkit se rábeszélni arra, hogy áttérjen a másikra, de a harcos space-hívőknek: Ha a space a tabulálásra van akkor a tab vajon mire van?

Ez a tabulálás dolog viszont leginkáb a python fejlesztők között okoz viszályokat, pár hét python buherálás után én így kategorizálom be a python fejlesztőket:
  • tab-os pythonos
  • 4-spaces pythonos
  • 4-től eltérő mennyiségű space-szel tabuláló pythonos
És mind meg van győződve róla, hogy ő vágja a témát és a többi falhozvert lófasz. A projectemen többségében 4-spaces pythonosok vannak, szerintük a pythonnak nagyon fontos, hogy pont 4 legyen. Ennek ellenére a kódban tucat helyen el van cseszve és csak 3 space. Sajnos kb azonnal elfelejtettem az indoklást, az összes python scriptem futott a tabokkal.

Sorhossz

A sorok hossza ami a másik dolog, amivel teljesen értelmetlenül és eredménytelenül lehet vitatkozni egy pár órát. Kezdetekben mindenkinek volt a szép karakteres képernyője, ami képes volt 80x25 karakter megjelenítésére, innen származott az a tradíció, hogy legyünk szivesek 80 karakternél többet ne pakolni egy sorba. Hát azóta eltellt egy kis idő, közben a képernyők közül a 23 colos lett a standard. Amennyiben nem a mobil telefonodon fejlesztessz. A sorok szélessége viszont sok projectben megmaradt 80 karakter.
Kicsit ez a dolog kapcsolódik a space vs tab vitához, mert a tab méretét lehet változtatni a szerkesztőben.

Kommentek

Talán ezzel volt a legkevesebb gubanc, mert áltaáában a fejlesztők beérik kevés dokmentációval. Egy ellenpéldával találkoztam, konkrétan az oVirt projecten dobták vissza az egyik patch-emet egy csillag miatt. Ugyanis egy kicsit bonyolultabb kóddarabhoz odaírtam, hogy mi a fészkes fenét csinál ez az egész, és a többsoros /* */ kommentet használtam. Erre valakinek az volt a kifogása, hogy "mi" csak a /** */ -t használjuk.
Akkor kapd be a patch-em :-)

Egy kis saját: final paraméterek

Á igen, gondoltam a végére csemegének megint egy saját paranoiámat dobnám be. Legalább tudok róla, hogy van :-) sőt már egyszer meg is gyóntam. Szóval amerre járok, hajlamos vagyok főleg a hosszabb metódusok paramétereit átírni final-ra. Ennek funkcionálisan a világon semmilyen következménye nincs: amennyiben lefordul, működni is fog. Azért alakult ki nálam ez a szokás, mert a parameter-reassignment-et teljesen olvashatatlannak tartom.
De én legalább senkivel nem kezdek el cseszekedni, ha nem finalként definiálja a paramétereket a patcheiben :-)

Policy Police

Pár eszközt említenék meg a kód konvenciók betartatásához illetve figyeléséhez:
  • nagyon szimpatikus a sonar. Azt is meg lehet oldani vele, hogy elhasaljon a build, ha súlyosabb hibát talál, de ilyen beállítással még nem találkoztam. A sonarral kapcsolatban azt tartom szomorúnak, hogy nagyon kevesen használják ténylegesen, pedig átalában egy csomó dologra hívja fel a figyelmedet, szerintem a használatával tényleg tanulhatsz pár érdekes dolgot, legalábbis én tanultam tőle.
    A legfontosabb, hogy időben láthatod a változást. Szerintem az egésznek nagyon kevés értelme van, ha nem a változást figyeled.
  • nagyon idegesítőnek találtam a maven-checkstyle plugint, ami az ovirtben nem csak pazarolja az időmet, de olyan marhaságokon képes eltörni a buildet, mint trailing spaces. Amikor éppen egy kritikus hibát próbálsz javítani el tudod képzelni mennyire örülsz egy ilyennek.

Amúgy nekem végülis 8, mondhatnám. Magyar jelöléses 80 karakteres sorhosszú, dokumentálatlan és akár egysorba írt kódot kapunk és nem ettől lesz az eredmény egy stack trace.
A kód konvenciókban engem az zavart mindenhol, a C/C++-os, Perl-es Python és PL/SQL-es projectekben egyaránt, hogy a kód konvenció személyenként változott. Azaz ha bedobod review-ra a patch-et, akkor attól függően lesz lefikázva vagy elfogadva, hogy ki nézi meg. Kb mint egy vizsgán, hogy melyik tanárnál vizsgázol.
Projectek illetve cégek különböző csoportai között egyre nagyobb véleménykülönbségeket láttam.

Ezzel együt lehet élni persze, a probléma akkor következik, amikor az egyik csoport megpróbálja rákényszeríteni a konvencióit a másik csoportra, illetve meg akar határozni egy globálisabb (pl céges) kódkonvenciót. 
Na, ez az amiből egyetlen egy sikeres próbálkozást nem láttam, de nagyon hosszú és anyázásig elmenő vitát jópárat.
"Persze, hogy benne van a céges policy-ban. Most írtam bele."
Én azt hiszem az lenne egy egyensúly közeli állapot, ha egy-egy projecten együtt dolgozó emberek a nem funkcionális elvárásaikat megbeszélnék nem egy bizottsági üllés keretében hanem inkrementálisan, ahogy jön. Azt is jobbnak hiszem, ha ezeket a szabályokat nem próbálják meg keményen bármi áron betartani. Ha funkconálisan teljesen jó és nem halom ganaj a kinézete, had jöjjön, aztán lesz időnk szépítgetni. 
Nyugdíj után bármire :-)
Ezt én sem tarom univerzálisan bevethető dolognak, a demokrácia nem mindenkivel működőképes, egyre több emberrel pedig egyre kevésbé.

2012. február 15., szerda

Gyárlátogatás: BuzzwordClass

Egy kis lista arról, hogy milyen ködösítő jelzőket szedtem össze, amik nem valami design pattern alkalmazását jelzik, hanem csak valahogy belekerülnek osztályok nevébe.

  1. Domain - Ez általában olyasmit akar, hogy sokminden lehet benne és úgy ahogy van egészben van. Hát ezt akármire is mondhatnánk. pl weblogic domain, storage domain, satöbbi...
  2. Business - Hát ez fogalmam sincs mit jelent, többnyire semmit, simán behelyettesítem BLF-re.
  3. Enterprise - Ez azt jelenti, hogy a józan paraszti logika szerint marhaság-gyanús, de karriercélokkal architektúrális okokkal jól alátámasztható.
  4. Manager - Ez néha ugyanaz, mint a valódi életben: konkrétan nem ő oldja meg a problémát, de ismeri azt, aki igen.
  5. Entity / Bean - Ez egyszerűen csak azt jelenti hogy ő az adat, de ez sajnos nem jelenti a történet végét.
Mit szólnál ehhez az osztálynévhez: EnterpriseBusinessManagerDomainEntityBean? Kemény bullshit, nem? :-)

2011. szeptember 11., vasárnap

Gyárlátogatás: Logging

A logging megintcsak egy érdekes és gubancos kis szál a java történetben. Nagyon szerény elvárásaim ezek lennének:
  • Legfontosabb: Ha a logging el van csűrve, azért az alkalmazás még csak menjen!
  • Lehessen konfigurálni a logging szintet
  • Lehessen konfigurálni azt, hogy hova menjen a log - többnyire file, valami archiválós megoldással vagy méret vagy idő bontásban, fejlesztőknek stdout, had kapjuk az arcunkba :) Vannak egzotikusabb megoldások is
  • Az nagggyon jóóó, ha nem kell újraindítani az appot a logging konfigurálása után. Ugyanakkor belátom, hogy egy évben csak egyszer van karácsony.
Mostanra sikerült odáig is eljutni, hogy a Logger-t kb így deklaráljuk:
private final static Logger logger = ...kakukk...

Ezt várja el a checkstyle, a PMD és a satöbbi. Nem tűnik nagy dolognak, de pl az avalon framework implementációi még bedobálták volna a komponenseknek egy setLogger metóduson keresztül. Persze nem kötelező így használni :-D

Nekem igazából nagyon szimpatikus ez a private final static dolog. A logger legyen a kód számára elérhető mindig. Ne írhassa felül semmi és ne lehessen null se. Amennyiben sikerült az osztályt betölteni, alighanem loggered is van. Innentől már nagy baj ezzel nem lehet.

Mit kellene logolni?

Hát kicsit izlés-codestandard-hitvita tárgya az, hogy mit mikor és hogyan kell logolni. Én nem hiszek a policy-kben, azt hiszem a józan paraszti ész valami ilyesmit diktálna, ha kellene a parasztoknak bármi ilyesmivel foglalkoznia: logolni azt érdemes, ami érdekelni fog hibakeresés közben, és persze csak olyan szinten, amilyen szinten keresni fogsz. Minden más csak a helyet fogja zabálni a szerveren. A logging frameworkok között enyhe eltérés van a szintek tekintetében. Azt hiszem van, ahol nincs trace szint, hanem debugnál kezdődik. Nekem a nagyon sok szint használata nem tetszik, nem tűnik praktikusnak.

Ja igen, bonyolult és anyázásig menő viták tárgya az is, hogy ha esetleg valami stringet hozunk létre a loggernek, amit logolunk, akkor csekkoljuk-e körülötte a debug szintet egy if-fel. Erre gondolok:

if(logger.isDebugEnabled()) {
  logger.debug("Baromira fajt osszerakni ezt a stringet: "+getTerribleString());
}

Szerintem ezzel a legtöbb alkalmazásban nem lehet mérhető teljesítményjavulást elérni. Inkáb csak a kód komplexitásának növekedését. Illetve akinek tényleg már csak ez segített, annak had gratuláljak a kiválló termékhez.

System.[out|err].println()

Na ez a logging elötti logging volt. Már rég megástuk a sírját, már rég ott térdel a szélén, de még mindig nem húztuk meg a ravaszt. Nagyon sokan használnak még ma is ilyesmit. Ezt azt hiszem korrekt tudatlanságnak és/vagy igénytelenségnek nevezni.
Na jó, szóval ez trehányság, de akkor mit kellene használni helyette? A válasz erre kb 2-3 évente változik akár még egyetlen fejlesztő esetében is.

log4j.properties - köszi Bocinak a megosztásért :)
Log4j

Ha jól emlékszem a log4j volt az első komolyan elterjedt logging api.
A log4j-ről tudni érdemes dolgok 99 százalékát tudod, ha tudsz egy log4j.properties file-t írni. Na, ez az a dolog, ahol kiválló alkalmak adódnak a dolgok elcseszésére: illik nem belecsomagolni a log4j.properties file-t a csomagodba. Ezt azért a mainstream opensource libraryk tudják, de enterprise körökben frekventált elcseszés tárgya. Ez még mehetne a multkori konfigurációs kérdéskör boncolgatásához.

Ennyi: Igen, kell a log4j.properties file - pontosabban jó ha van. De ez a konfiguráció része, nem csomagolhatjuk a kódhoz.

Alternatív...

A log4j sikere után sok alternatív logging api jött. Az alternatívok közül legtöbbet a commons-logging projectet lehetett látni. Ha jól tudom a sikerének oka az, hogy az apache projectekben kötelező (volt?). Ez elég sovány ok :-) Mindenesetre a commons-logging már végülis facade jellegű. Azaz az API mögött végülis valamibe logol bele. Valamelyik másik logging frameworkbe.

java.util.logging

A java.util.logging így visszatekintve rá egy szomorú példa a JCP töketlenségére. Aki ragaszkodik a szabványokhoz, az biztosan használja is, de más okot nem is tudnék rá. Az az egy nagyon tetszett benne, hogy a jconsole-n keresztül lehet babrálni a logging szinteket. Még talán akkor veszi az ember használatba ha valamilyen oknál fogva nem akar semmilyen dependency-t. Ultra-minimalista cuccokhoz, aminek nem kell semmi, csak egy JRE, és megy.

slf4j

Simple Logging Facade for Java. Itt tart a történet. Ma kb mindenki slf4j-vel logol, én is. Egyszer valami podcastot hallgattam ennek az előnyeiről, és ilyeneket említett a csákó, hogy végre Loggernek hívják a loggert, nem Log-nak, mint a commons-logging. Hát ez elég sovány ok azért, ebben azt hiszem egyetértünk :)
A slf4j-nél tipikus elba, amikor valakinek az APIja nem csak a slf4j-api-n dependel, hanem berántja valamelyik logging rendszerhez kötő részét (pl tipikusan slf4j-log4j13-at amikor te már berángattad a slefn-log4j12-t). Ugyanis nem, ezek a dolgok nem férnek meg békésen egymással a classpathon. Természetesen ez egy gyógyítható betegség (pl maven dependency exclude), de néhány bosszús pillanatot sikeresen össze tud hozni.

...és végül: log4j :-)

Akárhogy is, de az összes konfigurációban, amit eddig láttam a facadeken keresztül a végén a logging üzeneteidet a log4j kapja meg, és file-be nyomja be. Az üzemeltető csapatok a log4.properties-t keresik, ha debugolni kell valamit. Ennyi.
Szóval ebből a szempontból a történet marha hosszúra nyúlt, de a lényege nagyon keveset változott.

A java elött

Nem tudom mennyire rendelkeznek a java elődei logging apival, amennyire emlékszem amit a CGI scriptekben stderr-re írtunk, na az volt a log, a stdout-ra, na az meg a kimenet. Nem túl kultúrált. A C kultúrám megintcsak félelmetesen alacsony, C/C++-ban úgy logoltunk, hogy precompiler direktívaként megadtuk a log szintet. Nyilván újrakonfignál újra kell fordítani, ezt nem nevezném valami baráti megoldásnak.

Update: átneveztem ezt a postot, hogy kicsit kiemeljem azt hogy nem arról szól, hogyan kell logolni, hanem arról, hogy miket láttam tényleg. Többi ilyen.

2011. augusztus 24., szerda

Gyárlátogatás: konfiguráció

A következő dolog, amit mindenki totál máshogy csinál a java/j2ee/jee környezetben az a szoftver konfigurációja. A téma sajnos nem annyira "egyszerű" mint az a képesség, hogy a verziószámot meg tudjad mondani, így hát igen szép számban van rá megoldás. Ezek a megoldások még csak nem is diszjunktak, simán átfedik egymást. Egészen biztos, hogy nincsen két ugyanúgy konfigurálható java szoftver. Illetve csak ha pont ugyanaz az ember írta mondjuk 1 héten belül. Szóval oltári buhera zajlik a téren. Mint mindig.

Elvárások a konfigurációval kapcsolatban

Ha én lennék az admin, most így fejből ezeket várnám el az appoktól és fejlesztőiktől:

  1. Legalább az minor release-k között őrizze meg integrítását. Azaz a 1.0-hoz bütykölt konfig had menjen már el a 1.0.1-gyel is.
  2. Ne az alkalmazásba legyen belebuherálva (WEB-INF/classes, satöbbi), hogy amikor az upgrade során rm -rf paranccsal kezeled a régi verziót (ja, backup, csókolom!) ne vesszen el a régi bugokkal együt a konfiguráció is. Legalább a környezet-specifikus konfiguráció ne az appban legyen!

Mint fejlesztő, nagyon szeretem azt, ha nem kell a fél életemet a fejlesztői környezet összebuherálásával töltenem. Értelmes alapértékek (akár pl egy beágyazott DB), könnyű felülcsűrhetőség.
Illetve ezt csak nagyon szeretném, baromi ritka az ilyen. Remélem nem úgy képzelitek el a halálcsillag építését, hogy kiszedik a dobozból, bekapcsolják és működik.

Plain Property file-ok

A property fileok ősi java feature és a legtöbb rendszer még mindig felhasználja a konfiguráció tárolására. Ezzel persze nem rossz dolog. Máig ez a legtöbb konfigurációs megoldás alapja, de persze a tiszta és legalapabb formája az, amikor pl a konstruktorban megkapod a Properties ojjektumot magát és bányásszad ke belőle azt, ami köll. Volt egy ennél kicsit szofisztikáltabb megoldás, ami csak a teljes konfig egy részét passzolta oda... lényegtelen. Ezek tipikusan az IoC-nélküli rendszerek.

Á igen, IoC

Az IoC egy olyan ötlet volt, amiért jópárszor leégettem magam azzal hogy próbáltam megmagyarázni a főnökeimnek valamikor régen, és néha még mostanában is. Ötlet: "Do not call me, I will call you!" Azaz az IoC konténer majd beállítja neked a konfigot, összekapcsolja az ojjektumaidat, elindítja az appod ha kész, illetve elhasal ha nem sikerült (ez esetben az jó, hogy hülyeséggel nem indult el). Ebből eleinte még két faj létezett, az intrusive (pl Avalon) és a non-intrusive, tipikusan POJO jellegű. Az elöbbit mára csak CVS-múzumokban találod. Az utóbbiból se a spring volt persze az első, csak a legnépszerűbb. Volt még elötte picocontainer, nanocontainer, és már a fene se emlékszik mik. Ma Spring, Guice, és az EJB is sok inspirációt kölcsönzött a téren ezektől a projectektől. Vitatkozhatnánk róla, hogy eleget-e vagy sem, de igazából nem érdekelne.

Még itt szeretném megemlíteni azokat a böszme nagy XML fileokat amiket írunk az IoC frameworknek és együt jönnek az appal szinte minden verzióban kicsit úthuzalozva és átkombinálva. Szerintem ne akarjátok, hogy az admin ebben matasson! Az merge-hell! Sírás-rívás, jajjveszék, rollback, cancel, és hasonló kulcsszavak jutnak róla eszembe. (Egy külsős fejlesztő szívatott ilyennel éveken át)

Spring, PropertyOverrideConfigurer és PropertyPlaceholderConfigurer

Ezt a két dolgot igazából nagyon szerettem a spring-ben. Ez megoldás arra, hogy az appcontext-ben összeállított konfigurációt felülcsűrd egy property file tartalmával. Tehát ide lehet tenni az X-et ennek én nagy rajongója vagyok még most is. A különbség a két dolog lehetőség között, hogy az override configurerrel mindent felül lehet csapni (söt, olyat is ami az appcontextben nem is volt benne), míg a placeholder configurer csak a placeholdereket helyettesíti be. Azért gyanús, hogy az előre kigondoltakon kívül jól jöhet, ha időnként más beállításokat is megváltoztathatsz. Természetesen az a placeholder configurerben viszont szimpatikus, hogy az éles rendszerektől megköveteli az előre definiált placeholderek értékének beállítását, különben nem indul el. Ugyanakkor még mindig jobban szeretem, ha a rendszer értelmes defaultokkal jön, és bármít felül lehet benne csapni.

Mindkettőnek van némi hiányossága. Pl listákat és map-eket nem kezelnek. Na erre mindenkitől láttam valami saját szintaxist és saját megoldást.

Jó, de hova?

Azt a kérdést, hogy hova tegye a rendszergizda a konfig fileokat, illetve az app hol keresse, az izlés és hitviták tárgya. Volt egy melóhelyem, ahol a unix filerendszerhez kellett igazítani a struktúrát. A konfig az etc-be, a program kód meg a usr-be (usr-be?!?!?!), felhasználókkal kapcsolatos dolgok talán a home-ba, adatok a var-ba. Igen, még mindig java szoftverfejlesztésről van szó. Vicces volt egész addig amíg rá nem jöttem hogy komolyan gondolják. Utánna már nem :-D

Mindenesetre a legtöbb program egyszerűen csak a classpath-on keresi a konfigját, többnyire {appnév}.properties alatt. Ez talán a legértelmesebb dolog, de minden appszerveren máshova kell dobni, hogy a classpath alatt legyen. Had sírjon aki migrálni merészel!

JMX!

A JMX még belerúg ebbe a témába kicsit. JMX-en keresztül beállíthatod az alkalmazásod konfigurációját, meghívhatsz rajta maintenance metódusokat, stb. A JMX király dolog, de arról nem gondoskodik, hogy a container újraindítása utánra is megmaradjanak ezek a beállítások. Az az app gondja. Valószinúleg ez lehet az oka annak, hogy hibakeresés közben láttam csak JMX-et, konfiguráció beállításhoz soha. Nevezhették volna inkább java debugging extensionnak.

JNDI?

Ha már a container szolgáltatásainál tartunk. Sokat tűnődtem rajta, hogy a JNDI miért csak annyi lett, amennyi lett. Semmi mást nem csinálsz vele, csak java.sql.Datasource és java.mail.Session objektumot halászol ki belőle, többnyire hardcode-olt címről. Az innen kihalászott objektumok előre fel vannak konfigolva a környezet beállításaival: hol az adatbázis, milyen adatbázis, hány kapcsolatot nyithatok rá, satöbbi, hasonlóan az smtp szerverrel. Na jó, még arra is használjuk néha, hogy a LDAP szervereken kurkásszunk valamit. Ennyi?
Tehát akkor az adatbázis és SMTP eléréssel kapcsolatos infókat akkor ott tartjuk. A többit miért nem? És ha a többit nem ott, akkor azt miért? Nem lenne jobb egybe tartani?
Kipróbáltam pár appszervert, a GUI/web-es felületeken keresztül egyik sem volt hajlandó a fenti kettőtől eltérő ojjektumot elhelyezni a JNDI fában. Kézzel be lehet haxolni.

Adatbázis

Remélem mindenki érzi, hogy egy komoly robosztus ACID-compliant replikált és backupolt nagy teljesítményű, 24/7 365 felügyelt RDBMS a legrojszrojszabb hely a világon, ahova a konfigját az ember berakhatja. Szóval legkevésbé sem ritka, hogy az appok az adatbázisban tartják a konfigjukat. Akkor már csak az a kérdés, hogyan éred el az adatbázist, de ezt többnyire a JNDI megválaszolja.

Én nem érzem a késztetést :-) Csupán technikai oldalról, nem értem mi haszna van az ACID viselkedésnek akkor, amikor olyan adatokról van szó, ami csak akkor változik, amikor éppen bütyküljük a rendszert. Sokkal hasznosabb ha gyorsan és egyszerűen hozzá lehet férni, mindig. Továbbá nagyon nagyon szép ha pl valami verziókövetőben tárolhatjuk, hogy tudjuk ki buherált rajta és mit, mikor hogy nézett ki. Egy text-file sokkal szimpatikusabb. Na ezt talán inkáb oda kellett volna írnom a propertyfile-hoz. Na mindegy, úgyis elcsesztem már pár helyen ezt a cikket.

2011. augusztus 17., szerda

Gyárlátogatás: verziószám

Tipikus igény a szoftverekkel szemben, hogy meg tudják mondani a saját verziószámukat. Ez főleg azért kell, hogyha a kedves felhasználó meglát egy bogarat benne, meg tudja mondani, hogy melyik verzióban látta. Legalábbis hogy esélye legyen rá. Erre szedtem össze az általam eddig látott és használt megoldásokat, azzal együt hogy mi a tipikus elba**** velük kapcsolatban. Nemcsak hogy egyik sem tökéletes megoldás, de mindegyik szerintem elég töketlen. Persze a sajátját mindenki szereti :-)

Build script

Ez volt a leggyakoribb. Az ötlet annyi, hogy amikor buildelsz, akkor generáljon neked egy számot bele egy file-ba, amit valószinűleg besúvaszt utánna a classpath-ra. Ezt persze csak inkrementálgatni kell. Láttam olyat, hogy ez a file csak úgy "floating around" azaz akik release-t csináltak azok tudták a számozást, aztán volt olyan hogy visszakommitolták legalább időnként a verziókövetőbe. Ja még ezen belül is két különböző műfaj van, van aki verzió számot tart számon, van aki build számot. Szóval a kombinációk száma igen magas.
A tipikus elba:

  • Amikor nincs meg a file a classpathon, akkor valami törik
  • Elfelejted inkrementálni a build számot
  • Elfelejted a verziószámot bepakolni a verziókövetőbe, mielött tegelsz



Database, config

Olyat is láttam, hogy az emberek a konfigurációba, vagy gyakrabban az adatbázisba írják bele, hogy mennyi a szoftver verziószáma. Az egyébként tetszik, hogy az adatbázisban valahol benne legyen az, hogy milyen patcheket hajtottak végre rajta és milyen verzió satöbbi a jelenlegi schema, de akkor most az operátorra bíztuk, hogy felülbuherálja a verziószámot.
Elba:

  • Azon felül hogy anyukádat emlegetik közben, még rizikó tényező hogy az operátor valamikor visszacsinálja vagy átírja, vagy éppen ellenkezőleg: elfelejti átírni.
  • Az fenti elfelejtések simán ide is passzolnak

SVN-way


Ezt én találtam ki és hát primitív mint a szerzője: Csinálj egy osztályt pl Version néven, tegyél bele egy final static String mezőt, aminek az értéke legyen ennyi: "$HeadURL: http://svn.blf.hu/fubar/trunk/src/main/hu/blf/Version.java $", plusz egy metódust, ami fubar és az src közül kibányássza neked ami ott van: pl ennyi: StringUtils.substringBefore(StringUtils.substringAfter(version, "/fubar/"), "/src/"), ne felejtsd el a végén az svn property-k között a keywords-be beleírni azt hogy "HeadURL".
A build numebert nyilván hanyagolja. Csak azt adjuk oda bárkinek is, amit szépen betegeltünk.
Jó, a nyilvánvaló hátrányok elött felsorolnám hogy miért szerettem ezt:

  • Soha nem sikerült elszúrnom :) A Version osztály mindig valami értelmeset ad vissza. Pl azt hogy "trunk". A legdurvább elcseszés esetén semmit, de nem NullpointerException-t.
  • A release során simán meg lehet róla feledkezni. A release nálam ennyi: mvn release:prepare release:perform (így "howto release" manuált se írtam soha)
  • Ja és ez az egész substringes dolog csak a cicoma rajta, sima statikus text/html fileokkal is működhet, ha érti a felhasználód a HeadURL-t hogy mi az.
Akkor jöjjön a hátrány:
  • Totálisan SVN függő - azért volt ilyen a CVS-ben is, de arra már kiemlékszik
  • Az SVN-re meg most úgy fintorgunk mint a CVS-re úgy 6-7 évvel ezelött. Valahogy akkor jött ki az SVN, nem?
Még annyit a megoldás portolhatóságáról, hogy a git pl nemcsak hogy nem csinálja, de elvben is ellenzi. Linus Torvalds szerint írjál scriptet. Szerintem meg ... :-) Na mindegy, nekem ez nem tetszik, túlságosan könnyen elcseszhető. Meg bújja a git elba manuálját az, akinek nincs jobb szórakozása.

Ennyi... részemről

De kiváncsi lennék a ti tapasztalataitokra, linkeljétek vagy írjátok ide nyugodtan! Köszi előre is!

2011. július 17., vasárnap

Gyárlátogatás: saját főztöm

11 évvel ezelött landoltam egy új munkahelyen -azóta rég beszünt- , ahol valami tetűnagy rendszert fejlesztettünk C++-ban. Volt a dologban egy kis CORBA (béke poraira) és Oracle RDBMS, mert azt már akkor sem lehetett kihagyni semmiből. Érkezés után az űberführer mondta el, hogy mi is ez az egész. Egy chat szerver volt végülis, sok klienshez. Nem IRC protokol kompatibilis, hanem custom webes chat. Szóval az első reakcióm az volt, hogy "Klassz! Próbáljuk ki!", mire az űberführer már az első napomon korán reggel jól lecseszett: "Figyelj, nem érünk rá játszani, nagyon sok dolgunk van!"
Ez nekem ilyen tréfás emlék arról a cégről, mert végig ilyen volt, a termékeket soha nem próbálgattuk. Tellt-múlt az idő. Úgy kb 8-10 helyen dolgoztam azóta, ebből 2 helyen volt olyan ember, hogy "tesztelő". Igazából csak az egyik esetében jelentette ez azt, hogy az az ember automatizált teszteket programoz. Most már biztosan változott a kép, a sok kis magyar cég helyére többnyire multik jöttek, többszáz embert alkalmaznak és náluk nem az a QA, hogy "aha, kipróbáltam..."

A tesztelő mellett kiválló input lehet egy ügyfél (illetve a felhasználó, mert az nem ugyanaz) is, bár az kicsit változatosabb tud lenni minőségben. Például az egyik külföldi munkatársnő egyetlen hibajelzést tud leadni: "nem működik". Ilyenkor 10 email váltás, telefonon felhívom, satöbbi, fél óra amíg kiderül hogy a loginig el sem jutott, a browsere nem jut át a proxyn. Más felhasználókból egész értelmes dolgokat lehet kihúzni, mint például hogy nem értették hogy mire való az a gomb és nem merték megnyomni, nem találták a dokumentációban, pár kör levelezés után megegyezünk abban hogy hogyan tudunk segíteni.
Ez SCRUM-ban talán a product owner feladata lenne, de a személyes kapcsolat a felhasználóval azon túl hogy baromi sok időt emészt fel és néha még éjszaka is a munkahelyi leveleimet válaszolgatom meg, egyébként szerintem egyrészt sokat lehet belőle tanulni, másrészt pedig tényleg elhozza az egész problémakört oda. Ebben a problémakörben nem csak dolgozol, hanem ebben élsz. Azok, akikkel naponta spanolsz kint a konyhában vagy felhívnak valami problémájukkal, azok lesznek a társadalmi kapcsolataid, a te saját kicsi világod. Így egy kicsit más érzés egy problémán dolgozni. Nem azért csinálod, mert a managered azt mondta, vagy mert van egy jira issue rá és bekerült az iterációba, hanem azért, mert valakinek a környezetedből gubanc. Például volt egy hely, ahol ketten dolgoztunk 150 callcenteres nő között. Nekik az üzleti logikától nagyban fügött, hogy mennyi pénzt vihetnek haza hó végén, ezért munka végén volt aki bejött és megköszönte hogy jó munkát osztottunk neki (illetve a kód amit írtunk), vagy ránköntötte minden haragját amiért nem.

Csodálatos visszajelzés az üzemeltető csapat, amennyiben van ilyen :). Ők nem fogják megmondani neked a hiba okát, van ezer más bajuk, viszont nagyon precíz információkat tudnak adni arról hogy milyen hibajelenséget láttak és ez mennyire fáj. (rendszer outage, crash, túlterhelés, lassulás, memory leak, restart, satöbbi) Aztán persze tesznek rá, hogy a kód helyesen működik-e vagy sem, az már valaki más baja. Például az tök jó, hogy a vasműben minden nap többször is összefutok az üzemeltetőkkel. Másként nem tudok bemenni és kijönni. Szóval ha bármi gubanc volt, ők biztosan nem felejtik el.

Persze direktben a felhasználótól kapni vissza az élménybeszámolókat egy bizonyos mennyiségű felhasználó felett már nem szórakoztató, ilyenkor bejön a support, management, satöbbi. Csak szerintem annyira gyakran van az, hogy a management beáll középre a kommunikációt bonyolítani és nagyon lényeges információk vesznek el ezen a ponton.

No, ennyi jutott eszembe erről az eating your own dogfood témáról. Ja meg hogy csütörtökön palacsinta, az is a saját főztöm lesz :-)