Kb. két hete felrakták a forráskódokat tartalmazó szerverre a Vista forráskódját is (az MVP-séghez lehet kérni a hozzáférést, én éltem vele, használom is rendszeresen). Pont jól jött, mert az ActiveX Installer Service nem hallgat rám, pedig a munkámhoz ezt be kell konfigurálni majd az ügyfeleknek.
Debugolni lenne a legegyszerűbb ilyenkor, de egyelőre még nincs Vista kompatibilis kártyaolvasó driver, így marad az XP alóli kódböngészés (nyilván marha nagy secu van, nem csak jelszó alapú a hozzáférés).
Természetesen a kódokról nem beszélhetek direktben, főleg nem pasztázhatok be ide a blogba belőlük, de egy apróságot megosztok veletek, tetszett.
A Debugging Windows Applications könyv óta nagy szerelmese vagyok az Asserteknek. Az az igazság, míg nem olvastam a könyvet nem értettem, mire is való az assert? Azért nem értettem, mert ha úgyis van pl. egy függvényben paraméter ellenőrzés, ami exceptiont dob, vagy E_INVALIDARG-ot ad vissza, ha nem stimmel valami, akkor minek duplikálni az ellenőrzést még ASSERT-ekkel is? Nos, azért, mert az assert kiváltódása esetén egy gombnyomásra elindul a debugger, és benn vagyok a hibás részben, abban a kódrészletben, ahol nem teljesül az általam elvárt feltétel (invariáns, a tudományos neve? :). Mésként lehet, hogy csak 5 szinttel feljebb derülne fény a hibára, amikor már nem ismertek a mélyebben hibázó metódus lokális változó értékei, hisz a verem lebomlott. Tképpen az assertekkel a követelmények egy részét kódolja az ember a kódba, és egyúttal önvédelmet épít be a saját hibái ellen.
No, vissza a forráskódhoz. Az ieinstal.exe forrását nézegetem, hátha rájövök, miért nem úgy működik, ahogy szeretném. A forrás C++-ban íródott, nem C-ben. (Az oprendszer vegyesen asm, C és C++ kódokból épül fel.)
COM alapú, ezért tele van HRESULT kezeléssel. Ugye ez a hagyományos, status kód alapú hibakezelés, ami, ha csak if-elseket használunk nagyon mélyen betolt kódblokkokkat eredményezne. Ezt megelőzendő vagy exceptionkezelést használunk, vagy gotokat. Az első megoldás C++-ban nem annyira elterjedt, inkább managed és script környezetben használják elterjedtebben (de lehet, hogy csak nem értek hozzá). C++ kódokban gyakoribb a goto használata. if (FAILED(hr)) goto ErrorExit. Így sík lesz a kód, nem agyonindentált.
Az tárgyalt forráskódban szinte minden metódusban van két kijárat, egy sikeres és egy sikertelen, ahová gotoval ugrik be a szerző. Érdekes a következő. A sikeres kijáratnál vagy egy ilyen sor: ASSERT(SUCCEDED(hr)). A hibás ágnál: ASSERT(FAILED(hr)). Azaz a debug kód ellenőrzni, hogy ha egyszer a sikeres ágra engedtük a kódot, akkor ne adjunk már vissza véletlenül hibára utaló HRESULT-ot, és fordítva.
Apró, de szellemes trükk.
Mellesleg én sokáig legacynek éreztem a statuskód alapú hibakezelést, ez volt a .NET-es tankönyvekben is. Zoxigen annak idején adott egy linket, ahol Raymond barátunk rendberakta a fejemben a kérdést. Kötelező olvasmány. Van utójáték is a témához.
Mióta ezt olvastam mindig írok az if-ek mellé else-t még akkor is, ha abban nem csinálok semmit. Ilyenkor egy commentben odaírom, hogy ebben az ágban nincs teendő, de legalább látom, hogy nem feledkeztem meg róla.
Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.