Tím, že volající musí vědět co se uvnitř děje tak efektivně padá veškerá abstrakce.
...
Díky těm zřetězeným výjimkám musí každá úroveň programu do které ty výjimky můžou probublat vědět, co přesně se děje níž. Pokud to neví, tak vlastně nemá cenu ty výjimky ani házet.
To přece není pravda. To je jen tvrzení, které funguje na principu ode zdi ke zdi. Buď mám absolutní abstrakci a nemohu použít výjimky (a to si úplně nejsem jist pravdivostí tohoto tvrzení), nebo se musím vzdát abstrakce úplně. Nic mezi tím nevidíte.
Definice výčtu výjimek patří k definici rozhraní - malá poznámka pod čarou: jako rozhraní si můžete představit plně abstraktní třídu, nebo interface v javě. Každé rozhraní by mělo mít tzv. referenční implementaci, která ukazuje, jak se co má implementovat a mělo by 100% dodržovat pravidla rozhraní. Referenční implementace samozřejmě bude házet jen výjimky z výčtu, žádné jiné. To je ta abstrakce.
Bohužel nebo bohudík, rozhraní vznikají proto, aby skryly implementační detaily, nicméně to stejně nejde, protože už v implementaci nějakého rozhraní můžeme najít výrazné odlišnosti, úlevy a zkratky. Například rozhraní IPes má metodu VrtětOcasem(), tato metoda bude u objektu Buldok prázdná (buldok praktický nemá ocas). A to je ten lepší případ (čekali byste ze metoda IStream::closeOutput způsobí odeslání HTTP requestu pokud je tam HttpStream? No ale logiku to má, i když u TCPStreamu se spíš používá k uzavření spojení - příklad z knihovny LightSpeed).
To samé je to s výjimkami. Každý objekt by měl dodržovat rozhraní i na úrovni výjimek. Ale implementace se může začít potýkat s problémem, který na rozhraní definovaný není. Strojí před problémem. Má to vyhodit jako výjimku, která není na rozhraní definovaná? Nebo to má zabalit do jiné výjimky z nějaké existující, ke které to připojí Reason?
Opět příklad. HttpStream může vyhodit HttpStatusException. Ta ale na rozhraní IStream není definovaná. Tam je definovaná výjimka IOException. (zadání)
Má se tato výjimka vyhazovat jako IOException a jako reason vložit HttpStatusException?
Opět záleží, jak předpokládáte, že se to bude používat. Předpokládám tuto hierarchii
+ - (1) otevírám HttpStream, chci si něco stáhnout
+ - (2) čtu soubor přes IStream (třeba to je parser JSONu, který pracuje nad obecným streamem)
+ - (3) při čtení obdržím status 500 Internal Server Error
Co chci? Chci na úrovni (2) odchytit IOException? Co s tím na té urovni budu dělat? Pokud je tam JSON parser, tak asi nic, ten to hodí dál. Může to také vyřešit tak, že z toho vybalí reason a ten hodí. Jenže JSON parser nemůže vědět, zda nad ním náhodou není někdo, komu by se třeba hodilo, aby to bylo IOException
Takže asi budu chtít na úrovni (1) odchytávat HttpStatusException.
V tomto případě bych asi pro HttpStream výjimku nebalil a i když není na úrovni rozhraní IStream definovaná. Nicméně mohu předpokládá, že ten, kdo si objednal čtení přes HTTP protokol, bude nejspíš vědět, jak s výjimkou HttpStatusException naložít, spíš než s chybou IOException.
Jak já to dělám? HttpStatusException dědí IOException. Ne vždy to ale takhle jde řešit.