Výjimka vs assert

D

Re:výjimka vs assert
« Odpověď #15 kdy: 25. 01. 2015, 01:03:55 »
@zboj -- pardon ... zajímal by mne váš názor na výjimky v C++  -- ta nemožnost opravit příspěvek je otravná!


Re:výjimka vs assert
« Odpověď #16 kdy: 25. 01. 2015, 13:26:47 »
Výjimky jsou v C++ dobré v situaci, kdy máte dobře navrženou aplikaci, rozdělené akce atp. Dokážete tak zajistit smysluplnou recovery i z věcí, o kterých ani netušíte, že mohou nastat. Nicméně mají i řadu nevýhod, z toho největší jest asi ztráta kontextu, co se vlastně rozbilo (aby se to mohlo opravit) a boj s realitou, že v C++ existují pravděpodobně až miliardy řádek různých knihoven, které použití výjimek moc nenapomáhají a člověk dojde k názoru, že mu výjimky jen komplikují vlastní řešení (které je co do rozsahu významně menší než API, které používá).

Assert zase funguje jen v debug konfiguraci a jak mnozí uvádějí, jde o kontrakt, že daná situace nemá (nesmí) nastat. Osobně jej rozšiřuji i na situace druhu invalid_argument, ale souhlasím s tím, že takový argument nesmí pocházet od uživatele. Assert, na rozdíl od výjimky, jasně sděluje, že situace nastat nesmí a je třeba ji řešit, a navíc poskytuje vývojáři kompletní dump včetně stacku a lokálních proměnných, takže je nesrovnatelně snazší opravit assert než výjimku std::out_of_range.

Zjednodušeně, asserty dávám tam, kam nechci, aby se kód nikdy dostal, výjimky tam, kde doufám v recovery. A často kombinuji obojí, tedy dám assert před výjimku. Ale diskuse, kdy házet výjimku a kdy vrátit chybu pomocí return value, to je asi na delší povídání.

mc.

Re:výjimka vs assert
« Odpověď #17 kdy: 25. 01. 2015, 14:22:35 »
@zboj Třeba Google v určitých aplikací prý výjimky zakazuje (myslím že to je nějaké style-guide pro chrome?). Zajímalo by máte názor  na výjimky v C++, ve světle C++11/14. Díky

C++ není úplně stavěné na programování bez výjimek. Největší problém je v tom, že z konstruktoru, kopírovacího konstruktoru a nebo z operátoru přiřazení nemůžete vrátit nějaký návratový kód, podle kterého se dá poznat úspěch/chybový kód. Samozřejmě toto se dá obejít - nepoužíváním kopírovacích konstruktorů atp., pokud potřebujete při kopírování provést operaci, která může selhat (alokaci paměti) - ale to je fakt otrava.

Google C++ coding style výjimky zakazuje, zjednodušeně, proto, protože:

- vypnuté výjimky prodlužují kompilaci a zvětšují paměťové nároky
- výjimky dělají kód trochu méně čitelný, protože čtenář musí myslet na "schované" control-flow cesty z bloku způsobené možností vyhození výjimky

http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Exceptions

D

Re:výjimka vs assert
« Odpověď #18 kdy: 25. 01. 2015, 18:03:18 »
Díky za opovědi.

JSH

Re:výjimka vs assert
« Odpověď #19 kdy: 26. 01. 2015, 09:03:40 »
Google C++ coding style výjimky zakazuje, zjednodušeně, proto, protože:

- vypnuté výjimky prodlužují kompilaci a zvětšují paměťové nároky
- výjimky dělají kód trochu méně čitelný, protože čtenář musí myslet na "schované" control-flow cesty z bloku způsobené možností vyhození výjimky

http://google-styleguide.googlecode.com/svn/trunk/cppguide.html#Exceptions
Řekl bych, že jeden hodně důležitý (možná ten rozhodující) důvod vytáhli až v tom rozhodnutí. Mají kopec kódu, který s výjimkami nepočítá, a museli by ho kompletně překopat.


Petr M

Re:Výjimka vs assert
« Odpověď #20 kdy: 05. 02. 2015, 14:29:03 »
Výjimka je na řešení cyb v hodnotách, asset na hledání chyb v kódu.

Pokud mám kus kódu, který požaduje existující adresář, napíšu, co má dělat. Pak řeším, že není platná cesta, nebo že adresář neexistuje. Buďto dám na začátek test s return DIR_NOT_EXIST, nebo výjimku. Je to vstup zvenčí, kde může být hodnota, která se liší od toho, s čím můžu pracovat - výjímečná situace, která by správně neměla nastat. A může nastat v závislosti na použití, takže musí být i v release. Můžu to chytnout, hodit chybovou hlášku nbebo ten adresář bytvořit a prubnout to znovu,...

Oproti tomu aserce hlídá, že kód dělá to, co má. Pokud napíšu funkci pro odmocninu, tak z definice je jasný, že na výstupu bude kladný číslo menší než argument. To dám do assertu. V produkční verzi by to jenom zabíralo místo a brzdilo, ale během ladění mě to může praštit, že co počítám není odmocnina, ale nesmysl. A samozřejmě si musím hlídat i vstup, pokud jsem na reálné množině, tak musí být >=0. Tam je to na výjimku u knihovní funkce (volání odkudkoliv kdykoliv), ale pokud je to soukromá metoda, můžu tam dát assert a dostanu kopanec "pozor, rveš tam něco, co tam nepatří". A vím, že se na to mám zaměřit a fixnout to, než začne řvát zákanzík...

Mimo to existuje i compile time asserce, která nedovolí zkompilovat kód, pokud je v něm měco blbě (třeba se liší velikost pole od počtu hodnot v enumu, který je indexuje,...). V nejjednoduší formě
Kód: [Vybrat]
#ifndef KONSTANTA
#error KONSTANTA nedefinována
#endif

A vůbec nejhloupější řešení chyby je to, že programátor řeší blbý hodnoty na vstupu stylem "hodnota neodpovídá, padělám ji". To se pak chyba prakticky nedá najít.

Kit

Re:Výjimka vs assert
« Odpověď #21 kdy: 05. 02. 2015, 15:02:22 »
Pokud napíšu funkci pro odmocninu, tak z definice je jasný, že na výstupu bude kladný číslo menší než argument. To dám do assertu. V produkční verzi by to jenom zabíralo místo a brzdilo, ale během ladění mě to může praštit, že co počítám není odmocnina, ale nesmysl.

Je dobré si uvědomit, že jsi napsal nesmysl. Odmocnina může být i větší než argument.

PsychoIT

Re:Výjimka vs assert
« Odpověď #22 kdy: 05. 02. 2015, 18:44:25 »
Když jste tak tady všichni tak chytří, tak mi poraďte jak byste nejlépe řešili následující situaci v Javě:

Definujete v jednom balíku interface, které někdo bude implementovat, třeba com.company.interfaces.DataReader který v konkrétní implementaci bude číst data buď z databáze, nebo XML nebo třeba z CSV, bude mít nějakou metodu na čtení, třeba String readData() throws Exception, a otázkou je, jestli je dobré aby každá metoda nějakého rozhraní u nějž dopředu nebudu vědět konkrétní implementaci měla možnost házet výjimku, což je nutné pokud chceme dát implementátorovi možnost nějakou vyvolat, navíc Exception není moc obecná a bude ji nutné zkoumat přes reflexi.

Jak to nejlépe řešit?

Jednou z možností je že rozhraní nikdy nemůže vyhodit výjimku a v případě že nějaká nastane tak ji implementátor přepošle nahoru jako RuntimException.

Nejlepší řešení asi by bylo že každá třída rozhraní by měla umožnit zaregistrovat vlastní exception handler a jinak její metody nevyhazují nikdy žádnou výjimku, implementátor pak může všechny svoje výjimky odchytit a předat do případného handleru.

Jaký je váš názor na výjimky a rozhraní v Javě?

Re:Výjimka vs assert
« Odpověď #23 kdy: 05. 02. 2015, 18:55:56 »
throws DataReaderException

JSH

Re:Výjimka vs assert
« Odpověď #24 kdy: 05. 02. 2015, 20:21:58 »
Jak to nejlépe řešit?
Záleží na tom, co všechno může ten volající předpokládat. Pokud o vnitřku neví nic, tak ho stejně zajímá jen vyletěla/nevyletěla, protože může maximálně tak vypsat zprávu a možná to zkusit znova (což pravděpodobně zdechne zase).
Rozumné řešení je IMO poslat ji dál a doufat, že někde výš je něco, co ví, jaká implementace je použitá, a dokáže to chytit a zpracovat. Nebo musí být součástí rozhraní i trochu lepší specifikace toho, co může lítat ven.
Citace
Nejlepší řešení asi by bylo že každá třída rozhraní by měla umožnit zaregistrovat vlastní exception handler a jinak její metody nevyhazují nikdy žádnou výjimku, implementátor pak může všechny svoje výjimky odchytit a předat do případného handleru.
Aneb proč se střelit do nohy, když můžu do hlavy? Jaký je rozdíl v tom, jestli vyletí neznámá výjimka, nebo se mi zavolá handler se stejně neznámým parametrem?
Akorát musím navíc z toho handleru předat informaci ven, aby se ta volající funkce dověděla o to, že něco selhalo. Ještě by se ten handler mohl volat z nějakého pracovního vlákna, aby byla obzvlášť sranda. :)

aaa

Re:Výjimka vs assert
« Odpověď #25 kdy: 05. 02. 2015, 21:04:05 »
Nepisane vynimky (RuntimeException, Throwable) slusny programator sam nehadze*, lebo nevie, ako to kto osetri.

Hadze sa vynimka na urovni modulu - proste throws DataReaderException. A ked sa nieco nepodari, tak sa hodi ona - nikoho vyssie nemaju co zaujimat detaily. Ked nahodou maju, tak DataReaderException moze implementovat metody napr. getErrorLine() alebo getErrorCol(). Pripadny dovod vynimky odporucam dat do cause, takze ho vrati getCause().

Pouzivat introspection je vacsinou zle.

*moze hodit v pripade, ze je to natolko vazna chyba, ze by mal tento modul sposobit ukoncenie programu. To ale v 99,9% nie je