Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Obrada gresaka : exception ili return message

[es] :: Art of Programming :: Obrada gresaka : exception ili return message
(TOP topic, by vlaiv)

[ Pregleda: 7883 | Odgovora: 19 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

misk0
.: Lugano :. _.: CH :.

SuperModerator
Član broj: 634
Poruke: 2824
*.adsl.ticino.com.

ICQ: 46802502


+49 Profil

icon Obrada gresaka : exception ili return message22.02.2010. u 23:15 - pre 171 meseci
Danas smo nesto na faxu razgovarali, koja je bolja i zasto metodologija za obradu gresaka u nekom programskom bloku. Nije vezano ni za jedan programski jezik. Da li je bolje u tom bloku obraditi gresku pa na izlazu vratiti poruku ili je bolje podici Exception pa u proceduri koja je pozvala taj blok obraditi taj exception. Vase misljenje?
:: Nemoj se svadjati sa budalom, ljudi cesto nece primjetiti razliku ::
 
Odgovor na temu

Goran Rakić
Beograd

Član broj: 999
Poruke: 3766

Sajt: blog.goranrakic.com


+125 Profil

icon Re: Obrada gresaka : exception ili return message22.02.2010. u 23:21 - pre 171 meseci
Aplikativna logika treba isključivo da baci izuzetak, a onda pozivalac može zavisno od konteksta daleko bolje da pokuša oporavak ili prezentuje grešku (poruka, dnevnik, sms, prozorčić,...). U protivnom si vezan obradom koja je na pogrešnom mestu i kod daleko teže možeš iskoristiti u nekom drugom kontekstu.
http://sr.libreoffice.org — slobodan kancelarijski paket, obrada teksta, tablice,
prezentacije, legalno bez troškova licenciranja
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1249



+96 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 07:42 - pre 171 meseci
Izuzeci su dobri jer ti oslobađaju povratnu vrednost funkcije za ono što funkcija zaista treba da vrati. Takođe, kod je pregledniji jer nema silnih if-return iskaza. Ono što ne valja kod izuzetaka u C++ je što se izgubi informacija o tome gde je izuzetak nastao, a to ti treba za lociranje greške u produkciji. Ako ti to treba (a trebaće u jednom trenutku) moraš da napraviš sopstveni sistem koji će da ti obezbedi tu informaciju. U Javi je to bolje napravljeno.
 
Odgovor na temu

misk0
.: Lugano :. _.: CH :.

SuperModerator
Član broj: 634
Poruke: 2824
*.adsl.ticino.com.

ICQ: 46802502


+49 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 07:52 - pre 171 meseci
Da, slazem se. A sta se desava ako taj blok definishe custom izuzetke? To znaci da u aplikaciji moras imati dugacku listu catch exception uslova, nije li to malo "ruzno"?
Sta se desava sa tokom programa po povratku iz tog bloka ako je pozvan exception unutar bloka? Kako znam da li program treba da nastavi ili da prekine izvrsavanje ostatka koda? Moram opet nekako u Exceptionu vratiti neku vrijednost koja ce znati sta da radim dalje? Definisanjem globalne varijable ili kako?
Postoji velik broj "core exceptions" tako da ne mogu unutar exceptiona odlucivati kako ce program nastaviti jer program moze razlicito nastaviti u zavisnosti gdje se desio isti exception?

:: Nemoj se svadjati sa budalom, ljudi cesto nece primjetiti razliku ::
 
Odgovor na temu

Mihajlo Cvetanović
Beograd

Moderator
Član broj: 37636
Poruke: 1249



+96 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 09:01 - pre 171 meseci
Obično kad se desi izuzetak posao se ne nastavlja. Ako je logika takva da često moraš da se oporavljaš od izuzetka i nastavljaš rad onda bolje promeni logiku. Uvedi recimo nekakvu callback funkciju, može virtuelna funkcija klase, u kojoj se odlučuje o oporavku i nastavku rada. Kad se izuzetak desi onda korisnik obično mora nešto da promeni u svojim akcijama i pokuša ponovo.

Izuzeci su dobri i što te teraju da koristiš RAII idiom, bar u C++. U Javi ga koristiš hteo ne hteo.
 
Odgovor na temu

vladar85
php developer

Član broj: 250711
Poruke: 13
212.200.65.*



Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 09:13 - pre 171 meseci
Mislim da treba u catch bloku u zavisnosti od tipa greshke izvrshiti eventualne operacije(dealociranje memorije i sl.), i rethrow-vati odredjenu custom exception ili vec postojecu koja bi na vishem nivou bila adekvatno interperetirana i obradjena na vec odgovarajuci nacin.

Shto se tiche hvatanja "preostalih" greshaka catch(...) u c++ ili u javi catch(Exception e) ako se dobro secam pokrice ostatak bez problema. Naravno kritichnu zonu treba pokriti ugnezhdenim try catch blokovima kako bi se to shto bolje "prosejalo". Ne zaboravimo da u javi imamo i finnaly blok koji se poziva bez obzira na exception, obicno sa ulogom da se pocisti smece koje smo tokom izvrsavanja metode napravili. Slicno je i na ostalim jezicima.

Dakle treba znati koja klasa ili funkcija mozhe da baci izuzetak i kog tipa, te je opkoliti odgovarajucim try catch blokom, a onda baciti izuzetak u spoljni tray catch koji hvata sve izuzetke i izbaciti dalje na mesto gde je metoda/funkcija bila pozvana. Time dobijamo mogucnost da u kontekstu poziva podrutine koja je izbacila izuzetak nastavimo odredjenim putem, a ujedno i cistimo za sobom nakon pokusaja realizacije date podrutine.
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 10:18 - pre 171 meseci
Moj odgovor je i jedno i drugo a teorija se vuce iz teorija o state masinama, jer u sonovi programi su komplikovane state masine.

exception treba da sluzi kao vanredna mera, dakle u situaciji kada je state koda doveden u poziciju iz koje ne moze da se izvuce, bilo zato sto je state nelegalan (nedefinisan), izlazna tranzicija iz stanja nije definisana ili zato sto postoji ambiguity izmedju dve ili vise tranzicija. Ako umesto exceptiona vratis povratnu vrednost to znaci da si dodao tranzicije/grane u state masinu koje iz nelegalne pozicije vracaju stanje u neki od definisanih stanja i time si kompletirao state masinu, sto nije uvek pozeljna situacija. U prakticnom smislu to onda znaci da pozivaoc mora da koristi if/then/else strukturu da otkrije da li je taj state njemu upotrebljiv. (npr ako otvaras socket kroz api moras da proveris povratnu vrednost da vidis da li je socket zaista otvoren).
Tebe realno nista ne sprecava da tu masinu kompletiras van funkcije koja baca exceptione, samo napravis wrapper funkciju koja kroz try/catch poziva funkciju koja baca exceptione i definises nedostajuci state u catch bloku i time si ti odredio da ZNAS kako da ispravis stanje state masine, ako ne znas onda pustas exception dalje niz stek dok ne dodje kod onoga koji ZNA kako da je zakrpi. Ako dodje do kraja steka to onda znaci da niko ne zna kako da razresi taj state i program bi morao da pukne jer je situacija bezizlazna. Ja recimo ne dozvoljavam catch(Exception) do-it-all konstrukcije, to znaci da ti tvrdis da imas resenje za SVE MOGUCE probleme koji ce nastati u svim mogucim pod koracima sto skoro nikad nije tacno. Postoji mnogo nediscipline u koriscenju exceptiona.
Ako ti u startu izbegnes exception ti time tvrdis kao autor funkcije da ona predstavlja kompletnu state masinu, ako to nisi spreman, baci exception. To isto medjutim znaci da ne treba da bacas exceptione za one situacije za koje sam znas kako da resis bez pomoci pozivaoca jer ti za ta stanja imas jednoznacno definisane tranzicije u stabilan state.

Problem sa exceptionima je sto nisu skalabilni za batch operacije, a to ce se pokazati problematicno vrlo brzo sa sve vise nadirucom paralelizacijom (ako u thread poolu od 25 threadova jedan worker thread baci exception a drugih 24 ne koji je status cele paralelizovane operacije? i na kom threadu ce i ko ce baciti koji exception? itd). Ako saljes 100 database operacija u ne-atomicnoj batch operaciji i jedan pukne da li su onda svi pukli? Ili su pukli samo oni iza operacije koja je bacila exception, iako bi oni mozda prosli ok? Zar nije bolje onda nemati exception vec po zavrsetku operacije videti koje su uspele a koje treba doraditi/ponoviti? Tako da stvari nisu bas crno-bele.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

vlaiv
Vladimir Vlaisavljevic
Novi Sad

Član broj: 15993
Poruke: 352
212.200.249.*



+1 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 10:26 - pre 171 meseci
Saglasan sa mmix

Bash htedoh nesto slicno napisati.

Dodao bih jos jednu stvar. Exception je zgodno koristiti tako da korisnicima biblioteke koda
olaksa shvatanje API-a.

Primer: baciti exception ukoliko nije uradjena inicializacija. Znaci ukoliko se doslo u state koji
po logici stvari ne bi trebalo da postoji, pogresnom upotrebom biblioteke. Korisnici cesto
prelete dokumentaciju i ne vide da je potrebno nesto uraditi pre neceg drugog (prvo inicijalizuj
posle koristi)

Exception ako nosi u sebi tu poruku, brzo i efikasno stavi to korisniku do znanja.
 
Odgovor na temu

deerbeer
Beograd

Član broj: 174418
Poruke: 1189
*.adsl-1.sezampro.yu.



+395 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 10:51 - pre 171 meseci
Mozes napraviti custom klasu koja ce biti definisana da "baca" exceptione kad je to potrebno i eventualno kao neka povratna vrednost ,
za slucaj da bude neka enumeracija kao povratni tip . Prosiri je da moze i da ukljuci i zapis u neki log fajl .
Klasu mozes naslediti pa koristiti bazne metode ili kroz interfejs/abstract class , pa da implementira svaka na svoj nacin izuzetke.
Da li ces vise koristiti exception-e ili samo log ili kroz povratnu vrednost zavisi iskljucivo od koda i situacija koje su ovde nabrojane.
Bitno je da imas i jedno i drugo kroz jednostavan programski interfejs .

Exceptione koristim obilato kad je na stack-u 10-20 funkcija a treba ti bezuslovan izlazak iz prve pozivajuce f-je.
Onda sledi bublle-up Exceptiona iz pozvane f-je u onu pozivajucu itd .. tj. vraca se izvrsavanja koda sa hvatanjem Exceptiona .
Mana ovoga je da se mnogo exception objekata generise na stacku.






Viva lollapalooza
 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 12:20 - pre 171 meseci
Citat:
mmix:
Problem sa exceptionima je sto nisu skalabilni za batch operacije, a to ce se pokazati problematicno vrlo brzo sa sve vise nadirucom paralelizacijom (ako u thread poolu od 25 threadova jedan worker thread baci exception a drugih 24 ne koji je status cele paralelizovane operacije? i na kom threadu ce i ko ce baciti koji exception? itd). Ako saljes 100 database operacija u ne-atomicnoj batch operaciji i jedan pukne da li su onda svi pukli? Ili su pukli samo oni iza operacije koja je bacila exception, iako bi oni mozda prosli ok? Zar nije bolje onda nemati exception vec po zavrsetku operacije videti koje su uspele a koje treba doraditi/ponoviti? Tako da stvari nisu bas crno-bele.


Hm... zar nije identicna situacija i sa return value? Jedina razlika izmedju return value i exceptiona koliko sam ja uspeo da shvatim je to sto exceptioni mogu da putuju po stacku nesmetano, dok return value mora da se hvata i prosledjuje za svaku f-ju pojedinacno ako se zeli isti efekat kao exception. Doduse iz toga proizlazi da je bolje kada exception pukne nego kada se dovede state programa u takvo stanje da je jako tesko naci gresku.
 
Odgovor na temu

deerbeer
Beograd

Član broj: 174418
Poruke: 1189
*.adsl-1.sezampro.yu.



+395 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 12:40 - pre 171 meseci
Pa nije identicna situacija :
evo primer :
Code:

public int  SomeFunction ()
{

 try 
 {
  int nRetVal =  DoIt () ; 
 ..
 ..

 }
  catch (Exception exc) 
  {
    throw exc ; 
   // exception se dalje prosledjuje pozivajucoj f-iji 
  }

}

public int DoIt () 
{
 try 
 {
  // neki kod za izvrsavanje

 }
 catch (Exception exc) 
 {
    throw exc ; 
 }

}


Ako DoIt baci izuzetak SomeFunction ce to registrovati odmah bez ikakvog daljeg izvrsavanja koda ,
a ako bi vracao neki return vrednost po izlasku iz f-je DoIt situacija je nepredvidiva pogotovu ako ima jos par uslova
koje treba ispitati ako u njoj nisi vratio vrednost koju treba.

Na taj nacin teze je detektovati gresku i predvideti grananje izvrsavanja celog koda .
Ali sve ima svoju cenu tj. posledice po performanse ,
a to je kao sto sam i napomenuo generisanje exception objekata po stacku
dok je kod povratnih vrednosti promenjljiva vec alocirana na stacku .


Viva lollapalooza
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 12:58 - pre 171 meseci
Pa nije isto, u batch operaciji mozes da imas completed fleg koji ti je svojevrsan pandan multi-returnvalue, posle batch-a proveris i vidis koje operacije su prosle, mozes flag cak da iskoristis kao vizuelnu indikaciju korisniku u gridu, ako te exception izbaci operacija je zavrsena, najbolje sto mozes da uradis je da prijavis korisniku taj jedan na kojem je puklo i pride jos moras da se bakces sa svima onima iza njega koji jos nisu ni dobili sansu da budu upisani (a gde mozda ima jos neispravnih koji ce opet mroati pojedinacno da se resavaju).

Postoji tu jos problema koje upotreba exceptiona donosi sa sobom, jedan primer je bas dao deerbeer, bezuslovni izlaz u prvu funkciju kad ti je stek natrpan pozivima, i to moze da sljaka dok god je taj branch steka potpuno izlovan i modularan, recimo neka rekurzivna funkcija sa samo lokalnim varijablama. Ako sa druge strane kod izaziva side-effects (sto je verovatnije) onda imas veliki problem ako koristis exceptione kao flow control i premotas stek na pocetak jer onda pojma nemas sta je od efekata ispoljeno i kakav je state programa. Stvarno ne bi trebalo da koristite exception kao GOTO, narocito ako pride koristite i Disposable patern a niste sve dispose stavili u finally blokove SVUDA, sto je uobicajena praksa u .NETu. U praksi ako sam pozivac nema try/catch kompletiranje za operaciju ne bi trebao ni da ga ima njegov pozivac jer on jos manje ima pojma o tome kako da ispravi situaciju, ako exception propadne kroz prvi blok treba ga pustiti da obori aplikaciju ili ga treba dokumentovati za pozivaca ako exception nastaje indeirektno kao posledica njegovih parametara; to inace stalno vidite u MSDN dokumentaciji za .NET, za svaki metod moguce exceptione i razloge zbog kojih nastaju i iz toga izvlacite odgovarajuce ZNANJE o handlovanju tih exceptiona, neki od njih dopiru direktno iz pozvanog metoda, neke pak pozvana metoda samo propusti iz drugih metoda koje je ona zvala. Java to ima fino reseno sa checked exceptions.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 13:08 - pre 171 meseci
Kazes nije isto a napises:

Citat:

Ako DoIt baci izuzetak SomeFunction ce to registrovati odmah bez ikakvog daljeg izvrsavanja koda ,
a ako bi vracao neki return vrednost po izlasku iz f-je DoIt situacija je nepredvidiva pogotovu ako ima jos par uslova
koje treba ispitati ako u njoj nisi vratio vrednost koju treba.


U prevodu exception puca i signalzira gresku, operacija se prekida. Sa return value dolazi do greske ali to se jos plus ne vidi, nego se operacija nastavlja sa ko zna kakvim posledicama. Pa to je, bar meni tako zvuci, kao formalizam, kao papir, napises da si uradio a u stvarnosti truba.
 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 13:12 - pre 171 meseci
Citat:
mmix
Pa nije isto, u batch operaciji mozes da imas completed fleg koji ti je svojevrsan pandan multi-returnvalue, posle batch-a proveris i vidis koje operacije su prosle, mozes flag cak da iskoristis kao vizuelnu indikaciju korisniku u gridu, ako te exception izbaci operacija je zavrsena, najbolje sto mozes da uradis je da prijavis korisniku taj jedan na kojem je puklo i pride jos moras da se bakces sa svima onima iza njega koji jos nisu ni dobili sansu da budu upisani (a gde mozda ima jos neispravnih koji ce opet mroati pojedinacno da se resavaju).



Nisam siguran da razumem, ja sam citirao tvoj deo gde si rekao gde imas thread pool sa 25 threadova, posto su u pitanju paralelne operacije onda svaka operacija ima svoj fleg, ako od njih neka pukne ono sto ja mislim je - da je svejedno koje signalizirao da je operacija pukla, s tim sto sam samo precizirao da je return vale jos podmukliji jer se moze zagubiti greska a kao sve radi OK.

I plz, ako moze neki primer, mozda sam ja nesto prevideo.
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 13:45 - pre 171 meseci
Radi se o batch operaciji bilo koje vrste, i thread pool je jedna varijanta batch obrade tako da se svodi na manje vise isto. I da, moras da proveris sve flegove (to je ekvivalent sa if/then/else proverom u single method varijanti). Greska ne moze da ti se provuce nikako ako si sve flegove proverio. Return value je jednostavno indikacija da se funkcija nije izvrsila onako kako si ocekivao, nasuprot excpetionu koji kaze da je funkcija "pukla" u nedostatku boljeg termina. Mozda bi pomoglo ako o return value razmisljas kao o error handlingu a exceptionu kao critical error handlingu.
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

mmix
Miljan Mitrović
Profesorkin muz
Passau, Deutschland

SuperModerator
Član broj: 17944
Poruke: 6041



+4631 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 13:52 - pre 171 meseci
Evo da citiram bar nekog da ne bude da sam usamljena dusa :)

http://www.sturmnet.org/blog/2005/03/29/exceptions-flow

"An exception is meant as an instrument to signal that your application's flow has been broken. That's the one most important feature of the exception handling subsystem: it works across all boundaries of application flow. It's neither designed nor very useful for any situation where the state of the application is known.

Rule of thumb: if you expect that an error may occur in any specific line of code, and you are going to implement alternate handling for that particular case, don't use an exception. That's not an unexpected application state and shouldn't be handled with an exception."
Sloba je za 12 godina promenio antropološki kod srpskog naroda. On je od jednog naroda koji je bio veseo, pomalo površan, od jednog naroda koji je bio znatiželjan, koji je voleo da vidi, da putuje, da upozna,
od naroda koji je bio kosmopolitski napravio narod koji je namršten, mrzovoljan, sumnjicav, zaplašen, narod koji se stalno nešto žali, kome je stalno neko kriv… - Z.Đinđić
 
Odgovor na temu

deerbeer
Beograd

Član broj: 174418
Poruke: 1189
*.adsl-1.sezampro.yu.



+395 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 14:16 - pre 171 meseci
Citat:

Mozda bi pomoglo ako o return value razmisljas kao o error handlingu a exceptionu kao critical error handlingu.

Zato sam i napomenuo da custom klasa za exceptione koristi vise nivoa tj. severity errors .
Ako joj se prosledi flag critical onda baca exceptione msg box a recimo flag "report" ili "alert"
upisuje u log ili u report status ako je u batch-u pomocu povratne vrednosti iz f-ije.
I jedno i drugo treba pazljivo koristiiti i primeniti tamo gde treba .
Nema jedinstvenog recepta koji leci sve muke u vezi ovog .


Viva lollapalooza
 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Obrada gresaka : exception ili return message23.02.2010. u 14:17 - pre 171 meseci
Citat:
mmix
I da, moras da proveris sve flegove (to je ekvivalent sa if/then/else proverom u single method varijanti). Greska ne moze da ti se provuce nikako ako si sve flegove proverio. Return value je jednostavno indikacija da se funkcija nije izvrsila onako kako si ocekivao, nasuprot excpetionu koji kaze da je funkcija "pukla" u nedostatku boljeg termina.


Sa ovim se u potpunosti slazem, ali to znaci da je exception precizniji. On ti kaze da si negde zabrljao dok za return value si rekao "Greska ne moze da ti se provuce nikako ako si sve flegove proverio", kljucna rec je ako. Ako nisi provero sta onda, jer ako primenis isti model na exceptione, "ako handlujes sve exceptione koje se mogu pojaviti koji se nalaze u potpisu metode, ne i sve koji se deklarisu u potpisu metode" onda si na istom. Ja bih rekao da je exception bolji mehanizam kao podesetnik da si nesto prevideo, jer exception putuje po celom stacku, dok se return value zaustavlja vec na calleru (probacu da namestim jedan mali primer, nisam siguran koliko je sve ovo jasno za ostale sto cituaju, a i ja se ponekad zbunim ).

BTW. Da ne isapdne da sam ljubitelj EH, treba ga koristiti kao i svaki drugi alat, ali moje neko vidjenje je da je, bar u .NET-u, EH previse koriscen, kao runtime metod za odbranu od gresaka, ali mislim da se krenulo u pogresnom smeru, bolje da su se orijentisali odmah ka statickoj validaciji code-a, pa bi onda bilo i manje potrebe za silnim onim preconditionima. No, mozda je to sad lako reci, dovde ih je dovela evolucija, pa mozda nije lako bilo videti sve to ranije.

[Ovu poruku je menjao negyxo dana 23.02.2010. u 15:29 GMT+1]
 
Odgovor na temu

negyxo
Aleksandar Perkuchin

Član broj: 29751
Poruke: 898
82.117.202.*



+171 Profil

icon Re: Obrada gresaka : exception ili return message24.02.2010. u 10:54 - pre 171 meseci
Elem,

Evo namestio sam jedan primer koji bi trebao ovo sto smo diskutovali da objasni. Prvo cu na brzinu objasni code, pa onda ceo primer, neka svako proba.

Code je napisan u C#, konzolna aplikacija, minimalno sam koristio .NET FW, cini mi se samo Console.WriteLine() i Console.ReadLine().

Postoje cetri testa: ReturnValueTest1, ReturnValueTest2, ExceptionTest1 i ExceptionTest2.

ReturnValueTest1 je test sa CreateBackup metodom koja ima gresku, programer je zaboravio da proveri gresku i return value ne vraca ispavne vrednosti. ReturnValueTest2 je isti test kao i prvi sa ispravljenom metodom.
ExceptionTest1 je test sa CreateBackup metodom koja ima gresku ali ova greska nece uticati na output u krajnjoj operaciji. ExcetionTest2 je isto sto i prvi test samo sa ispravljenom meodom.


Svi testovi se sastoje od sledece cetri metode Backup1, Backup2, CreateBackup, Compress i WriteFile:

Code:

        private bool CreateBackup(string srcFileName, string destFileName)
        {
            // precodintions
            if (srcFileName == null) return false;
            if (destFileName == null) return false;

            byte[] compressedBytes;

            Compress(srcFileName, out compressedBytes);
            WriteFile(destFileName, compressedBytes);

            return true;
        }
        
        private bool Compress(string srcFileName, out byte[] compressedBytes)
        {
            compressedBytes = null;
            // precodintions
            if (srcFileName == null) return false;

            Console.WriteLine("Compressing file :   {0} ", srcFileName);
            compressedBytes = new byte[] { 1, 2, 3, 4 };

            return true;
        }

        public bool WriteFile(string destFileName, byte[] compressedBytes)
        {
            // precodintions
            if (destFileName == null) return false;
            if (compressedBytes == null) return false;
            if (destFileName.EndsWith("log")) return false;

            Console.WriteLine("Writing file :       {0} ", destFileName);

            return true;
        }
        
        public bool Backup1()
        {
            if (!CreateBackup(@"D:\t1.log", @"D:\b1.log")) return false;
            if (!CreateBackup(@"D:\t2.txt", @"D:\b2.bkp")) return false;
            if (!CreateBackup(@"D:\t3.txt", @"D:\b3.bkp")) return false;

            return true;
        }
        
        public bool Backup2()
        {
            bool b1 = CreateBackup(@"D:\t1.log", @"D:\b1.log");
            bool b2 = CreateBackup(@"D:\t2.txt", @"D:\b2.bkp");
            bool b3 = CreateBackup(@"D:\t3.txt", @"D:\b3.bkp");

            return b1 | b2 | b3;
        }


Naime, ideja je da imamo neku backup batch operaciju koja treba da backup-uje vise fajlova, imamo dva tipa backup-a, jedan koji ukoliko dodje bilo gde do greske izlazi iz metode, i drugi koji prvo obavi sve operacije pa zatim akumulira rezultat svih operacija (ovo je isto promenljivo, da li se zeli AND ili OR operacija). U zavisnosti od testa sve metode se menjaju na odredjeni nacin, recimo return value vraca value kod loseg prosledjenog argumenta dok EH vraca exception.


Evo i celog testa, ostavio sam komentare tako da ne pisem ponovo sve ovde. Nadam se da ce biti pitanja, posto mnoge stvari sam samo pomenuo sto ce verovatno nekima biti nejasno, ali zato smo tu


Code:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace ExceptionReturnValueTest
{
    class Program
    {
        static void Main(string[] args)
        {
            ReturnValueTest1 rvt1 = new ReturnValueTest1();

                        
            Console.WriteLine("Testing return value with error");
            Console.WriteLine("--------------------------------------------------------");
            Console.ReadLine();
            // u ovom slucaju Backup1 nas "lazno" informise
            Console.WriteLine("Backup1 result {0}", rvt1.Backup1());
            Console.WriteLine();
            Console.WriteLine("Creating backup");
            Console.WriteLine("Backup2 result : {0}", rvt1.Backup2());
            Console.WriteLine();

            ExceptionTest1 et = new ExceptionTest1();
            Console.WriteLine("Testing exception with error");
            Console.WriteLine("--------------------------------------------------------");
            Console.ReadLine();
            // u ovom slucaju Backup1 zbog EH nas obavestava da smo nesto propustili
            Console.WriteLine("Backup1 result : {0}", et.Backup1());
            Console.WriteLine();
            Console.WriteLine("Creating backup");
            Console.WriteLine("Backup2 result : {0}", et.Backup2());
            Console.WriteLine();


            ReturnValueTest2 rvt2 = new ReturnValueTest2();
            Console.WriteLine("Testing return value with corrected method");
            Console.WriteLine("--------------------------------------------------------");
            Console.ReadLine();            
            Console.WriteLine("Creating backup");
            Console.WriteLine("Backup1 result : {0}", rvt2.Backup1());
            Console.WriteLine();
            Console.WriteLine("Creating backup");
            Console.WriteLine("Backup2 result : {0}", rvt2.Backup2());
            Console.WriteLine();


            ExceptionTest1 et2 = new ExceptionTest1();
            Console.WriteLine("Testing exception with corrected method");
            Console.WriteLine("--------------------------------------------------------");
            Console.ReadLine();
            Console.WriteLine("Backup1 result : {0}", et2.Backup1());
            Console.WriteLine();
            Console.WriteLine("Creating backup");
            Console.WriteLine("Backup2 result : {0}", et2.Backup2());
            Console.WriteLine();

            Console.ReadLine(); 
        }
    }

    // Prvi test je sa return value vrednosti, metoda CreateBackup nije dobro napisana
    // zaboravlja se provera vrednosti WriteFile metode, ovo dovodi do nevalidnog stanja programa
    public class ReturnValueTest1
    {
        private bool CreateBackup(string srcFileName, string destFileName)
        {
            // precodintions
            if (srcFileName == null) return false;
            if (destFileName == null) return false;

            byte[] compressedBytes;

            if (!Compress(srcFileName, out compressedBytes)) return false;

            // ovde se zaboravlja provera return value, sto znaci da program odolazi u 
            // neko nedefinisano stanje, ovo moze da prouzrokuje bilo sta ali da kazemo
            // da ce u ovom slucaju samo nastaviti sa ekzekucijom + side effect
            WriteFile(destFileName, compressedBytes);

            return true;
        }

        // Compress metoda je vise kao noise, da ne bi bas bilo obicno propagiranje 
        // CreateBackup-a WriteFile metodi
        private bool Compress(string srcFileName, out byte[] compressedBytes)
        {
            compressedBytes = null;
            // precodintions
            if (srcFileName == null) return false;

            Console.WriteLine("Compressing file :   {0} ", srcFileName);
            compressedBytes = new byte[] { 1, 2, 3, 4 };

            return true;
        }

        public bool WriteFile(string destFileName, byte[] compressedBytes)
        {
            // precodintions
            if (destFileName == null) return false;
            if (compressedBytes == null) return false;

            // ovo je dodato kao simulacija WriteFile methode, da bi kao na osnovu ulaza
            // dobili neku false vrednost, recimo da bi u praksi ovo znacilo da je fajl 
            // system nedostupan (recimo write permission)
            if (destFileName.EndsWith("log")) return false;

            Console.WriteLine("Writing file :       {0} ", destFileName);

            return true;
        }

        // prvi slucaj : izlazi se iz metoda cim dodje do false vrednosti        
        public bool Backup1()
        {
            if (!CreateBackup(@"D:\t1.log", @"D:\b1.log")) return false;
            if (!CreateBackup(@"D:\t2.txt", @"D:\b2.bkp")) return false;
            if (!CreateBackup(@"D:\t3.txt", @"D:\b3.bkp")) return false;

            return true;
        }

        // drugi slucaj : svaki rezultat se 'kesira' tek kada svi 
        // metodi zavrse posao proverava se ukupan rezultat
        public bool Backup2()
        {
            bool b1 = CreateBackup(@"D:\t1.log", @"D:\b1.log");
            bool b2 = CreateBackup(@"D:\t2.txt", @"D:\b2.bkp");
            bool b3 = CreateBackup(@"D:\t3.txt", @"D:\b3.bkp");

            return b1 | b2 | b3;
        }
    }


    // Drugi test je ekvivalent sa EH, 
    // mala napomena:
    // - nigde se ne hvata general catch osim u backup metodama, jer su one simulacija neke batch oepracije
    // - provera argumenata se ne handluje preko exceptiona, tereba koristiti defensive programming*
    public class ExceptionTest1
    {
        private void CreateBackup(string srcFileName, string destFileName)
        {
            // precodintions
            if (srcFileName == null) throw new ArgumentException();
            if (destFileName == null) throw new ArgumentException();

            byte[] compressedBytes;
            Compress(srcFileName, out compressedBytes);


            // programer je zaboravio da handluje exception, ali ovde sada dolazi do sledeceg problema
            // WriteFile baca IOException - ako programer uhvati exception sta dalje raditi, baciti novi exception
            // jer se ne zna rezultat WriteFile operacije? Ja ovde vidim dva resenja:
            // 1. Baciti novi exception, moze 'prevedeni' exception sa informacijama
            // 2. Koristiti return value 

            // Prvo resenje znaci da koristimo Exception za komunikaciju, ali ovde opet treba gledati da li je exception
            // nesto sto ocekujemo ili ne, jer ako ga ocekujemo onda treba koristiti drugo resenje - return value
            WriteFile(destFileName, compressedBytes);
        }

        private void Compress(string srcFileName, out byte[] compressedBytes)
        {
            compressedBytes = null;
            // precodintions
            if (srcFileName == null) throw new ArgumentException();

            Console.WriteLine("Compressing file :   {0} ", srcFileName);
            compressedBytes = new byte[] { 1, 2, 3, 4 };
        }

        public void WriteFile(string destFileName, byte[] compressedBytes)
        {
            // precodintions
            if (destFileName == null) throw new ArgumentException();
            if (compressedBytes == null) throw new ArgumentException();

            // slicno kao kod return value, simulira write metodu
            if (destFileName.EndsWith("log")) throw new IOException();

            Console.WriteLine("Writing file :       {0} ", destFileName);
        }

        public bool Backup1()
        {
            try
            {
                // ovo je interesantna stvar, po defaultu pozivi metoda sa exceptionima
                // prekidaju ekzekuciju dok kod return value pozivi se nastavljaju (imamo podmuklu gresku) 
                // jos jedna stvar je ta sto mi imamo gresku u WriteFile metodi koju poziva CreateBackup
                // posto smo zaboravili exception da handlujemo exception putuje niz stack i propagira 
                // se do ovog catch bloka
                CreateBackup(@"D:\t1.log", @"D:\b1.log");
                CreateBackup(@"D:\t2.txt", @"D:\b2.bkp");
                CreateBackup(@"D:\t3.txt", @"D:\b3.bkp");

                return true;
            }
            catch 
            {
                return false;
            }
        }
        
        public bool Backup2()
        {
            // a da bi vrednosti svakog poziva pojedinacno proverili, da bi se dobio isti efekat
            // kao kod return value, onda je potrebno svaki poizv pojedinacno handlovati            
            bool b = false;
            try { CreateBackup(@"D:\t1.log", @"D:\b1.log"); b = true; } catch  { }
            try { CreateBackup(@"D:\t2.txt", @"D:\b2.bkp"); b = true; } catch  { }
            try { CreateBackup(@"D:\t3.txt", @"D:\b3.bkp"); b = true; } catch  { }

            return b;
        }
    }

    // Treci test je opet sa return value ali ovaj put CreateBackup metoda 
    // je dobro napisana sto rezultuje ispravnom output-u
    public class ReturnValueTest2
    {
        private bool CreateBackup(string srcFileName, string destFileName)
        {
            // precodintions
            if (srcFileName == null) return false;
            if (destFileName == null) return false;

            byte[] compressedBytes;

            if (!Compress(srcFileName, out compressedBytes)) return false;

            //  programer je uvideo gresku i proverio return value za WriteFile
            if (!WriteFile(destFileName, compressedBytes)) return false;

            return true;
        }

        private bool Compress(string srcFileName, out byte[] compressedBytes)
        {
            compressedBytes = null;
            // precodintions
            if (srcFileName == null) return false;

            Console.WriteLine("Compressing file : {0} ", srcFileName);
            compressedBytes = new byte[] { 1, 2, 3, 4 };

            return true;
        }

        public bool WriteFile(string destFileName, byte[] compressedBytes)
        {
            // precodintions
            if (destFileName == null) return false;
            if (compressedBytes == null) return false;

            // ovo je dodato kao simulacija WriteFile methode, da bi kao na osnovu ulaza
            // dobili neku false vrednost, recimo da bi u praksi ovo znacilo da je fajl 
            // system nedostupan (recimo write permission)
            if (destFileName.EndsWith("log")) return false;

            Console.WriteLine("Writing File : {0} ", destFileName);

            return true;
        }
        
        public bool Backup1()
        {
            if (!CreateBackup(@"D:\t1.log", @"D:\b1.log")) return false;
            if (!CreateBackup(@"D:\t2.txt", @"D:\b2.bkp")) return false;
            if (!CreateBackup(@"D:\t3.txt", @"D:\b3.bkp")) return false;

            return true;
        }
       
        public bool Backup2()
        {
            bool b1 = CreateBackup(@"D:\t1.log", @"D:\b1.log");
            bool b2 = CreateBackup(@"D:\t2.txt", @"D:\b2.bkp");
            bool b3 = CreateBackup(@"D:\t3.txt", @"D:\b3.bkp");

            return b1 | b2 | b3;
        }
    }


    // Cetvrti test je opet EH, ali ovaj put ispravljen propust, exception je handlovan
    // ali rezultat je i dalje isti, batch prijavljuje identicnu sitaciju kao i kada je 
    // metod CreateBackup bio lose implementiran
    public class ExceptionTest2
    {
        private void CreateBackup(string srcFileName, string destFileName)
        {
            // precodintions
            if (srcFileName == null) throw new ArgumentException();
            if (destFileName == null) throw new ArgumentException();

            byte[] compressedBytes;
            Compress(srcFileName, out compressedBytes);


            // programer handluje exception, ali ovde sada dolazi do vec opisanog problema, sta raditi sa uhvacenim exceptionom?
            // 1. Baciti novi exception, moze 'prevedeni' exception sa informacijama ili
            // 2. Koristiti return value 

            // recimo da je ovo situacija koja ne moze da se desi, onda cemo da bacamo exception
            // ako je sitacija koja moze da se desi onda vracamo return value 
            // 
            // uzecemo da je sitacija nemoguca pa cemo da bacamo dalje exception sto dodvodi do sledeceg pitanja
            // da li jednostavno pustiti exception (posto je on vec tipa IOException) ili 'prevesti' u neki novi exception?
            // (mala digresija, koji god metod da se izabere exception koji se baca mora biti izlistan u nekoj formi dokumentacije,
            // kod jave postoji checked exceptions, kod C++ postoji exception specifications, kod C#-a izgleda nista osim XML dokumentacije)
            //
            try {
                WriteFile(destFileName, compressedBytes);
            }
            catch (IOException)
            {
                throw new MyException();
            }

        }

        private void Compress(string srcFileName, out byte[] compressedBytes)
        {
            compressedBytes = null;
            // precodintions
            if (srcFileName == null) throw new ArgumentException();

            Console.WriteLine("Compressing file :   {0} ", srcFileName);
            compressedBytes = new byte[] { 1, 2, 3, 4 };
        }

        public void WriteFile(string destFileName, byte[] compressedBytes)
        {
            // precodintions
            if (destFileName == null) throw new ArgumentException();
            if (compressedBytes == null) throw new ArgumentException();

            // slicno kao kod return value, simulira write metodu
            if (destFileName.EndsWith("log")) throw new IOException();

            Console.WriteLine("Writing file :       {0} ", destFileName);
        }
        
        public bool Backup1()
        {
            try
            {                
                CreateBackup(@"D:\t1.log", @"D:\b1.log");                 
                CreateBackup(@"D:\t2.txt", @"D:\b2.bkp");
                CreateBackup(@"D:\t3.txt", @"D:\b3.bkp");

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Backup2()
        {
            bool b = false;
            try { CreateBackup(@"D:\t1.log", @"D:\b1.log"); b = true; } catch { }
            try { CreateBackup(@"D:\t2.txt", @"D:\b2.bkp"); b = true; } catch { }
            try { CreateBackup(@"D:\t3.txt", @"D:\b3.bkp"); b = true; } catch { }

            return b;
        }
    }

    public class MyException : Exception { }

}
 
Odgovor na temu

lermi
Freelancer

Član broj: 230692
Poruke: 62
*.crnagora.net.



+5 Profil

icon Re: Obrada gresaka : exception ili return message29.10.2010. u 11:13 - pre 163 meseci
Nekad je greška sastavni dio funkcije programskog koda (ili kako se to već kaže). Lijep primjer za ovo je brojanje stavki u nizu u Pythonu.

Code:

slova = ('a', 'b','b', 'c','d', 'd','d', 'd', 'f')
prebrojano = {}

for slovo in slova:
    try:
            prebrojano[slovo] += 1
    except KeyError:
            prebrojano[slovo] = 1

print 'Broj slova:', prebrojano

>>> 
Broj slova: {'a': 1, 'c': 1, 'b': 2, 'd': 4, 'f': 1}
>>> 


 
Odgovor na temu

[es] :: Art of Programming :: Obrada gresaka : exception ili return message
(TOP topic, by vlaiv)

[ Pregleda: 7883 | Odgovora: 19 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.