Výjimka vs assert

D

Výjimka vs assert
« kdy: 24. 01. 2015, 18:07:09 »
Kdy použít jistě aserci a kdy vyhodit výjimku?

Vím, že aserce slouží pro zachycení stavu, který nesmí nikdy nastat. Podle mne však, pokud mám funkci, která dělí dvě čísla předaná parametrem, pak dělení nulou by nemělo nastat... nicméně raději vyhodím výjimku -- protože ta nemůže být vypnuta direktivou kompilátoru a klient ji může zachytit -- je to tak  správné?

Jak sem četl, aserce by měla být aplikována také jen na soukromé a chráněné části kódu a výjimky především na veřejné metody. V mnoha zdrojácích jsem se však s asercí v soukromím kódu nesetkal, většinou je tam také výjimka.

« Poslední změna: 25. 01. 2015, 21:12:26 od Petr Krčmář »


Re:výjimka vs assert
« Odpověď #1 kdy: 24. 01. 2015, 18:20:38 »
Nevim, v jakem jazyce to resis, tak to popisu, jak to je v Jave, ale jinde to bude podobne. A predpokladam, ze nechavame stranou asserce v testech.


Asserce jsou poor man's design by contract. Muzes v nich popsat jake jsou predpoklady danych kusu kodu (tenhle parametr neni nula...) a co se jsou vlastnosti jeho vysledku (vraci se neprazdny seznam...). V Jave jsou udelane tak, ze pokud neni asserce splnena (a asserce jsou povolene), tak vylitne vyjimka. Takze ani s assercemi se vyjimek nezbavis, jen
- mas hezci zapis
- mas urcene, co ti vyleti

Casto se asserce pouzivaji pri vyvoji a testovani, na produkci jsou vypnute (t.j. pokracuje se v krasojizde i kdyz nekdo porusil kontrakt, bozi at nas chrani pred nasledky). Ze to je dobra metoda, to bych si netroufal tvrdit.

V poslednim odstavci mas vicemene pravdu - vstup od cizich mas kontrolovat a v definovanych stavech hazet vhodnou vyjimku (IllegalArgumentException...), asserce by mely "dozajistovat" ze uvnitr tvych kusu kodu je vsechno OK.

Ja uz leta asserci nenapsal, vsechny kontoroly pouzivaji jine vyjimky. Ale protoze neni uplne pekne mit vsude if ... throw, neni od veci misto toho pouzit nejakou knihovnu, ktera dela to same v citelnejsi podobe (assertThatNotNull(variable, "comment"), assertNotEmpty(list, SpecializedExceptionClass)....), cimz ziskas pekny zapis i jistotu, ze na produkci i pri testovani je vse stejne.

Re:výjimka vs assert
« Odpověď #2 kdy: 24. 01. 2015, 18:48:02 »
Assert se používá pro případy, které nikdy nemůžou nastat - a pokud přesto nastanou, jedná se o chybu uvnitř TVÉHO kódu, nikoli cizího, nebo dokonce jen špatným vstupem.

Tedy pokud ta knihovna, která dělí dvě čísla, je použita pouze uvnitř tvého programu a daná funkce není exportována ven, dal bych tam assert. Máš totiž zajistit už předem, aby ten assert nevylítl, a za to jsi zodpovědný pouze ty.

Pokud je ta knihovna nějak veřejná a tedy by ji mohl použít někdo zvenčí, pak rozhodně dej výjimku. Pokud bych zavolal knihovnu a ta by někde uvnitř spadla na assert, myslel bych si, že je špatně napsaná (a hlavně bych nevěděl, co s tím mám udělat). Pokud vylítne výjimka, alespoň s tím něco můžu udělat.

Přiznám se ale, že občas pro ryze soukromé programy (které spouštím jen já) z lenosti používám assert i tam, kde by měla být výjimka (například „otevři soubor“, „assert(soubor je otevřený)“); je to nejrychlejší způsob a stejně při každém běhu programu koukám na výstup já (takže tomu rozumím) a zároveň vím, že nemám asserty vypínat.

D

Re:výjimka vs assert
« Odpověď #3 kdy: 24. 01. 2015, 18:59:06 »
@Ondra Satai Nekola "Nevim, v jakem jazyce to resis (...)" To je dobrá připomínka, moje zmatení souvisí také s rozdíly v jazycích, které jsem načítal  toto téma (C++, Java, Python, Ada). Například Ada má už _pre-conditions_ a _post-condition_ -- tedy DbC.
@Aleš Janda "Pokud je ta knihovna nějak veřejná" Tím myslíte rozhraní knihovny, tedy public třídy a  metody, nebo obecně, pokud jde někam do produkce?
Díky za vaše odpovědi!

Re:výjimka vs assert
« Odpověď #4 kdy: 24. 01. 2015, 19:03:05 »
Assert v Javě označuje předpoklady, které musí být splněné, aby kód fungoval správně. Když nejsou splněné, neznamená to nutně, že kód bude fungovat špatně - proto je kontrola assercí při vývoji zapnutá (aby se odhalila místa, kde se něco používá špatně), ale při provozu zapnuté být nemusí. Výjimka naproti tomu znamená, že tohle určitě nemůže dopadnout dobře.

Třeba píšu funkci, u které vím, že teď ji nikdy nebudu volat s null jako parametrem. V funkci je na to assert a při psaní neřeším případ, že by parametr byl null. Pokud ji ale s null někdo zavolá a má vypnuté asserty, může se stát, že ta funkce proběhne bez chyby. A nebo někde spadne na NullPointerException (v Javě). Pokud ale vím, že by ta funkce s null parametrem fungovala špatně, dám tam if a vyhození NPE.


Re:výjimka vs assert
« Odpověď #5 kdy: 24. 01. 2015, 19:10:21 »
@Aleš Janda "Pokud je ta knihovna nějak veřejná" Tím myslíte rozhraní knihovny, tedy public třídy a  metody, nebo obecně, pokud jde někam do produkce?

Tím myslím rozhraní knihovny. Ale třeba i v rámci jednoho týmu. Pokud může někdo jiný než TY způsobit assert, dej tam výjimku. Ať už to je kolega, který bude volat tvoji funkci knihovny (ale ta knihovna jinak veřejná nebude), anebo se tam ta čísla dostanou nějak ze vstupu, patří tam výjimka. Assert je pro místa, která můžeš způsobit jen ty, a používá se typicky pro elementární kontrolu, že kód ještě pořád funguje (například po refaktoringu).

D

Re:výjimka vs assert
« Odpověď #6 kdy: 24. 01. 2015, 19:21:13 »
Obecně v mnoha zdrojích jsem našel: use asserts for things that should never happen, což ale podle platí i pro spoustu výjimek. Rozdíl vidím v tom, že aserce neslouží k řešení situace, oproti výjimce, která toto umožní. Také use exceptions when checking parameters passed to public or protected methods and constructors, je ve shodě s odpověďmi. Nicméně to je asi pořád více méně ještě závislé na jazyku, ve kterém to řeším.

Někdo

Re:výjimka vs assert
« Odpověď #7 kdy: 24. 01. 2015, 21:13:16 »
Assert v Javě označuje předpoklady, které musí být splněné, aby kód fungoval správně. Když nejsou splněné, neznamená to nutně, že kód bude fungovat špatně - proto je kontrola assercí při vývoji zapnutá (aby se odhalila místa, kde se něco používá špatně), ale při provozu zapnuté být nemusí. Výjimka naproti tomu znamená, že tohle určitě nemůže dopadnout dobře.

Třeba píšu funkci, u které vím, že teď ji nikdy nebudu volat s null jako parametrem. V funkci je na to assert a při psaní neřeším případ, že by parametr byl null. Pokud ji ale s null někdo zavolá a má vypnuté asserty, může se stát, že ta funkce proběhne bez chyby. A nebo někde spadne na NullPointerException (v Javě). Pokud ale vím, že by ta funkce s null parametrem fungovala špatně, dám tam if a vyhození NPE.

Chybí tu popis jedné zásadní vlastnosti assert v Javě: pokud podmínka selže, je vyhozena výjimka java.lang.AssertionError což je potomek java.lang.Error a stejně jako všichni ostatní potomci java.lang.Error nemá být tato výjimka nikdy chytána a jakkoliv zpracovávána - znamená totiž že došlo k situaci která je neopravitelná (podobně jako například java.lang.OutOfMemoryError). Toto je zásadní rozdíl proti tomu kdy si výjimku hážu sám, to si totiž můžu vybrat potomka java.lang.Exception kde se počítá s tím že je aplikace může chytat a pokoušet se zpracovat.

Re:výjimka vs assert
« Odpověď #8 kdy: 24. 01. 2015, 22:42:46 »
Chybí tu popis jedné zásadní vlastnosti assert v Javě: pokud podmínka selže, je vyhozena výjimka java.lang.AssertionError což je potomek java.lang.Error a stejně jako všichni ostatní potomci java.lang.Error nemá být tato výjimka nikdy chytána a jakkoliv zpracovávána - znamená totiž že došlo k situaci která je neopravitelná (podobně jako například java.lang.OutOfMemoryError). Toto je zásadní rozdíl proti tomu kdy si výjimku hážu sám, to si totiž můžu vybrat potomka java.lang.Exception kde se počítá s tím že je aplikace může chytat a pokoušet se zpracovat.
To je správně, výjimka z assertu se nemá zachytávat - pokud selže assert, je to stav aplikace, se kterým se nepočítá. Pokud s danou situací počítám, musím upravit aplikaci tak, aby assert neselhával.

D

Re:výjimka vs assert
« Odpověď #9 kdy: 24. 01. 2015, 23:46:26 »
Jestli se nepletu, tak např. v Pythonu se právě `assert` může zachytávat a to pomocí `AssertionError`. Toť rozdíl oproti Javě. Při optimalizaci Pythonu se ale `assert` odstraní, podobně jako při použití direktivy kompilátoru.

Re:výjimka vs assert
« Odpověď #10 kdy: 24. 01. 2015, 23:53:51 »
Selhani assertu je takovej stav, kdyz se algoritmus dostane do stavu, ve kterym bejt nesmi

takze assert pouzit pro kontrolu vnitrniho stavu algoritmu, nikdo z vnejsku to nesmi byt schopen vyvolat!
na osetreni vstupu vzdy vyhodit vyjimku (obvykle NPE, IAE), NPE se taky vyhazuje i automaticky, pro ohlidani null se i daji pouzit @NonNull a @Nullable anotace (napriklad je pro to podopra v Eclipse), ale pak je treba toto pouzivat vsude, ale daji se timto zpusobem ohlidat NPE (prekladac ziska informace o mistech, kde muze dochazet k NPE)

zboj

  • *****
  • 1 507
    • Zobrazit profil
    • E-mail
Re:výjimka vs assert
« Odpověď #11 kdy: 25. 01. 2015, 00:25:54 »
Ten příklad s dělením je hezký. Jak už tu zaznělo, jde-li vstup od uživatele, nesmí se to řešit asertem. Asert odchytává situace, kdy je chyba v kódu, a měl by mít za následek ukončení aplikace.

Jinak od výjimek se v některých jazycích/knihovnách upouští. Někdo tvrdí, že výjimky jsou jen převlečené goto. Já bych spíš řekl zamaskovaný long jump. Většinou je lepší vracet chybu jinak (například výstupním parametrem nebo vláknově lokální proměnnou jako v C), výjimky mají už podle názvu řešit výjimečné situace, ne chybu na vstupu.

Radek Miček

Re:výjimka vs assert
« Odpověď #12 kdy: 25. 01. 2015, 00:53:32 »
výjimky mají už podle názvu řešit výjimečné situace, ne chybu na vstupu.

Název může být chybný. Kdy je vhodné použít výjimky, záleží na konkrétním jazyku a jeho konkrétní implementaci.

Re:výjimka vs assert
« Odpověď #13 kdy: 25. 01. 2015, 00:57:31 »
ja bych rekl, ze vyjimka pro chybu na vstupu dava ladici informaci o tom, ze kdyz ji nezachytime, program spadne a vypise, k cemu doslo (pripadne muzeme vyjimku odchytit, ale pak jsme vedomi toho, ze k chybe na vstupu dojit muze) Vono v jave stejne muzes budto vratit normalni hodnotu, vratit null nebo vyhodit vyjimku. Null muze mi i nekdy svuj vyznam ho vracet, navic muze posunou problem o patro vejs (a zkreslit ho), takze je opravdu nejlepsi vratit vyjimku (ktera presne popise co se stalo). Vyjimka je zpusob, jak metoda muze oznamit, ze neni schopna skoncit "standardnim" zpusobem

D

Re:výjimka vs assert
« Odpověď #14 kdy: 25. 01. 2015, 00:59:07 »
@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