![]() | ||
Joel a szoftverről szoftvermenedzsment egyszerűen
| ||
A rossz kód rosszul is nézzen kiÍrta: Joel Spolsky (2004. június 13.)
Még 1983-ban volt, hogy elkezdtem az első rendes állásomban dolgozni. Az Oranim hatalmas kenyérgyár volt Izraelben, ami úgy napi 100.000 kenyeret gyártott minden éjjel, hat óriási kemencében, repülőgép-anyahajó méreteivel. Az első nap ahogy körülnéztem, képtelen voltam elhinni, mekkora kupleráj van. A kemencék oldala sárgállott, a gépek rozsdásak voltak, minden tele volt zsírral. – Mindig ekkora rendetlenség van? – kérdeztem. – Mi? Miről beszélsz? – kérdezte az üzemvezető. – Most végeztünk a takarítással. Hetek óta nem volt ilyen tisztaság. Aha. Hónapokig takarítottam a pékségben, mire felfogtam miről beszéltek. Egy pékségben az a tisztaság, ha nincs tészta a gépeken. Az a tisztaság, ha nincs kelő tészta a szemétben. Az a tisztaság, hogy nincs tészta a földön. Nem kell a kemencéket folyton festegetni, hogy tiszták és csinosak legyenek. A sütő festése olyan dolog, amit tízévente egyszer csinálsz, nem pedig naponta. A tisztaságból nem következik a zsír hiánya. Igazándiból egy csomó gép van amit rendszeresen olajozni vagy zsírozni kell, és egy vékony réteg olaj rajtuk pont azt jelzi, hogy most rakták rendbe őket.
Két hónap a pékségben és megtanulod „látni” a tisztaságot. A kóddal ugyanez a helyzet. Amikor kezdő programozó vagy, vagy egy új programnyelvvel ismerkedsz, a kód rejtélyesnek tűnik. Amíg meg nem érted magát a nyelvet, addig nem szúrnak szemet még az alapvető szintaktikai hibák sem. Az első tanulási fázis után felfedezel olyan dolgokat, amikre általában „programozási stílusként” hivatkozunk. És elkezdenek feltűnni, mikor nem jók a bekezdések, vagy a Változó Neveket-Rosszul Nagybetűsítették. Ezen a ponton jellemzően felkiáltasz, „Bazzzeee, egyszerűen muszáj bevezetnünk egységes kódolási konvenciókat!”, majd a következő napot azzal töltöd, hogy konvenciókat írogatsz a csapatnak, az azután következőket azzal, hogy vitatkozz az Egyetlen Igaz Zárójelezés Stílusról, majd még egy pár kellemes hetet, hogy a régi kódot Egyetlen Igaz Zárójelezés Stílusúvá alakítsd, amíg egy főnök fülön nem csíp és rádpirít, hogy már megint olyan dologgal foglalkozol, ami nem hoz pénzt. Ezután már csak azokat a részeket akarod majd újraírni, amiket amúgy is át kellene nézned és lesz egy félig Egyetlen Igaz Zárójelezés Stílusú kódod. Ezek után szépen megfeledkezel az egészről és valami hasonlóan fontos dologgal keresel pénzt, mint például lecseréled az egyik szöveg osztályt egy másikra. Ahogy elmélyülsz egy eszköz használatában, elkezdesz észrevenni más dolgokat is. Olyan dolgokat, amik teljesen szabályosak, még a kódolási szabványodnak se mondanak ellent, mégis zavarnak valahogy. Például, C-ben:
Ez egy szabályos sor, illeszkedik a kódolási szabványodba is, és még azt is csinálja, amit elvárnak tőle. Mégis, ha gyakorlott C programozó vagy, akkor észre fogod venni, hogy a sor dest-et char mutatóként, míg src-t csupán egyszerű char-ként deklarálja, mégha azt is csinálja, amit el akartál érni, valahogy nem oké. Ez a kód egy kicsit csúnyának tűnik. Vagy egy még ravaszabb:
Ebben az esetben a kód 100%-ban korrekt, illeszkedik a legtöbb kódolási konvencióba, és semmi gond nincs vele, mégis, hogy az egységnyi belső utasítás blokk nincs zárójelek közé zárva, valahogy zavar, mert az agyad hátsó sötét részében felmerül, hogy valakinek egyszer majd eszébe jut beszúrni még egy sort.
… és elfelejti odarakni a zárójeleket, amitől a foo(i) véletlenül feltétel nélkül marad! Szóval, ha valahol a kódban látsz zárójelezetlen blokkot, akkor egy egészen parányi kellemetlen érzésed lesz, csökkentve a komfortérzetedet. Oké, eddig bemutattam három szintet, amit elérhetsz programozóként: 1. Nem tudod megkülönböztetni a tiszta kódot a csúnyától. 2. Vannak felszínes elképzeléseid a tisztaságról, jórészt azon a szinten, hogy a kód illeszkedik-e a konvencióidhoz. 3. Kezdenek kellemetlen érzéseid kialakulni a felszínen észrevehetetlen kosszal kapcsolatban is, és eléggé bosszantanak ahhoz, hogy rendbe tedd a kódot. És, van egy még magasabb szint, amiről én igazából beszélni szeretnék: 4. Szándékosan úgy építed fel a kódodat, hogy a tisztasággal kapcsolatos érzeted segítsen korrektebb kódot létrehozni. Ez az igazi művészet: úgy létrehozni robusztus kódot, hogy közbe folyamatosan olyan konvenciókat vezetsz be, amelyek garantálják, hogy a rossz kód szembeötlő legyen a képernyőn. Nézzük ezt meg példán keresztül, majd mutatok egy általános módszert arra, hogyan vezess be kód robusztusságot növelő konvenciókat, végül ez majd abba torkollik, hogy megvédem a Magyar Jelölésmódot – jó eséllyel nem azt a fajtáját, amitől az embereknek émelyegnek – majd kritizálom a kivételkezelés használatát bizonyos esetekben, valószínű nem azokban az esetekben, amik általában előfordulnak veled. De ha meg vagy győződve róla, hogy a Magyar Jelölésmód egy Gonosz Dolog, és a kivételkezelés a legcsodálatosabb dolog, mióta feltalálták a csokis vaníliaturmixot, és nem is akarsz más véleményt megismerni, akkor hajrá, olvass a Rorysnál egy kitűnő képregényt helyette; jó eséllyel nem fogsz sokat veszíteni ezzel; tulajdonképpen egy percen belül elkezdek olyan kód példákat ismertetni, amik olyan gyorsan elaltatnak, hogy még arra se lesz időd, hogy felidegesítsd magad. Nnno. Azt hiszem a terv az lesz, hogy szinte teljesen elaltatlak, majd alattomosan elhitetem veled, hogy a Magyar Jelölésmód=jó, Kivételkezelés=rossz amikor már félálomban vagy és nincs erőd küzdeni. Egy példaOké, elő a példával. Tegyük fel, hogy egy web alapú alkalmazást építesz, mert úgy tűnik, ez mostanában minden gyerek nagy mániája. Létezik egy biztonsági rés fajta, amit „Cross Site Scripting” résként ismernek, vagy másként az XSS. Nem akarok elmerülni a részletekben, csak annyit kell tudnod, hogy amikor webes alkalmazást építesz, mindig ügyelned kell arra, hogy ne adj vissza olyan szöveget, amit egy felhasználó írt be egy kérdőíven. Például, ha van egy weboldalad azzal a kérdéssel, hogy „Mi a neved?” szövegbeviteli mezővel, majd a kérdés elküldésekor feljön egy másik oldal a felirattal, hogy Hello Elemér! (tegyük most fel, hogy a felhasználót Elemérnek hívják), nos, ez egy biztonsági rés, mert a felhasználó begépelhet valami fura HTML vagy Javascript kódot az „Elmer” helyett, és a csúnya Javascript kifejezései csinálhatnak valami kellemetlent, például elolvashatják a sütiket, majd továbbíthatják azokat Dr. Genya gonosz oldalára. Nézzük meg pszeudokódban. Képzeld el, hogy az alábbi kód
bevitelt olvas (pontosabban egy POST változót) egy HTML kérdőívből. Ha ezt a kódot használod:
akkor az oldalad nyitott az XSS támadásokra. Ennyi az egész. Ehelyett el kell kódolnod az inputot mielőtt visszaírnád egy HTML állományba. A kódolás ebben az esetben azt jelenti, hogy lecseréled a " jelet "-ra, és a > jeleket > jelekre, és így tovább. Tehát
teljesen biztonságos. Minden karaktersorozat, ami a felhasználótól érkezik, veszélyes. Semmilyen veszélyes szöveg nem jelenhet meg elkódolás nélkül. Akkor most próbáljunk meg bevezetni egy kódolási konvenciót, ami – ha esetleg hibát ejtenél a kódban – egyszerűen rossznak láttatná azt. Ha a rossz kód legalább rossznak látszik, jó esély van rá, hogy valaki kiszúrja, aki éppen azzal a részlettel dolgozik. Lehetséges megoldás #1Az egyes számú megoldás, ha minden szöveget azonnal elkódolunk, amikor megkapjuk a felhasználótól:
Tehát a konvenciónk ez lesz: ha egyszer olyat látsz, hogy Request amely nincs körülvéve egy Encode-al, a kód biztos, hogy rossz. Nekiállsz edzeni a szemedet, hogy csupasz Request-eket találjon, mert azok ütköznek a konvencióddal. Ez működik, legalábbis abban az értelemben, hogy amennyiben betartod a konvenciódat, soha nem lesz XSS bug a kódodban, de ez nem a lehetséges legjobb megoldás. Ha ezeket a szövegeket valahol egy adatbázisban is el akarod tárolni, és más helyen felhasználni, zavaró lehet a HTML kódolt adat. Például hitelkártya tranzakciónál zavaró lehet a kódolt formátum. A legtöbb webes alkalmazás abban a szellemben készül, hogy semmi nincs elkódolva a legeslegutolsó pillanatig, mielőtt kikerülne egy HTML állományba, és valószínű ez a legjobb felépítés. Sajnos szükségünk van rá, hogy veszélyes formában is tároljunk adatokat egy darabig. Ugorjunk csak neki mégegyszer! Lehetséges megoldás #2Mi van, ha a konvenciónk azt mondja, hogy mielőtt kiírnál bármilyen szöveget, el kell kódolnod?
Most, ha bármikor meglátsz egy csupasz Write utasítást Encode nélkül, tudni fogod, hogy valami nem stimmel. Hát, ez néha sajnos nem fog működni, mert előfordul, hogy HTML elemeket kell kiraknod a kódodban amiket nem kódolhatsz el:
Úgy tűnik, hogy ez sérti a konvenciódat, ami kötelez rá, hogy csak kódolva rakhass ki szövegeket:
De most a „<br>”, aminek egy új sort kellene kezdenie, el lesz kódolva <br> és megjelenik a felhasználónak mint a < b r > kifejezés. Szóval ez se jó megoldás. Tehát, néha nem tudod elkódolni a szöveget, amikor beolvasod, néha meg nem kódolhatod el kiírás előtt, tehát a fenti javaslatok egyike sem jó megoldás. Viszont működő konvenció nélkül még mindig azt kockáztatjuk, hogy valami ilyen történjen:
Vajon emlékszünk rá, hogy elkódoltuk-e a szöveget? Nincs olyan hely a kódban, ahol szemet szúrhatna a hiba. Nincs egy bizonyos hely, ahol észlelhetnénk. Ha van egy halom olyan kódod mint ez, akkor gigászi detektívmunkába kerül, mire végignézel minden szálat, hogy ellenőrizd van-e kódolatlan szöveg, amit kiírsz. Az Igazi MegoldásAkkor találjunk egy kódolási konenciót, ami működik is. Csak egy szabályunk lesz: Minden olyan karaktersorozat, ami egy felhasználótól származik, akár változóban akár adatbázis oszlopban tároljuk, „us” prefixet kell kapjon (ami az „Unsafe String”-re utal). Minden szöveg, ami HTML kódolva van már, vagy biztonságos forrásból származik, „s” prefixet kell hogy kapjon (ami a „Safe” szövegre utal). Hadd írjam újra a kódot úgy, hogy csak a változók nevét írom át, hogy megfeleljenek az új konvenciónknak.
A dolog, amit szeretném ha észrevennél az új konvencióval kapcsolatban, hogy most, ha hibázol egy veszélyes szöveggel kapcsolatban, azt mindig láthatod egyetlen kódsorban, mivel a konvenció sugallja:
biztos hogy rossz, hiszen látod, hogy az eredménye a Request kérésnek egy olyan szövegben tárolódik, aminek a prefixe s, ami a szabályok ellen való dolog. A Request eredménye mindig veszélyes, így mindig olyan változóban kell tartanod aminek a prefixe „us”.
Mindig OK.
Mindig OK.
tuti rossz.
korrekt.
biztos rossz.
OK, ahogy a következő is
Minden egyes kódsor ellenőrizhető önmagában, és ha minden egyes sor helyes, akkor az egész kódtörzs helyes. Végsősoron ezzel a konvencióval a szemeid megtanulják észrevenni, a Write usXXX kifejezést és tudják, hogy rossz, sőt azt is egyből tudni fogod, hogy hogy kell a hibát javítani. Jó, jó tudom, hogy egy darabig nehezen fogod észrevenni a rossz kódot, de csináld ezt három hétig, és a szemed rááll a dologra, ahogy a pékség dolgozója is megtanulta, hogy csak körülnézzen egy hatalmas kenyérgyárban, és azonnal azt mondja, „Jézusom, hát senki sincs aki kipucolja ezt a szerencsétlen tésztaformáló vackot! Milyen igénytelen egy ***** bagázs dolgozik itt?” Tulajdonképpen egy kicsit még ki is terjeszthetjük a szabályunkat, és átnevezhetjük a Request és az Encode függvényeket UsRequest és SEncode nevekre… más szóval, egy olyan függvény ami veszélyes szöveggel tér vissza, kapjon szintén Us prefixet, míg S-el kezdődjenek azok, amelyek biztonságosat, akárcsak a változóknál. Nézzük meg így a kódot:
Csak a kezemet figyeled, nem csaltam ugye? Most már csak annyira kell figyelned, hogy egy értékadás két végén lévő dolgok ugyanúgy kezdődnek-e, és máris észreveheted a hibákat.
Sőt, egy lépéssel még tovább mehetek, a Write átírásával WriteS-re és átnevezhetem az SEncode-ot SFromUs-re:
A hibák így még sokkal szembeötlőbbek. A szemed rááll, hogy „lássa” a koszos kódot, ami hozzásegít, hogy zavaros biztonsági hibákat fedezz fel a normális kódírási és -olvasási munkamenet közben. A rossz kódot rossznak láttatni fontos, de persze nem ez a legjobb megoldás minden biztonsági problémára. Nem fogsz minden egyes hibát leleplezni, mert nem fogod végigböngészni a kód minden egyes sorát. De az biztos, hogy sokkal jobb, mint semmit sem tenni, és a konvenciód garantálni fogja, hogy a rossz kód legalább rossznak tűnjön. Bónuszként megkapod azt a tulajdonságot, hogy minden egyes alkalommal, amikor egy programozó szeme átfut afölött a sor felett, azt a típusú hibát így ellenőrzi. Egy általános szabályEnnek a fajta módszernek a lényege megköveteli, hogy az egymáshoz tartozó dolgok valahol egymás közelében is legyenek a monitorodon. Bármikor, amikor látok egy szöveget, ahhoz, hogy tudjam, hogy a kód helyes-e, tudnom kell mindenhol, ahol előfordul, hogy biztonságos-e, vagy pedig veszélyes. Nem szeretném, ha ez az információ valahol máshol lenne, egy másik állományban, vagy csak a kódnak egy távoli zugában, ahova le kell görgetnem a szerkesztőben. Képesnek kell lennem rá, hogy ott lássam, ahol van, és ehhez kell egy változó elnevezési konvenció. Egy halom más példa van, ahol javíthatod a kódot, ha a dolgokat közelebb helyezed egymáshoz. A legtöbb konvenció tartalmaz ezekhez hasonló szabályokat:
Ezekben a felsorolt példákban az a közös, hogy megpróbálnak gondoskodni róla, hogy az együvé tartozó kódsorok fizikailag is közel legyenek egymáshoz. Ez elősegíti, hogy a szemgolyóidnak legyen esélyük leleplezni minden disznóságot. Általában be kell vallanom, hogy tartok az olyan nyelvektől, amelyek eltakarnak dolgokat. Amikor egy ilyen kódot látsz:
C-ben, tudod legalább, hogy j be lesz szorozva öttel, és az eredményt i-ben fogja tárolni. De ha ugyanezt látod C++ban, akkor semmit se tudsz. Tényleg semmit. Az egyetlen esélyed, hogy rájöjj, mi történik, ha megnézed, milyen típusú i és j, ami ugye valahol máshol is lehet deklarálva. Ez az, ami miatt j lehet egy olyan típus, aminek van egy * operátora felülírva az eredetit, és ami művel valami elviselhetetlenül szellemeset, amikor megpróbálod megszorozni valamivel. És i lehet olyan típus is, aminek meg az = operátora van felülírva, ami ráadásul lehet, hogy nem kompatibilis az eredménnyel, ami miatt egy érdekes automatikus konverzió kerül meghívásra. Az egyetlen út ebben az esetben, hogy ellenőrzöd a két változó típusát, amihez meg kell találnod a kódot, amiben implementálták a típusokat. Aztán Isten mentsen meg tőle, hogy öröklődést is használjanak, mert akkor még végig is mehetsz az egész osztály-hierarchián találgatva, hogy hol is van a kód. Ráadásul ha a dolog még polimorfizmussal is meg van spékelve, akkor vagy igazán bajban, mert nem csak azt kell kinyomoznod, hogy i és j milyen típusúnak van deklarálva, hanem azt is tudnod kell, hogy akkor éppen milyen típusúak, aminek az lesz az eredménye, hogy egy irtózatosan nagy halom kódot kell végigguberálnod, és közben soha nem lehetsz biztos benne, hogy mindenhol megnézted, köszönhetően a bonyolultságnak (fúúú!). Amikor i=j*5 utasítást látsz C++ban akkor igazán magadra vagy utalva, ami nagyon lecsökkenti az esélyét annak, hogy könnyen észrevedd a problámákat pusztán a kód nézésével. Persze senki nem beszél ezekről a gondokról. Amikor jó iskolásként felüldeklarálod a * operator-t, az nagy segítség neked, hogy létrehozz egy szép, zárt absztrakciót. Amikor j Unicode String típusú, beszorozni egy ilyet egy egésszel nyilvánvalóan hasznos absztrakció, ami hozzásegít a tradícionális kínai szabványos kínaira való konvertálásához, nemde? A gond csak annyi, hogy zárt absztrakciók nem léteznek. Elég részletesen kifejtettem már ezt a Szivárgó absztrakciók törvényében, szóval nem fogom ismételni magamat. Scott Meyera egy egész karriert épített arra, hogy megmutassa, hogyan árulnak el ezek az eszközök, legalábbis C++ban. (Mellesleg Scott könyvének harmadik kiadása Effective C++ épp most jött ki; teljesen újraírta; szerezz egy példányt még ma!) Oké. Elveszettem a fonalat. Inkább összefoglalom mi történt eddig:
Magyar vagyok.
– START DRAFT –A Magyar Jelölésmódot Charles Simonyi vezette be a Microsoftnál. Simonyi egyik legnagyobb Microsoftos projektje a Word volt. Igazából azt a projektet vezette, aminek a célkitűzése az volt, hogy létrehozza az első WYSIWYG szövegszerkesztőjét, valami olyat, amit Bravonak hívtak a Xeroxnál. Egy WYSIWYG szerkesztőnél görgethető ablakaid vannak, tehát minden egyes koordinátát úgy is értelmezhetsz, mintha az ablakhoz lenne viszonyítva, és úgy is, mintha az oldalhoz. Ez persze egy nagy és lényeges különbség, aminek a világos elkülönítése fontos feladat. Van egy olyan sejtésem, ez volt az egyik oka, hogy Simonyi elkezdett használni egy módszert, ami később a Magyar Jelölésmód nevet kapta. Úgy épült fel, mint a magyar kifejezések, és mivel Simonyi innen származott, hát ezt a nevet kapta. Simonyi verziójában minden egyes változónak volt egy előtagja, ami arra utalt, milyen fajta adatot tárol a változó.
Azt a szót használtam, hogy fajta annak ellenére, hogy Simonyi eredetileg hibásan típust használt a leírásában, és programozók generációi értették emiatt félre, hogy mit akart mondani. Ha figyelmesen elolvasod Simonyi munkáját, akkor láthatod, hogy amit javasolt, az egy ugyanolyan elnevezési konvenció volt, mint amit feljebb én is bevezettem. Amikor eldöntöttük, hogy us jelentése „veszélyes (unsafe) szöveg”, és s azt jelenti, hogy „biztonságos (safe) szöveg”. Természetesen mindkettőnek string a típusa. A fordító nem tud neked segíteni, hogy megkülönböztesd őket, és az Intellisense sem ismeri fel a különbséget. Szemantikailag azonban különböznek: máskép kell értelmezni és kezelni őket, és konvertálásra van szükség, ha egyiket értékül adod a másiknak, mert ha nem, akkor futási időben kapsz majd hibát. Ha szerencsés vagy. Simonyi eredeti koncepcióját a Magyar Jelölésmódra a Microsofton belül „Apps Hungarian”-nek nevezték el, mivel az alkalmazásokat készítő osztály használta, azaz a Word és az Excel fejlesztői. Az Excel forrásában egy csomó rw és col prefixet találhatsz, és amikor látod, tudhatod, hogy oszlopokról és sorokról van szó. Na ja, mind egész számok persze, de semmi értelme értékül adni az egyik fajta változó értékét egy másik fajtájúnak. A Word forrásában egy csomó xl és xw prefix van, ahol xl jelentése „megjelenéshez (layout) viszonyított vízszintes koordináta”, az xw viszont „ablakhoz viszonyított vízszintes koordináta”. Mindkettő int, mégsem keverjük össze. Mindkét alkalmazásban találsz sok cb-t, ami a „bájtok számára” (count of bytes) utal. Persze, ez is egy egész szám, de mennyivel többet tudsz, ha egy ilyen változónévre nézel rá. Ez egy bájt számláló: egy puffer méret. És ha azt látod: xl = cb, eljárhatod a Rossz Kód Táncot, mivel ez biztosan egy hibás kódrészlet, mert bár xl és cb is egész szám, tökéletesen hülye ötlet egy vízszintes offszetnek egy bájt számláló értékét adni. Az Apps Hungarian-ben az előtéteket függvényekre és változókra is bevezették. Hogy az igazat megvalljam, soha nem láttam személyesen a Word forráskódját, de egy kupac pénzbe mernék fogadni, hogy van benne egy függvény, amit YlFromYw-nek hívnak, ami az ablakhoz viszonyított függőleges koordinátákat konvertálja a megjelenítéshez szükséges függőleges koordinátákká. Az Apps Hungarian a ÚjTípusFromRégiTípus jelölésmódot használja a tradicionálisabb RégiTípusToÚjTípus helyett, így aztán minden függvénynév kezdődhet a megfelelő előtaggal pont úgy, ahogy a példában, ahol átneveztem az Encode-ot SFromUs-re. Igazándiból Apps Hungarian-nek megfelelő kódban az Encode függvényt muszáj átnevezni SFromUs-re. Az Apps Hungarian nem ad esélyt, hogy eldönthesd, milyen nevet adsz ennek a függvénynek. És ez így jól is van, hisz eggyel kevesebb dolgot kell fejben tartanod, és nem kell azon gondolkoznod, hogy vajon milyen kódolás kerül meghívásra, amikor az Encode-ot látod: ennél pontosabb a leírásod. Az Apps Hungarian hihetetlenül értékes volt, főleg azokban a régi napokban, amikor a C fordító nem nyújtott túl nagy segítséget a típusok használatához. De aztán valami rossz történt. A sötét oldal rávetette árnyékát a Magyar Jelölésmódra. Senki sem tudja már hogy, de úgy alakult, hogy a Windows csapat dokumentáció készítői figyelmetlenségből bevezettek valamit, amire azóta „Systems Hungarian”-ként hivatkozunk. Valaki valahol, aki olvasta Simonyi dokumentációját, ahol ő a „típus” szót használta, azt gondolta, hogy ő valóban a típusra is gondolt, ahogy az osztályban, a típus rendszerben, vagy a fordító típusellenőrzésénél értjük. Pedig ő nem így értette. Nem, ő nagyon gondosan elmagyarázta, hogy mit ért „típus” alatt, de ez nem segített. A baleset megtörtént. Az Apps Hungarian-nek nagyon hasznos jelentéssel bíró előtagjai voltak, mint pl. az „ix”, ami egy tömbindexre, a „c”, ami egy számlálóra, vagy a „d”, ami két szám különbségére utalt (például „dx” jelentése „szélesség”), és így tovább. A Systems Hungarian-nek messze nem voltak ilyen értelmesek az előtagjai. Például „l”, mint long, vagy „ul”, mint „unsigned long”, és „dw”, mint double word, ami ugye egy unsigned long. A Systems Hungarian-ben az egyetlen dolog, amit meg tudtál egy ilyen prefixből, az a változó adattípusa volt. Ez apróságnak tűnik, de igazándiból tökéletes félreértése Simonyi céljának és módszereinek, ami csak azt mutatja, hogy ha nyakatekert akadémikus prózában fogalmazol meg valamit, akkor senki se fogja megérteni az ötleteidet, amelyek így félremagyarázva nevetségessé tesznek, mégha nincs is sok közük az eredeti ötletedhez. Így a Systems Hungarian-ben kaptál egy csomó dwFoo-t, ami „double word foo”-t jelentett, és a francba, ez nem szolgált túl sok információval az olvasójának. Szóval nem nagy csoda, hogy az emberek fellázadtak a Systems Hungarian ellen. Systems Hungarian-t közel s távol hirdették. Ez a szabvány a teljes Windows programozási dokumentációban. Mindenkivel megismertették az olyan könyvek, mint a Charles Petzold Programming Windows című munkája, a Windows programozók Bibliája, és gyorsan a Magyar Jelölésmód alapértelmezett formájává vált, még a Microsofton belül is. Csak kevesen értették meg az Excel és Word csapaton kívül, hogy mekkora hibát követtek el. Aztán jött a nagy ribillió. Elsőként persze azok a programozók tiltakoztak, akik soha nem értették a Magyar Jelölésmódot, csak annak félremagyarázott fajtáját, és felkeltek annak „szinte haszontalansága” ellen. Tulajdonképpen még a Systems Hungarian-nek is van néhány olyan tulajdonsága, ami segít kiszűrni a hibákat. Ugye ha használod, akkor minimum tudni fogod egy változóról a típusát, akárhol is van a kódban. De ez közel sem olyan hasznos, mint az Apps Hungarian. A Nagy Lázadás akkor érte el a csúcsát, amikor a .NET első verziója megjelent, és végül a Microsoft elkezdte azt mondani az embereknek, hogy, „a Magyar Jelölésmód nem ajánlott”. Volt is nagy öröm. Nem hinném, hogy sokat gondolkoztak a miérten. Egyszerűen végigmentek a dokumentum elnevezésekkel kapcsolatos részén, és minden bekezdésbe beleírták: „Ne használd a Magyar Jelölésmódot”. A Magyar Jelölésmód hírneve addigra már annyira meg volt tépázva, hogy senki nem tiltakozott ez ellen, és az Excel és Word fejlesztőkön kívül mindenki fellélegzett, hogy nem kell a továbbiakban egy nehézkes elnevezési konvenciót alkalmaznia, ami amúgy is felesleges már az erős típusellenőrzések és az Intellisense korában. De még mindig félelmetesen sok értéke van az Apps Hungariannak, amelyek megkönnyítik az eligazodást a kódban és amitől az olvashatóbb, fejleszthetőbb, könnyebben karbantartható és gyorsabb hibakeresést tesz lehetővé. De ami a legfontosabb, a rossz kódot segít rossznak látni. Mielőtt továbbhaladnánk, ígéretemhez híven megint bántom egy kicsit a kivételkezelést. Utoljára mikor ezt tettem, elég sok bajt okoztam magamnak. Egy rögtönzött megjegyzésben a Joel on Software oldalán, azt írtam, hogy nem igazán szeretem a kivételeket, mert tulajdonképpen láthatatlan goto utasítások, ami – érveltem – rosszabb, mint egy látható goto utasítás. Nyilván azonnal milliók ugrottak a torkomnak. Az egyetlen ember, aki a védelmemre kelt, természetesen Raymond Chen volt, a föld legjobb programozója, ami azért mégiscsak jelent valamit, nem? Nézzük ezt a dolgot a kivételekkel, ennek a cikknek a kontextusában. A szemed megtanulja észrevenni a rossz dolgokat, és ez segít elkerülni a hibákat. A kód igazán robusztussá válhat, ha rendelkezésedre állnak elnevezési konvenciók. Másképp fogalmazva, minél több információt láthatsz arról, hogy mit csinál a kód annak a puszta nézésével, annál könnyebb dolgod lesz a hibák keresésénél. Amikor van egy kódod, ami azt mondja
a szemeid szerint van valami baj? Mindig meghívódik a cleanup(). De annak a lehetősége, hogy dosomething kivált egy kivételt, azt jelenti, hogy a cleanupesetleg nem hívódik meg. Ez persze könnyen javítható finally használatával, vagy anélkül, de nem is erről akarok beszélni, hanem arról, hogy az egyetlen módja, hogy megtudd, a cleanup mindenképpen meghívódik, az, ha a dosomething egész hívási fáját végignézed, ellenőrizve hogy van-e ott valami, bármi, ami kiválthat egy kivételt. Ez így talán nem is lenne baj, mert vannak eszközök ennek a munkának a megkönnyítésére. A baj, hogy a kivételek lehetetlenné teszik a gond helyi vizsgálatát. Muszáj valahol máshol keresgélned, ha rá akarsz jönni, a kód a megfelelő dolgot csinálja-e, kihasználatlanul hagyva a szemednek azt a képességét, hogy kiszúrhatja a rossz dolgokat, mert egyszerűen nincs mit kiszúrni. Persze, amikor írok egy csinos kis szkriptet arra, hogy összeszedjen és kiírjon egy csomó adatot naponta egyszer, akkor persze hasznosak a kivételek. Mi sem kellemesebb, mint elhanyagolva a részleteket belegyömöszölni az egész programot egy méretes try/catch blokkba, ami küldd nekem egy emailt, ha valami váratlan történik. A kivételek jók a gyors-és-mocskos kódoláshoz, szkriptekhez, és olyan kódhoz, ami nem életfontosságú. De amikor operációs rendszert, atomerőmű vezérlést, vagy szívműtétnél használt körfűrészt programozol, akkor a kivételek borzasztóan veszélyesek. Tudom, lesznek, akik azt fogják gondolni, milyen láma programozó vagyok, aki képtelen felfogni a kivételkezelést mélységeit, és meglátni azokat a tulajdonságait, amelyek az életemet tökéletesebbé tehetnék, ha közelebb engedném őket a szívemhez, de sebaj. A mód, hogy igazán megbízható kódot írjunk az, hogy egyszerű eszközöket használunk, amelyek segítenek elkerülni az emberi tévedéseket, és nem az, ha olyan csalhatatlan programozóknak készített bonyolult csodafegyverekhez nyúlunk, amelyeknek rejtett belső tulajdonságokkal és szivárgó absztrakcióval rendelkeznek. További olvasmányokHa még mindig azt gondolod, hogy minden rendben van a kivételkezeléssel, akkor olvasd el Raymond Chen írását Tisztább, elegánsabb, és nehezebb felismerni. „Olyan irtózatosan nehéz megkülönböztetni a kivételkezelést jól és rosszul használó kódot… a kivételek túl bonyolultak, és én nem vagyok elég okos, hogy használjam őket.” Raymond kirohanását a Makrók Általi Halálról Gondolatok a folyamatokat kezelő Makrókról, ami szintén egy olyan esetet mutat be, amikor az információk elszórtsága miatt a kód karbantartása ellehetetlenedik. „Ha olyan kódot látsz, ami használja [a makrókat], le kell fúrnod a fejléc állományokig, hogy rájöjj, mi történik.” A Magyar Jelölésmód történetének megismeréséhez kezdj Simonyi eredeti írásával, A Magyar Jelölésmód-dal. Doug Klunder, aki bevezette az Excel csapatban egy kicsit világosabb stílusban ismertette. További Magyar Jelölésmóddal kapcsolatos történetekért, és hogy megtudd, hogy tették tönkre a dokumentáció készítők, olvasd el Larry Osterman véleményét, főleg Scott Ludwig megjegyzését, vagy Rick Schaut véleményét. | ||