J00.qxd
11/13/2008
3:35 PM
Page ix
Elõszó Képzeljük el, hogy egyik munkatársunk egyszer csak így szól hozzánk: „Enyém házastárs éjjel ma egy nem megszokott élelmiszert gyárt az otthonban. Rácsatlakozol?” E szavak hallatán bizonyára a következõ három dolog futna át az agyunkon: 3: Úgy fest, vacsorázni hívtak... 2: Ez az ember nem beszéli anyanyelvi szinten a magyart. 1: Mi van?! Aki tanult már idegen nyelvet, aztán megpróbálta azt a tantermen kívül is használni, az bizonyára tudja, hogy ilyenkor három dologra kell egyszerre figyelni. A nyelvi struktúrákra (nyelvtan), hogyan neveznek dolgokat az adott nyelven (szókészlet), és arra, hogy hogyan szokás kifejezni bizonyos a hétköznapi dolgokat (szóhasználat). Mivel a nyelvórákon legtöbbször csak az elsõ kettõ kerül szóba, idõnként azon kapjuk magunkat, hogy anyanyelvi beszélgetõtársunk elfojtott röhögéssel küzd, miközben mi vért izzadva próbáljuk magunkat megértetni vele. Hasonló a helyzet a programozási nyelvekkel is. Meg kell érteni a nyelv alapjait: algoritmikus, funkcionális, objektum-orientált? Ismerni kell a szótárat: milyen adatszerkezetek, mûveletek és milyen nyelvi lehetõségek állnak rendelkezésünkre a szabványos programkönyvtárakban? Meg kell ismerkednünk azonban a bevett és hatékony módszerekkel is, amelyek segítségével jól mûködõ programokat írhatunk. A programozási nyelvekrõl szóló könyvek gyakran pusztán az elsõ kettõrõl szólnak, és többnyire csak hellyel-közzel (vagy egyáltalán nem) említik meg a helyes használatra vonatkozó tudnivalókat. Ennek talán az az oka, hogy az elsõ kettõrõl sokkal könnyebb írni. A nyelvtan és a szókészlet magának a nyelvnek a sajátossága, a használat azonban már arról a közösségrõl szól, amely alkalmazza a nyelvet. A Java programozási nyelv például egy objektum-orientált nyelv, egyszerû öröklõdéssel, amely az imperatív (utasítás-orientált) kódolási stílust támogatja az egyes metódusokon belül. A programkönyvtárakban megtaláljuk a megfelelõ eszközöket a grafikus felületek elõállításához, a hálózati használathoz, a párhuzamos futtatáshoz (azaz az elosztott számításokhoz) és a biztonsági környezet kialakításához. A kérdés már csak az, hogyan is lehet a legjobban kihasználni ezeket a lehetõségeket a gyakorlatban?
J00.qxd
11/13/2008
x
3:35 PM
Page x
Hatékony Java
És igazából ez a lényeg. A programok – a beszélt nyelvekkel és a legtöbb könyvvel ellentétben – idõnként változnak. Általában nem elég olyan kódot írni, amely hatékonyan mûködik, és amelyet mások is megértenek; olyan programokat érdemes kiadni a kezünkbõl, amelyeket módosítani is könnyû. Képzeljünk el egy F feladatot, amit tízféle módon lehet programmal megoldani. A tízbõl hét esetlen, nem hatékony, zavaros. A kérdés az, hogy a maradék háromból melyik áll a legközelebb ahhoz, amit a szoftver következõ évi kiadásának F feladata követel majd meg? Számos könyv van, amelyekbõl a Java programozási nyelv nyelvtana megtanulható, köztük az Arnold, Gosling és Holmes által írt The Java™ Programming Language [Arnold05] vagy a Gosling, Joy (szerénységem) és Bracha által írt The Java™ Language Specification [JLS]. Könyvek tucatjai tárgyalják a Java programozási nyelvhez tartozó programkönyvtárakat és API-kat is. Ez a kötet a fent vázolt célkitûzések közül a harmadikat szeretné megvalósítani: a bevált és hatékony módszerek megtanítását. Joshua Bloch számos évet töltött el azzal, hogy a Sun Microsystems szakembereként használta a Java nyelvet, sõt maga is írt hozzá alkalmazásokat és kiterjesztéseket. Sok más fejlesztõ programjait (köztük az enyéimet is) olvasta. Ebben a mûben rendszerezve foglalja össze tanácsait arra vonatkozóan, hogyan érdemes strukturálni a programkódot a helyes mûködés és olvashatóság érdekében. Olyan programok írását tanítja meg, amelyeknek késõbbi módosítása vagy kiegészítése nem okoz fejfájást másoknak – sõt, kifejezetten az lesz az érzése utódainknak, hogy programunk kellemes, könnyed és az elegáns. Guy L. Steele Jr. Burlington, Massachusetts 2001. április
J00.qxd
11/13/2008
3:35 PM
Page xi
Bevezetés Bevezetés a második kiadáshoz A könyv elsõ kiadásának megírása, 2001 óta sok változás történt a Java platformon. A legfontosabb változások a következõk voltak: A Java 5-ben megjelentek az általános típusok, a felsorolási típusok, az annotációk, az automatikus ki- és becsomagolás, valamint a for-each ciklus. Ezekhez hasonló jelentõségû volt az új párhuzamossági programkönyvtár, a java.util.concurrent megjelenése a Java 5-ben. Gilad Bracha-val együtt abban a megtiszteltetésben volt részem, hogy az új nyelvi elemek tervezését végzõ csapatot vezethettem. Tagja voltam annak a csapatnak is, mely a párhuzamossági programkönyvtárat tervezte és fejlesztette Doug Lea vezetésével. A platform másik nagy változása abban állt, hogy elterjedtek a modern Integrált Fejlesztõi Környezetek (IDE-k): az Eclipse, az IntelliJ IDEA és a NetBeans. Az is komoly lehetõségeket nyitott meg, hogy különféle statikus elemzõeszközök jöttek létre, mint amilyen például a FindBugs. Bár ezeknek a kialakításában nem vettem részt, használtam õket, és közben átéltem, hogy milyen erõs hatással vannak a Java fejlesztés gyakorlatára. 2004-ben munkahelyet váltottam: a Sun-tól átmentem a Google-hoz. Továbbra is részese voltam azonban a Java platform fejlesztésének. A párhuzamossági és a gyûjteményes (collections) API-t a Google és a Java Community Process csatornáin át terjesztettem. Abban az örömben is részem lehetett, hogy Java platformon fejleszthettem a Google egyes programkönyvtárait. Megismertem tehát azt az oldalt is, hogy milyen érzés felhasználónak lenni. A könyv elsõ kiadásának 2001-beli megírásához hasonlóan most is az az elsõdleges célom, hogy megosszam tapasztalataimat az olvasókkal. Ily módon követhetik azt az utat, amelyen haladva sikeres programok írhatóak, és elkerülhetik azokat a zsákutcákat, melyek kudarcaimhoz vezettek. Az újonnan bedolgozott anyagban is folytatom a Java platform programkönyvtárainak szabad használatát a valódi életbõl vett példák bemutatása kapcsán. Az elsõ kiadás sikere minden várakozásomat felülmúlta. Mindent megtettem azért, hogy ugyanebben a szellemben jelenjen meg ez a kiadás is, miközben az új idõknek is szeretnék megfelelni az új részek megírásával. A könyv mérete elkerülhetetlenül nõtt: 57 tételrõl 78-ra. Ez nemcsak
J00.qxd
11/13/2008
xii
3:35 PM
Page xii
Hatékony Java
annyit jelent, hogy az eredetihez hozzátettem még 21 tételt, hanem az elsõ kiadás 57 tételét is alaposan átdolgoztam, és esetenként el is hagytam belõlük elavultnak bizonyuló részleteket. A Függelékben megtekinthetik, hogy hogyan viszonyul a második kiadás anyaga az elsõ kiadáséhoz. Az elsõ kiadáshoz írt bevezetésben úgy fogalmaztam, hogy a Java programozási nyelv és a hozzá tartozó programkönyvtárak a kód kiváló minõségéhez és hatékony programozáshoz vezettek, és hogy öröm ezekkel dolgozni. Az 5. és 6. kiadással megjelent változások ezt még inkább elõmozdítják. A platform már sokkal nagyobb és összetettebb, mint 2001-ben volt. Ám ha az olvasó rászánja az energiát arra, hogy megtanulja a helyes technikákat és az új lehetõségek által biztosított módszereket, akkor sokkal jobb programokat írhat, amivel a saját életét is megkönnyíti. Remélem, hogy ebben a kiadásban is tükrözõdni fog a platform iránti töretlen lelkesedésem, és lehetõvé teszi, hogy a platform által kínált lehetõségeket még hatékonyabban és élvezetesebben használhassák ki könyvem olvasói. San Jose, California 2008. április
Az elsõ kiadás bevezetõje 1996-ban szedtem a sátorfámat, és elindultam nyugatra a JavaSofthoz (ahogy akkor hívták), mivel világos volt, hogy ott zajlanak csak igazán az események. A közbeesõ öt évben a Java platform programkönyvtárainak tervezõjeként dolgoztam. Több könyvtárat terveztem, valósítottam meg és tartottam karban, sok más könyvtár fejlesztésével kapcsolatban pedig konzultánsként is közremûködtem. A Java platform éretté válásakor vezetõ fejlesztõként felügyelhettem ezeknek a könyvtáraknak az alakulását ami olyan lehetõség volt számomra, amilyen egy életben rendszerint csak egyszer adatik meg. Nem túlzás azt állítani, hogy korunk legnagyobb szoftvermérnökeivel dolgozhattam együtt. Mindeközben sokat tanulhattam a Java programozási nyelvrõl – mi mûködik, mi nem, és hogy miként lehet használni ezeket a könyvtárakat a lehetõ legjobb hatás elérésének érdekében. Ez a könyv kísérlet tapasztalataim megosztására. Meg szeretném mutatni az olvasónak azt az utat, amelyen haladva sikeres programokat írhat, miközben elkerülheti azokat a zsákutcákat, melyek az én kudarcaimhoz vezettek. A könyv szerkezetét Melyers Effective C++ [Meyers98] mûve alapján alakítottam ki. Ötven szakaszból áll, melyik mindegyike egy speciális programozási szabályt mutat be – ezekkel hatékonyabbá tehetõ a programok tervezése és megírása. Azért választottam ezt a formát, mert Meyers könyvének egyszerûsége nekem nagyon megtetszett – remélem, az olvasóknak is öröme telik majd benne. Több esetben vettem a bátorságot, és a való életbõl vett példákkal világítottam meg a mondanivalót. Olyan esetek is voltak, amikor saját kódrészleteimen vagy kollégáim konkrét programjain mutattam be azt, hogy valamit jobban is meg lehet oldani. Õszintén sajnálom, ha ezzel bárkinek is kényelmetlenséget okoztam. A negatív példákat nem azért idéztem, hogy lejárassak bárkit is, hanem az együttmûködés szellemében, hogy mindannyian tanulhassunk az elõdök hibáiból.
J00.qxd
11/13/2008
3:35 PM
Page xiii
Hatékony Java
Bár könyvem nemcsak az újrahasznosítható komponensek fejlesztõinek szól, óhatatlanul megjelenik benne ez a téma, hiszen tény, hogy az utóbbi két évtizedben ilyenekkel foglalkoztam. Természetesnek érzem azt a megközelítést, hogy exportált API-k fogalmaiban gondolkodom, és mást is erre bátorítok. Ha valaki nem újrahasznosítható komponenseket fejleszt, akkor is javítja az általa írt szoftver minõségét, ha ebben a megközelítésben tekint a programfejlesztésre. Az sem ritka, hogy valaki anélkül ír újrahasznosítható komponenseket, hogy ennek tudatában lenne. Írunk például egy hasznos segédeszközt, megosztjuk a környezetünkkel, aztán kisvártatva már fél tucat felhasználónk van. Ettõl kezdve már elvész az a rugalmasság, amely az API ötletszerû megváltoztathatóságából adódna; azok az erõfeszítések azonban igencsak meghálálják a rájuk szánt idõt és energiát, amelyeket a legelsõ API helyes megtervezésre szántunk. Az új pehelysúlyú szoftvertervezési módszertanok fényében (ilyen például az Extreme Porgramming, [Beck99]) elsõ látásra talán természetellenesnek tûnhet, hogy ennyire az API tervezésre koncentrálok. Ezek a módszertanok azt hangsúlyozzák, hogy olyan programok írása a cél, amelyek a lehetõ legegyszerûbb módon oldanak meg egy-egy feladatot. Ugyanakkor ha ilyen módszertan szerint dolgozunk, akkor is azt fogjuk tapasztalni, hogy az API megtervezésére szánt idõ igencsak megtérül az újratervezés (refactoring) folyamán. Az újratervezés alapvetõ célja a rendszer szerkezetének javítása és a kódkettõzés elkerülése. Ezeket a célokat csak a rendszer komponenseinek jól megtervezett API-jai révén érhetjük el. Nincs tökéletes nyelv, de van néhány kiváló. Úgy látom, hogy a Java programozási nyelv és a hozzá tartozó programkönyvtárak rendkívül sokat segítenek a kiváló kódminõség elérésében és a hatékony programozásban olyannyira, hogy egyenesen öröm velük dolgozni. Remélem, hogy könyvemben tükrözõdni fog a platform iránti töretlen lelkesedésem, és megmutatja, hogyan használhatja ki az olvasó is a nyelv által kínált lehetõségeket a maga örömére. Cupertino, California 2001. április
xiii