Próbálok sorban:
Checked Exception.
nehéz refaktorálni
Ha rosszul volt tervezve (vagyis simán áteresztette magán a belső checked exception-öket, vagyis implementációs részeket leakelt), akkor valóban. Ha viszont saját Exception osztályt használt burkolt belső kivételekkel, akkor (leszámítva az esetet, hogy tudod garantálni a hibamentességet és meg lehet szüntetni az Exception-t :) ) nagyjából ugyanannyi refaktorálni, mintha runtime exception-öket dobáltál volna vagy az exception-t visszaadtad volna.
inkonzisztens állapotot hagyhat maga után és Többszörös érték visszaadás.
nem hagy inkonzisztens állapotot maga után
(Egyébként ha immutable objektumok felett pure function-öket használsz, ez kb. tárgytalan)
Mennyiben segíti a többszörös érték visszaadás az inkonzisztens értékek visszaadását. Ha egy metódus törzsében "középen" kapsz egy hibát, a többszörös érték visszaadás rákényszerít-e, hogy visszatérj egy konzisztens állapotba? Valóban, ugyanígy egy checked exception sem kényszeríti ki a konzisztenciát, viszont (ha csak nem nyeli le a kód az Exception-t), legalább garantáltan propagálódik az értesítés, hogy nem feltétlenül konzisztens.
nehéz kombinálni más dolgokkal (compose)
?
Jó esetben a más dolgoknak is van egy saját kivétele a signiture-ben, egy laza mozdulattal beágyazod a külső kivételbe, és jónapot.
Többszörös érték visszaadás.
könnyebben olvasható a kód
Szerintem nem. Egy kivételnél szépen látod, hogy meddig tart a try blokk, tudod, hogy azon a szakaszon fordulhat elő valami hiba - aminek a kezelése elkülönül a fő ágtól. Linkeltétek a "használjunk wrapper függvényt, ami feljegyzi, hogy volt-e már hiba és ha igen, menjen át noop-ba" megoldást: azon a kódon nagyon szépen látszik, hogy - pont, mint C-ben, jobb eszköz híján - a hibakezelés bekerült a fő ágba.
Ráadásul a példa meglehetősen egyszerűsített, mivel egy homogén művelet hibáit veszi csak figyelembe. Ugyanez mondjuk annál, hogy beszúrsz egy rekordot a DB-be, és küldesz egy értesítő e-mailt már lényegeseb bonyolultabb lesz (és függetlenül attól, hogy hogyan szervezed a kódod, elrejtheted akár 15 hívás mélységben is):
ha a rekord beszúrásánál hiba volt, akkor tranzakció vissza, nem küldünk levelet.
ha a levél kiküldésénél hiba volt, akkor adatbázis tranzakció vissza.
ha nem volt hiba, örülünk.
Ez ugye Exception-ökkel
try {
db.beginTransaction();
db.insert(foo);
mail.send(bar);
db.commit();
} catch (MailException x) {
db.rollback();
} catch (DBException x) {
}
A fő ágad és a hibakezelésed szépen elkülönül. Ha nincs kivételkezelésed (pszeudó-kód, mert nem ismerem a go-t)
db.beginTransaction()
err_db = db.insert(foo)
if err_db != nil
err_mail = mail.send(bar)
if err_mail != nil
err_db.rollback()
else
db.commmit()
endif
endif
A kód komplexitása ugyanaz maradt (4 lehetséges út van), viszont az utóbbinál kénytelen vagy mind a négy utat expliciten megjeleníteni a fő ágadban. Ami a tranzakción belül műveletek számával szépen (talán) exponenciálisan fog nőni (tegyük bele a kötelező naplózást egy audit naplóba, ami ha nem sikerül, vissza kell vonni a tranzakciót - a mail mondjuk itt már keresztbe tesz, mert annak van egy visszavonhatatlan mellékhatása; vagyis azt kell mindig utoljára hagyni), ez újabb elágazást fog jelenteni. Exception-nel ez egy újabb audit.log('foo') hívás, és egy újabb catch block. A komplexitás ott is ugyanaz, _kód szinten_ mégse nő az elágazások száma.
könnyű refaktorálni
Mennyivel könnyebb, mint a check exception-nél? A method signature-t mindenképp módosítanod kell, az meg nagyjából lényegtelen, hogy a visszatérési érték változik, vagy a dobott kivételek listája.
BlackY
--
"en is amikor bejovok dolgozni, nem egy pc-t [..] kapcsolok be, hanem a mainframe-et..." (sj)