[java] waarom niet alleen exception gebruiken

Pagina: 1
Acties:
  • 254 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 18-08 18:12
Ik ben nu al een tijdje bezig met exceptions en na een tijdje vraag ik mij af waarom ik nog specifieke exceptions zou gooien en niet alleen Exception.

Dus bijv:
code:
1
2
3
4
5
6
try {
    // Doe code welke de bijv. deze exceptions kan gooien: ClassNotFoundException en java.sql.SQLException
} catch (Exception e) {
    // Echter hier vangen de alleen Exception af
    e.printStackTrace(e);
}


Nu krijg ik alsnog netjes de foutmelding weergegeven die ik kan gebruiken om te debuggen.
En nu hoef ik heel wat minder exceptions te catchen in al me code.

Zie ik hier iets essentieels over het hoofd?

Acties:
  • 0 Henk 'm!

Verwijderd

Subclasses van Exceptions gebruik je voor verschillende klassen van fouten. Misschien heb je een categorie fouten waarbij je het programma meteen moet laten crashen. Misschien heb je een categorie fouten waarbij bepaalde onderdelen uitgeschakeld worden. Misschien heb je een categorie fouten waarbij slechts een melding wordt geprint... je kan het zo ver opdelen als je zelf wilt.

Acties:
  • 0 Henk 'm!

  • Reptile209
  • Registratie: Juni 2001
  • Laatst online: 13:25

Reptile209

- gers -

Tijdens het debuggen maakt het in principe inderdaad geen klap uit welke exception je hebt, alleen dat er eentje optreedt. Voor het kunnen hergebruiken van je code in grotere projecten en voor "release" versies slaat dit natuurlijk nergens op. Dan krijg je van die programma's die alleen iets roepen als: "An error occurred!" waar je als eindgebruiker natuurlijk geen ruk aan hebt. Als de exceptie door zijn type al vertelt wat er ongeveer aan de hand is, kan je veel adequater afhandelen (bepaalde dingen negeren, actie op anderen, crash bij grote ellende :))
Kortom: het mechanisme bestaat niet voor niks, gebruik het zoals je wil in je eigen werk maar besef wat er gebeurt als een ander er mee moet kunnen werken.

[ Voor 14% gewijzigd door Reptile209 op 07-12-2007 21:00 ]

Zo scherp als een voetbal!


Acties:
  • 0 Henk 'm!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 13:16

NetForce1

(inspiratie == 0) -> true

Jazeker, je kunt dan bijvoorbeeld een speciale foutmelding tonen aan de gebruiker met tips hoe het de fout in de toekomst te vermijden is (de vraag is wel of je design wel goed is als dat nodig is, maar het kan soms nodig zijn). Of bijv. de gebruiker in laten loggen als je een 401 error terug krijgt van een website, of de boel automatisch weer recht trekken als dat mogelijk is.
Zonder de speciale typen excepties weet je niet wat er precies fout is gegaan en wordt bovenstaand verhaal een stuk lastiger (dan zou je allerlei dirty tricks moeten doen met de message van de exception, en dat wil je echt niet).

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Acties:
  • 0 Henk 'm!

Verwijderd

NetForce1 schreef op vrijdag 07 december 2007 @ 20:59:
Jazeker, je kunt dan bijvoorbeeld een speciale foutmelding tonen aan de gebruiker met tips hoe het de fout in de toekomst te vermijden is (de vraag is wel of je design wel goed is als dat nodig is, maar het kan soms nodig zijn). Of bijv. de gebruiker in laten loggen als je een 401 error terug krijgt van een website, of de boel automatisch weer recht trekken als dat mogelijk is.
De vraag is natuurlijk of je een verwachte fout (een errorcode is een geldige respons van een server) wel in een Exception moet opvangen.

Acties:
  • 0 Henk 'm!

  • NetForce1
  • Registratie: November 2001
  • Laatst online: 13:16

NetForce1

(inspiratie == 0) -> true

Verwijderd schreef op vrijdag 07 december 2007 @ 21:03:
[...]

De vraag is natuurlijk of je een verwachte fout (een errorcode is een geldige respons van een server) wel in een Exception moet opvangen.
Idd, maar als je het over bijv. webservices hebt is er eigenlijk geen ander mechanisme. Mits je natuurlijk tegen de interfaces van die webservices aan programmeert en niet zelf met soap gaat lopen zooien.

De wereld ligt aan je voeten. Je moet alleen diep genoeg willen bukken...
"Wie geen fouten maakt maakt meestal niets!"


Acties:
  • 0 Henk 'm!

  • verytallman
  • Registratie: Augustus 2001
  • Laatst online: 18-08 18:12
De programma's die ik schrijf gebruik ik alleen zelf. Maar ik snap de redenatie wel; als je weet welke exception komt, kan je de gebruiker beter vertellen wat er fout ging.

Alleen wordt ik een beetje gek van het aantal exceptions wat elke keer kan komen en het aantal regels code wat het me kost.

Acties:
  • 0 Henk 'm!

Verwijderd

Een exception gooien is ook niet echt tof. Het mooist is om eerst via de "normale" manieren na te gaan of iets misschien mis kan gaan. Als alle gewone controles goed gaan, kan er nog steeds iets fout gaan. Iemand kan tijdens het downloaden van een bestand de netwerkkabel doorknippen. Dat is eigenlijk waar die exceptions voor zijn. Je kunt niet alles voorzien.

En het klopt dat sommige stukken productiecode bol staan van controles en exception handling. Dat is nu eenmaal de aard van bijvoorbeeld client/server-software.

[ Voor 18% gewijzigd door Verwijderd op 07-12-2007 21:49 ]


Acties:
  • 0 Henk 'm!

  • Hydra
  • Registratie: September 2000
  • Laatst online: 21-08 17:09
Ik weet niet zeker of de OP nou bedoelt dat hij zich afvraagt of hij specifieke exceptions moet 'gooien' of specifieke exceptions moet afvangen.

Want in een gewone applicatie wil je volgens mij geen exceptions gooien in de zin van dat de JVM met een stackdump komt, daar wil je gewoon een mooi "oops" errorschermpje tonen. En dus het 2e punt, je vangt specifieke exceptions omdat deze vaak extra info hebben. Zo kan een ConnectionException je bijvoorbeeld melden dat er niet op een bepaalde poort geluisterd wordt, of een hostname niet resolved. Allemaal info die voor een gebruiker enorm nuttig is.
verytallman schreef op vrijdag 07 december 2007 @ 21:14:
De programma's die ik schrijf gebruik ik alleen zelf. Maar ik snap de redenatie wel; als je weet welke exception komt, kan je de gebruiker beter vertellen wat er fout ging.

Alleen wordt ik een beetje gek van het aantal exceptions wat elke keer kan komen en het aantal regels code wat het me kost.
Beetje fatsoenlijke IDE kan je flink helpen met het maken van try-catch blokken.

[ Voor 29% gewijzigd door Hydra op 07-12-2007 22:38 ]

https://niels.nu


Acties:
  • 0 Henk 'm!

  • YopY
  • Registratie: September 2003
  • Laatst online: 13-07 01:14
In de meeste gevallen is het enige verschil tussen exceptions de naam die ze hebben - SQLException, ConcurrentModificationException, NullPointerException, etc. Een deel hiervan, zoals de NullPointerException, geeft echter geen bericht terug - dus je hebt geen flauw idee wat voor een exception het was, alleen dat 'ie er is, en op welke regel die er was. Je zou op zich met gewoon losse Exceptions kunnen werken, maar vroeg of laat ga je er dan zelf iets aan toevoegen dat het type exception ook in het exceptionbericht zichtbaar is.

Uiteindelijk zijn er echter maar twee types Exception: exceptions die je af kunt vangen en waarmee het programma gewoon verder kan gaan, en exceptions waarvan het hele programma op zijn spreekwoordelijke bek gaat waarbij je afvangen kunt zoveel je wilt, maar het programma is toch naar z'n grootje.

Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

YopY schreef op zaterdag 08 december 2007 @ 20:15:
Een deel hiervan, zoals de NullPointerException, geeft echter geen bericht terug - dus je hebt geen flauw idee wat voor een exception het was, alleen dat 'ie er is, en op welke regel die er was.
Als je de Sun JDK gebruikt, dan zijn er heel wat classes die zelf expliciet een NullPointerException, met verklarende boodschap, gooien.
verytallman schreef op vrijdag 07 december 2007 @ 20:46:
Ik ben nu al een tijdje bezig met exceptions en na een tijdje vraag ik mij af waarom ik nog specifieke exceptions zou gooien en niet alleen Exception.
Omdat op niet alle gebeurtenissen op dezelfde manier gereageerd kan/moet worden. Als je een programma voor gebruikers schrijft, dan zal je het programma de enige keer moeten afsluiten met 'rapporteer deze error alstublieft aan prutser@bedrijf.com', terwijl je de gebruiker de andere keer wilt vertellen dat hij een geldige filename in moet voeren.
En nu hoef ik heel wat minder exceptions te catchen in al me code.
Met 'catch (Exception e)' vang je alle soorten excepties, ook als je verschillende soorten gooit.

offtopic:
Het is mijn code.

[ Voor 48% gewijzigd door Confusion op 08-12-2007 20:33 ]

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Robtimus
  • Registratie: November 2002
  • Laatst online: 20:00

Robtimus

me Robtimus no like you

YopY schreef op zaterdag 08 december 2007 @ 20:15:
In de meeste gevallen is het enige verschil tussen exceptions de naam die ze hebben - SQLException, ConcurrentModificationException, NullPointerException, etc. Een deel hiervan, zoals de NullPointerException, geeft echter geen bericht terug - dus je hebt geen flauw idee wat voor een exception het was, alleen dat 'ie er is, en op welke regel die er was. Je zou op zich met gewoon losse Exceptions kunnen werken, maar vroeg of laat ga je er dan zelf iets aan toevoegen dat het type exception ook in het exceptionbericht zichtbaar is.
NullPointerException en een groot aantal andere subclasses van RuntimeException, zoals IllegalArgumentException, hoor je helemaal niet af te vangen - je hoort ze te voorkomen. De API hoort je te vertellen wanneer ze voor kunnen komen, en daarmee kun je ze als programmeur vermijden.

Als deze execptions komen door foutieve user input dan hoort deze user input vantevoren gecontroleerd te worden, voordat deze exceptions ook maar kunnen voorkomen.

Er is hier trouwens een grote uitzondering op (helaas): NumberFormatException. Er is geen goede manier om te controleren of een string een geldige integer / long / double etc bevat zonder dat deze exception meteen gethrowd wordt.

Just my 2 cents.

More than meets the eye
There is no I in TEAM... but there is ME
system specs


Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Java:
1
2
3
4
5
if (string.matches("^\\d+$")) {
    // String bevat louter nummers.
} else {
    // String bevat niet louter nummers.
}

Voor de rest ben ik het volkomen mee eens dat je RuntimeExceptions niet handmatig hoort af te vangen maar dat je de code gewoon perfect daarop moet afstemmen. Over alle andere Exceptions kan ik kort zijn: het hangt af van de eisen dat gesteld wordt aan de uiteindelijke programmatuur. Er kunnen verschillen zitten tussen een wegwerphobbyprogrammaatje en een enterprise webapp.

Acties:
  • 0 Henk 'm!

Verwijderd

Mij is bij het vak Datastructuren verteld dat je alleen Exceptions wilt gooien als je anders, om de invoer te controleren, de hele class opnieuw zou moeten schrijven in de aanroepende code.

Maar aangezien Exceptions gooien nogal duur is vraag ik me af: is het mogelijk om alle Exceptions te vervangen door een controle? Of moet je sommige dingen gewoon proberen om te weten of het fout gaat? Die NumberFormatException kan je bijvoorbeeld voorkomen door een static methode in de wrapper classes aan te maken die met weinig extra code controleert of een bepaalde String een geldige <insert_type> is.

In m'n eigengemaakte types doe ik dat in ieder geval wel altijd op die manier. Dan kan je alsnog een Exception gooien als je zonder de check een ongeldige instantie van het type wilt maken, maar die is dan altijd te vermijden door vooraf te controleren.

Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Verwijderd schreef op zondag 09 december 2007 @ 14:45:
Maar aangezien Exceptions gooien nogal duur is vraag ik me af: is het mogelijk om alle Exceptions te vervangen door een controle?
Dat is dus exact waar ik op doel met het niet afvangen van RuntimeExceptions (unchecked exceptions). Een RuntimeException wordt in principe alleen geworpen als er een fout in de code logica zit, niet in de invoer of uitvoer. De meeste van de overige Excepties (checked exceptions) kun je moeilijk controleren vanuit de code en het vooraf controleren is in feite overbodig zolang je code en omgeving prima in orde is.

[ Voor 3% gewijzigd door BalusC op 09-12-2007 14:51 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Nouja, NullPointers bijvoorbeeld. Je kan makkelijk met een ifje controleren of iets null is. Zolang het geen bug is, kan je daarmee een dure stacktrace voorkomen. Als het natuurlijk nooit mag voorkomen, dan laat je je programma gewoon hard crashen met de melding dat je de stacktrace naar a@b.com moet mailen. (in beta-versies tenminste ;))

Acties:
  • 0 Henk 'm!

  • dawuss
  • Registratie: Maart 2001
  • Laatst online: 10-07 16:50

dawuss

gadgeteer

Een Exception is eigenlijk letterlijk wat de naam al zegt: een uitzondering op de normale gang van zaken binnen je programma. Uiteraard kunnen er meerdere soorten van dat soort afwijkingen bestaan en daar wil je wellicht op verschillende manieren mee om gaan. (bij netwerk applicaties kan bijvoorbeeld de verbinding lokaal stuk gaan, maar de peer aan de andere kant kan ook overlijden, om maar iets te noemen).

Ik kan me trouwens niet geheel vinden in de algehele aversie tegen excepties. In veel gevallen maken ze het namelijk mogelijk om de afhandeling daar te doen waar die het meest logisch is. Ik vind

Java:
1
2
3
4
5
6
7
8
9
10
try {
  doSomethingThatMayGoWrongInANumberOfDifferentWays(withThisParameter);
  continueWorking(withThisParameter);
}
catch(IMadeABooBooException e) {
  tellUserIMadeABooBoo();
}
catch(ParameterWentBroken e) {
  doSomethingElse(withThisParameter);
}


dan ook een heel stuk netter dan dit:

Java:
1
2
3
4
5
6
7
8
9
10
int retval = doSomethingThatMayGoWrongInANumberOfDifferentWays(withThisParameter);
if(retval == OK) {
  continueWorking(withThisParameter);
}
else if(retval == I_MADE_A_BOOBOO) {
  tellUserIMadeABooBoo();
}
else if(retval == PARAMETER_WENT_BROKEN) {
  doSomethingElse(withThisParameter);
}


of iets soortgelijks. Een eventuele error afvangen in de methode waar hij optreedt is vaak niet wenselijk of niet mogelijk (bij gesloten library classes).

Om het nog maar niet te hebben over nested try/catch blokken:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
try {
  while(cond) {
    try {
      doSomething();
    }
    catch(NonFatalException e) {
      report(e);
    }
  }
}
catch(FatalError e) {
  reportAndDie(e);
}


Natuurlijk is het zwaar en is het niet bedoeld om deel uit te maken van je normale flow, maar kwalijk en schadelijk is het in mijn ogen niet. De opoffering performance vs. maintainability is er in ieder geval eentje die ik graag maak :)

[ Voor 3% gewijzigd door dawuss op 09-12-2007 15:33 ]

micheljansen.org
Fulltime Verslaafde Commandline Fetisjist ©


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Verwijderd schreef op zondag 09 december 2007 @ 14:45:
Maar aangezien Exceptions gooien nogal duur is [..]
Premature optimization is the root of all evil. Als blijkt dat het een performance bottleneck is, dan vervang ik het alsnog wel door een test. De belangrijkste reden om het gebruik van Exceptions te vermijden, is als het de code minder begrijpelijk maakt.
is het mogelijk om alle Exceptions te vervangen door een controle?
Niet alle exceptions die vanuit gebruikte libraries gegooid worden kan je voorkomen. NumberFormatException is eenvoudig te voorkomen; FileNotFoundException is al iets lastiger (en betekent het deels herimplementeren van de library die je gebruikt); SocketTimeOutException is zo lastig dat vrijwel niemand er aan zal beginnen.
dawuss schreef op zondag 09 december 2007 @ 15:31:
Ik kan me trouwens niet geheel vinden in de algehele aversie tegen excepties. In veel gevallen maken ze het namelijk mogelijk om de afhandeling daar te doen waar die het meest logisch is.

Ik vind

Java:
1
2
3
4
5
6
7
8
9
10
try {
  doSomethingThatMayGoWrongInANumberOfDifferentWays(withThisParameter);
  continueWorking(withThisParameter);
}
catch(IMadeABooBooException e) {
  tellUserIMadeABooBoo();
}
catch(ParameterWentBroken e) {
  doSomethingElse(withThisParameter);
}


dan ook een heel stuk netter dan dit:

Java:
1
2
3
4
5
6
7
8
9
10
int retval = doSomethingThatMayGoWrongInANumberOfDifferentWays(withThisParameter);
if(retval == OK) {
  continueWorking(withThisParameter);
}
else if(retval == I_MADE_A_BOOBOO) {
  tellUserIMadeABooBoo();
}
else if(retval == PARAMETER_WENT_BROKEN) {
  doSomethingElse(withThisParameter);
}


of iets soortgelijks.
Maar dat is een vals dilemma, want je staat meestal niet voor de keuze uit die twee mogelijkheden. Om een aantal mogelijkheden te noemen:
1) Je wilt geen methode 'doSomethingThatMayGoWrongInANumberOfDifferentWays(withThisParameter);', maar die methode opsplitsen in siverse kleinere methoden, die allemaal maar op 1 manier fout kunnen gaan.
2) Dat jij die code netter vindt, betekent niet dat ik die code ook netter vindt. Een exception is eigenlijk niets anders dan een globale vlag. Met welke syntactische constructie je daar op controleert is mij om het even.
3) Hoezo handel je de fout in de eerste code op 'een andere plek' af dan in de tweede code?
4) De plaats die de exceptions opvangt en afhandelt schuift snel ver naar boven, waardoor die moeilijk te vinden wordt tijdens het debuggen en waardoor die methode een verzameling onsamenhangende verantwoordelijkheden op zich neemt.
5) Excepties geven maar beperkte informatie en staan bijvoorbeeld het teruggeven van deelresultaten met statuscode niet toe.

[ Voor 54% gewijzigd door Confusion op 09-12-2007 15:44 ]

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

Verwijderd

De belangrijkste reden om het gebruik van Exceptions te vermijden, is dat het de code minder begrijpelijk maakt
Dat snap ik dus niet, waarom maakt het gooien van exceptions je code minder begrijpelijk? Zie dawuss' reply.

Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Verwijderd schreef op zondag 09 december 2007 @ 15:39:
[...]
Dat snap ik dus niet, waarom maakt het gooien van exceptions je code minder begrijpelijk? Zie dawuss' reply.
Zie mijn edit :). Niet 'dat', maar 'als'. Niettemin is dat een val waar je makkelijk intrapt: de afhandeling van de fout komt gemakkelijk op een onlogische plaats terecht, die bovendien niet de verantwoordelijkheid voor het afhandelen van die fout zou moeten hebben. Het zelf vaak gooien van excepties werkt het produceren van slechte code in de hand.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09:39

Janoz

Moderator Devschuur®

!litemod

Mwah, dat ben ik niet helemaal met je eens. Proberen het gooien van exceptions te vermijden zorgt er imho juist voor dat fouten op een verkeerde plek afgehandeld worden. Wat ik vaak in mijn code doe is slechts een deel van het probleem oplossen en een nieuwe exception gooien (of de oude doorgooien).

Verder ben ik geheel met dawuss. Ik snap niet wat er tegen exceptions is.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • dawuss
  • Registratie: Maart 2001
  • Laatst online: 10-07 16:50

dawuss

gadgeteer

Confusion schreef op zondag 09 december 2007 @ 15:34:
Maar dat is een vals dilemma, want je staat meestal niet voor de keuze uit die twee mogelijkheden. Om een aantal mogelijkheden te noemen:
Volgens mij zijn we helemaal niet zo oneens :) Mijn voorbeelden zijn misschien niet illustratief genoeg van wat ik bedoel.
1) Je wilt geen methode 'doSomethingThatMayGoWrongInANumberOfDifferentWays(withThisParameter);', maar die methode opsplitsen in siverse kleinere methoden, die allemaal maar op 1 manier fout kunnen gaan.
Als dat mogelijk is heeft dat natuurlijk de voorkeur, maar dingen als het opzetten van een protocolverbinding oid kunnen op veel plaatsen mis gaan en dan heb je de keuze tussen ofwel van de "gebruiker" (van je library) vragen de methoden die elk mis kunnen gaan (openSocket(); connectToServer(); doHandshake();) in de juiste volgorde aan te roepen, ofwel conveniently een connect() aan te bieden die verschillende excepties kan gooien (beetje gammel voorbeeld, maar ik hoop dat duidelijk is wat ik bedoel :))
2) Dat jij die code netter vindt, betekent niet dat ik die code ook netter vindt. Een exception is eigenlijk niets anders dan een globale vlag. Met welke syntactische constructie je daar op controleert is mij om het even.
Tsja, zo voeren we natuurlijk geen discussie :P Ik vind het wel degelijk prettig om de "natuurlijke" flow te kunnen scheiden van de "foutafhandelende" flow. Het mooie aan excepties is dat ze je er niet toe dwingen dat te doen, het kan prima anders:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try {
  openDoor();
  walkThrough();
  closeDoor();
}
catch(DoorStuckException e) {
  // do something
}
catch{TooLittleSpaceException e) {
  // do something else
}
catch(DoorWontCloseException e) {
  // panic
}

return;


is analoog aan

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
try {
  openDoor();
}
catch(DoorStuckException e) {
  // do something
}

try {
  walkThrough();
}
catch{TooLittleSpaceException e) {
  // do something else
}


try {
  closeDoor();
}
catch(DoorWontCloseException e) {
  // panic
}


Meestal zou ik voor de eerste optie gaan, omdat daar dus de normale flow gescheiden is van alternatieve flows, maar er zijn best situaties waarin de tweede mooier / beter is. Het is in ieder geval net zo goed mogelijk om het zo op te lossen.
3) Hoezo handel je de fout in de eerste code op 'een andere plek' af dan in de tweede code?
Dat is in dit voorbeeld niet zo, maar je noemt zelf al library functions als een voorbeeld waarbij dat wel het geval is :)
4) De plaats die de exceptions opvangt en afhandelt schuift snel ver naar boven, waardoor die moeilijk te vinden wordt tijdens het debuggen en waardoor die methode een verzameling onsamenhangende verantwoordelijkheden op zich neemt.
Dat is gewoon een kwestie van tussentijds ook al excepties afvangen en ze niet doorgooien naarboven als ze afgevangen horen te worden.
5) Excepties geven maar beperkte informatie en staan bijvoorbeeld het teruggeven van deelresultaten met statuscode niet toe.
Eens. Natuurlijk is daar wel omheen te werken (bijvoorbeeld door ipv met return values met references te werken), maar mooi is het niet :)

[ Voor 5% gewijzigd door dawuss op 09-12-2007 16:05 ]

micheljansen.org
Fulltime Verslaafde Commandline Fetisjist ©


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09:39

Janoz

Moderator Devschuur®

!litemod

Confusion schreef op zondag 09 december 2007 @ 15:34:
Maar dat is een vals dilemma, want je staat meestal niet voor de keuze uit die twee mogelijkheden. Om een aantal mogelijkheden te noemen:
1) Je wilt geen methode 'doSomethingThatMayGoWrongInANumberOfDifferentWays(withThisParameter);', maar die methode opsplitsen in siverse kleinere methoden, die allemaal maar op 1 manier fout kunnen gaan.
Sommige dingen kunnen inherent op meerdere manieren fout gaan. Een methode die een resource oproept via een http request kan falen omdat de resource niet beschikbaar is, de server niet beschikbaar is of het netwerk niet beschikbaar is. Elk van die dingen zou anders afgehandeld kunnen worden en het is onmogelijk om dat in verschillende deel methoden op te splitsen.
2) Dat jij die code netter vindt, betekent niet dat ik die code ook netter vindt. Een exception is eigenlijk niets anders dan een globale vlag. Met welke syntactische constructie je daar op controleert is mij om het even.
Een exception is wel ietsje meer dan een globale vlag. Het is een manier om een ander (exceptioneel) executie pad uit te voeren. Verder geeft het, ook in de code en voor de andere ontwikkelaars, aan dat er een exeptioneel iets gebeurt. Tot slot is goede naamgeving van je excepties en de bijbehorende javadoc een heel stuk leesbaarder dan integer return codes.
3) Hoezo handel je de fout in de eerste code op 'een andere plek' af dan in de tweede code?
Dat wordt vooral duidelijk wanneer je meerdere methoden onder elkaar zet. In het if gevalletje wordt het een onnoemelijk diep genest zootje.
4) De plaats die de exceptions opvangt en afhandelt schuift snel ver naar boven, waardoor die moeilijk te vinden wordt tijdens het debuggen en waardoor die methode een verzameling onsamenhangende verantwoordelijkheden op zich neemt.
Exceptions zijn niet moeilijk te vinden bij het debuggen. Ze geven een volledige stacktrace van waar ze opgeroepen zijn en vaak zit er ook nog de stacktrace van een veroorzakende exception bij. Verder is het natuurlijk wel van belang dat de ontwikkelaar zijn exceptions op het juiste niveau afhandeld, of wrapt in een logischere exception.
5) Excepties geven maar beperkte informatie en staan bijvoorbeeld het teruggeven van deelresultaten met statuscode niet toe.
Als je deelresultaten terug wilt geven dan zul je geen exception moeten gooien. Als je denkt dat het nog te recoveren is dan moet je dat doen. Uiteindelijk geef je dan gewoon een 'normaal' resultaat terug met eventueel wat extra info, maar dat zul je dan gewoon in dat resultaat op moeten lossen.

Tot slot houd niemand je tegen om een eigen exception te implementeren waarin je wel je gegevens kwijt kunt die je graag bij je exception wil hebben.


Ik proef uit je reactie dat je eerder het C type ontwikkelaar bent. Daar is natuurlijk niks mis mee, maar er zijn goede redenen geweest om af te stappen van het 'geef een status code als return waarde en geef echte resultaten maar terug als pass by ref parameters' paradigma.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Nu online
Er wordt (vooral in het begin van de thread) gesuggereerd dat exceptions alleen maar dienen om informatie te geven aan de exception handler, en dat je dus best alleen maar Exception zou kunnen gooien omdat elke exception toch op dezelfde plek afgehandeld gaat worden.

De grap is nu juist dat dat níet de bedoeling is. In een catch clause kun je matchen op het type van de exception, en daarmee kunnen verschillende soorten exceptions die in dezelfde methode optreden in verschillende methoden afgehandeld worden. Het is gebruikelijk dat een methode specifieke exceptions die door de methode zelf veroorzaakt worden zelf afhandelt, maar meer algemene exceptions (denk aan gebrek aan geheugen of een security exception) aan hoger gelegen code overlaat.

Dáárom zijn verschillende types voor exceptions nuttig en dáárom moet je bijna nergens (behalve misschien op het hoogste nivo in je applicatie) een constructie als catch (Exception e) schrijven.

Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

dawuss schreef op zondag 09 december 2007 @ 16:01:
Als dat mogelijk is heeft dat natuurlijk de voorkeur, maar dingen als het opzetten van een protocolverbinding oid kunnen op veel plaatsen mis gaan [..]
Natuurlijk, maar de aversie tegen Exceptions is ontstaan door overmatig en verkeerd gebruik er van. Ik probeer aan te geven dat ik de aversie prima begrijp, ondanks de goede redenen en manieren zijn om Excepties te gebruiken, zoals in het voorbeeld dat je geeft.
Tsja, zo voeren we natuurlijk geen discussie :P
Dat is ook een beetje mijn punt: aangeven dat een esthetische overweging niet relevant is, omdat smaken verschillen en 'het mooiste' volgens mij niet altijd samenvalt met wat het overzichtelijkst/best te begrijpen is.
Dat is gewoon een kwestie van tussentijds ook al excepties afvangen en ze niet doorgooien naarboven als ze afgevangen horen te worden.
En dat is precies het probleem, want het is zó verleidelijk om de afhandeling uit te besteden naar 'boven'...
Janoz schreef op zondag 09 december 2007 @ 16:03:
Verder geeft het, ook in de code en voor de andere ontwikkelaars, aan dat er een exeptioneel iets gebeurt.
Tjah, die dingen heten wel 'Exception', maar als je ze zelf gooit, met het doel ze af te vangen, dan gebeurt er niet iets dat je niet hebt voorzien. Hoe 'exceptioneel' is een SocketTimeOutException?
Tot slot is goede naamgeving van je excepties en de bijbehorende javadoc een heel stuk leesbaarder dan integer return codes.
Gelukkig zijn er heel wat manieren om resultaten te coderen met constantes of enums, zodat de code goed te begrijpen is :). De meerwaarde van een exceptie zie ik op dat vlak niet en juist daar heb ik er mijn neus weleens tegen gestoten dat iemand excepties gooide als onderdeel van de 'normale' flow.
Dat wordt vooral duidelijk wanneer je meerdere methoden onder elkaar zet. In het if gevalletje wordt het een onnoemelijk diep genest zootje.
Aan de andere kant is het met een exceptie rond een reeks statements soms knap moeilijk om te bepalen welke actie er moeten worden ondernomen, aangezien je moet achterhalen welke state er allemaal al gezet was. Als exceptie-blokken nou transactioneel konden zijn...
Exceptions zijn niet moeilijk te vinden bij het debuggen. Ze geven een volledige stacktrace van waar ze opgeroepen zijn en vaak zit er ook nog de stacktrace van een veroorzakende exception bij.
Ik doel op het geval als de exceptie op een hoog niveau wordt afgevangen, maar niet goed afgehandeld wordt. De stacktrace wordt dan vaak niet standaard geprint (tenminste, alle applicaties die ik ken loggen dan op DEBUG van alles, maar niet de complete stacktraces van exceptions die afgehandeld worden).
Verder is het natuurlijk wel van belang dat de ontwikkelaar zijn exceptions op het juiste niveau afhandeld, of wrapt in een logischere exception.
En de vraag is: gebeurt dat in de praktijk ook?
Tot slot houd niemand je tegen om een eigen exception te implementeren waarin je wel je gegevens kwijt kunt die je graag bij je exception wil hebben.
Dat mag je dan wel heel expliciet documenteren en dan nog denk ik dat een volgende programmeur er niet blij van wordt.
Ik proef uit je reactie dat je eerder het C type ontwikkelaar bent.
Zou kunnen, maar mijn inspiratie is het aantal keren dat is tengevolge van onhandig gebruik van exceptions lang aan het debuggen ben geweest. :)

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09:39

Janoz

Moderator Devschuur®

!litemod

Confusion schreef op zondag 09 december 2007 @ 21:03:
Tjah, die dingen heten wel 'Exception', maar als je ze zelf gooit, met het doel ze af te vangen, dan gebeurt er niet iets dat je niet hebt voorzien. Hoe 'exceptioneel' is een SocketTimeOutException?
Dus als je een exception vangt dan heb je hem wel voorzien dus moet je hem eigenlijk niet meer middels een exception implementeren?

Mijn definitie van 'exceptioneel' is iets dat afwijkt van de nromale flow (en dan bedoel ik niet alleen de happy flow). Uiteraard ga ik niet userinput valideren middels exceptions (muv parseInt, maar vaak zit er al een masker op de input), maar voor een fout in de configuratie van een applicatie heb ik een leuke ConfigurationException gemaakt die, tijdens de initialisatiefase van die (JSE) applicatie gegooid kan worden (met de onderliggende exception als cause).
Gelukkig zijn er heel wat manieren om resultaten te coderen met constantes of enums, zodat de code goed te begrijpen is :). De meerwaarde van een exceptie zie ik op dat vlak niet en juist daar heb ik er mijn neus weleens tegen gestoten dat iemand excepties gooide als onderdeel van de 'normale' flow.
imho hoort een methode gewoon het object terug te geven waar je hem om vraagt, en niet een statuscode die aangeeft dat die ene parameter die je hem meegeeft nu gevuld is met het resultaat.
Aan de andere kant is het met een exceptie rond een reeks statements soms knap moeilijk om te bepalen welke actie er moeten worden ondernomen, aangezien je moet achterhalen welke state er allemaal al gezet was. Als exceptie-blokken nou transactioneel konden zijn...
Veel acties kunnen al worden ondernomen in de methode waar de exception voor het eerst optreed. Verder vraag ik me af of dat afhandelen daadwerkelijk duidelijker wordt wanneer het verstopt zit in een enorm geneste if boom van statuschecks. Transactie specifieke dingen kun je keurig op het niveau afhandelen waarop je ook met die transactie bezig bent, zonder dat je daar de exception daadwerkelijk af hoeft te handelen. Die kun je immers doorgooien, of je maakt een finaly blok. Op die manier kun je op elk niveau in de bijbehorende stack keurig je zaakjes opruimen en daar valt inderdaad ook een eventuele rollback onder..
Ik doel op het geval als de exceptie op een hoog niveau wordt afgevangen, maar niet goed afgehandeld wordt. De stacktrace wordt dan vaak niet standaard geprint (tenminste, alle applicaties die ik ken loggen dan op DEBUG van alles, maar niet de complete stacktraces van exceptions die afgehandeld worden).
Alle log implementaties hebben bij hun log methode ook een extra parameter Throwable waardoor er een keurig stacktrace van die throwable, maar ook zijn causes in de log terecht kan komen. Het lijkt me dan ook dat je beter je log aanroepen of configuratie aan kunt passen dan de schuld op exceptions schuiven.
En de vraag is: gebeurt dat in de praktijk ook?
Ja. In principe is dat natuurlijk het hele blackbox concept van OO. Voor de buitenkant maakt het niks uit hoe alles binnenin gebeurt. Vandaar ook het wrappen. Dan zijn je exceptions ook implementatie onafhankelijk. Als je bijvoorbeeld een resource class hebt die onafhankelijk is van de gegevens bron (erg academisch voorbeeltje, ik weet het) dan laat je die een ResourceException gooien en niet een SQLException wanneer het een database bron gebruikt en een IOException wanneer het een file of netwerkbron gebruikt.
Dat mag je dan wel heel expliciet documenteren en dan nog denk ik dat een volgende programmeur er niet blij van wordt.
En dat is anders dan je status enums of magic constants omdat? Ikzelf zou het ook niet zomaar doen, maar het was een reactie op iets waarvan werd beweerd dat het niet mogelijk was terwijl dit wel het geval is. Daarnaast is het uiteraard niet de bedoeling om zomaar buisness informatie in die Exception op te slaan. Het ging hier dan ook specifiek om 'extra informatie die ik nodig heb voor het verwerken van de exceptie'. Ik kan me goed voorstellen dat je graag een nummer toe wilt voegen voor je eigen administratie en/of bugtracking systeem.
Zou kunnen, maar mijn inspiratie is het aantal keren dat is tengevolge van onhandig gebruik van exceptions lang aan het debuggen ben geweest. :)
uiteraard kun je exceptions ook onhandig gebruiken en dat lijkt mij inderdaad ook niet de bedoeling, maar hier kan ik natuurlijk niks over zeggen omdat ik die specifieke implementatie niet ken.

Zou je anders een stukje voorbeeld kunnen geven van wat je daar tegen gekomen bent en waarom je dat een lastige constructie vond?

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Janoz schreef op maandag 10 december 2007 @ 08:43:
Mijn definitie van 'exceptioneel' is iets dat afwijkt van de nromale flow (en dan bedoel ik niet alleen de happy flow). Uiteraard ga ik niet userinput valideren middels exceptions (muv parseInt, maar vaak zit er al een masker op de input), maar [knip voorbeeld]
Ik denk niet dat je duidelijk kan definieren wanneer iets 'exceptioneel' is en wanneer niet. Waar jij zegt 'uiteraard', daar denken (of denken ze juist niet?) talloze anderen 'handig, ik gooi gewoon een exceptie', dan kan ik het 'ergens' afvangen.

[quote]imho hoort een methode gewoon het object terug te geven waar je hem om vraagt, en niet een statuscode die aangeeft dat die ene parameter die je hem meegeeft nu gevuld is met het resultaat.[/qquote]
Over het algemeen gebruik ik dan een object, dat resultaatcode en resultaat, met eventueel nog wat meta-informatie, wrapped.
Veel acties kunnen al worden ondernomen in de methode waar de exception voor het eerst optreed. Verder vraag ik me af of dat afhandelen daadwerkelijk duidelijker wordt wanneer het verstopt zit in een enorm geneste if boom van statuschecks.
Zoals ik in mijn eerste reactie op dawuss zei: dat is een vals dilemma. Het is niet òf exceptions, òf een enorme boom if's. Sterker nog: je kan zelfs zonder if statements.
Transactie specifieke dingen kun je keurig op het niveau afhandelen waarop je ook met die transactie bezig bent, zonder dat je daar de exception daadwerkelijk af hoeft te handelen. Die kun je immers doorgooien, of je maakt een finaly blok. Op die manier kun je op elk niveau in de bijbehorende stack keurig je zaakjes opruimen en daar valt inderdaad ook een eventuele rollback onder.
Ja, maar het punt is dat je moet gaan achterhalen welke rollback operaties je allemaal uit moet voeren om de state van je programma te herstellen. Qua databases en de waarden van variabelen voor het blok is het niet zo moeilijk, maar als je ook bij moet gaan houden of files gewijzigd zijn, of bepaalde mails wel of niet verzonden zijn, etc., dan kan er aardig wat werk naar de exceptie afhandeling verschoven raken.
Alle log implementaties hebben bij hun log methode ook een extra parameter Throwable waardoor er een keurig stacktrace van die throwable, maar ook zijn causes in de log terecht kan komen. Het lijkt me dan ook dat je beter je log aanroepen of configuratie aan kunt passen dan de schuld op exceptions schuiven.
Natuurlijk, maar als je de code moet aanpassen, hercompileren, uitrollen en de fout reproduceren om te achterhalen waar een exception vandaan kwam, dan had ik liever dat ze het op een andere manier hadden opgelost.
Ja. In principe is dat natuurlijk het hele blackbox concept van OO. [knip uitleg]
Mijn zorg is niet dat het niet kan, maar dat het in de praktijk niet gebeurt. Ik heb geen conceptueel bezwaar tegen Excepties, maar een praktisch bezwaar. En dat is volgens mij ook waar de aversie vandaan komt: het is een taalconstructie die uitnodigt tot misbruik. Ik ben zelf ook een keer in de val getuind te denken 'ach, ik moet hier zoveel waarden op '!= null' controleren... weet je wat, ik wrap het hele zaakje gewoon in een try...catch NullPointerException blok, dan ben ik van dat gecontroleer af. Om vervolgens te ontdekken dat ik later op verschillende nulls wel verschillend wilde reageren, waardoor er logica in het catch blok terechtkwam, etc. Mijn punt is gewoon: als je denkt dat je een exception wil gooien, probeer het dan eerst drie keer op te lossen zonder exception. Als al die ontwerpen minder overzichtelijk zijn dan het geval met de exception, en het gevval met de exception leent zich ook voor latere aanpassing, vooruit, dan zal dit wel een geval zijn waarin het echt het handigst is.
Zou je anders een stukje voorbeeld kunnen geven van wat je daar tegen gekomen bent en waarom je dat een lastige constructie vond?
Ik zal eens kijken of ik dat nog terug kan vinden.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09:39

Janoz

Moderator Devschuur®

!litemod

Confusion schreef op maandag 10 december 2007 @ 09:49:
Ja, maar het punt is dat je moet gaan achterhalen welke rollback operaties je allemaal uit moet voeren om de state van je programma te herstellen. Qua databases en de waarden van variabelen voor het blok is het niet zo moeilijk, maar als je ook bij moet gaan houden of files gewijzigd zijn, of bepaalde mails wel of niet verzonden zijn, etc., dan kan er aardig wat werk naar de exceptie afhandeling verschoven raken.
Dat is in principe iets dat je in je transaction moet implementeren, en niet in je exception. In je catch zou een transaction.rollBack() dan ook voldoende moeten zijn.
Natuurlijk, maar als je de code moet aanpassen, hercompileren, uitrollen en de fout reproduceren om te achterhalen waar een exception vandaan kwam, dan had ik liever dat ze het op een andere manier hadden opgelost.
Dat is een beetje onzin. Als je loglevel nog niet goed was, dan pas je dat life aan waardoor maximaal een herstart van de applicatie nodig is, maar over het algemeen is een onverwachte stacktrace iets wat je standaard in je log opneemt. Hercompileren is dus helemaal nergens voor nodig (mits de log methoden op de juiste manier aangeroepen waren.)
Mijn zorg is niet dat het niet kan, maar dat het in de praktijk niet gebeurt. Ik heb geen conceptueel bezwaar tegen Excepties, maar een praktisch bezwaar.
Niet mijn praktijk om eerlijk te zijn.
En dat is volgens mij ook waar de aversie vandaan komt: het is een taalconstructie die uitnodigt tot misbruik. Ik ben zelf ook een keer in de val getuind te denken 'ach, ik moet hier zoveel waarden op '!= null' controleren... weet je wat, ik wrap het hele zaakje gewoon in een try...catch NullPointerException blok, dan ben ik van dat gecontroleer af. Om vervolgens te ontdekken dat ik later op verschillende nulls wel verschillend wilde reageren, waardoor er logica in het catch blok terechtkwam, etc. Mijn punt is gewoon: als je denkt dat je een exception wil gooien, probeer het dan eerst drie keer op te lossen zonder exception. Als al die ontwerpen minder overzichtelijk zijn dan het geval met de exception, en het gevval met de exception leent zich ook voor latere aanpassing, vooruit, dan zal dit wel een geval zijn waarin het echt het handigst is.
Runtime exceptions zoals NullPointer exceptions zijn juist weer typische voorbeelden van exceptions die niet in je 'excpetional flow' voor zouden moeten komen (muv de Spring Exceptions, maar die gebruiken runtime exceptions om te voorkomen dat er een hele rits throw definities bij een methode opgenomen moeten worden terwijl het toch de type excpetion zijn die niet onder de RunTime groep vallen, maar dat is weer een hele andere discussie)

Een nullpointer exception zou je eigenlijk alleen maar moeten gebruiken wanneer je framework of library code ontwikkeld die volgens specs geen null values accepteerd. In alle andere gevallen is er deuidelijk gedefinieerd wat er met een null value zou moeten gebeuren.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • Confusion
  • Registratie: April 2001
  • Laatst online: 01-03-2024

Confusion

Fallen from grace

Janoz schreef op maandag 10 december 2007 @ 10:07:
Dat is in principe iets dat je in je transaction moet implementeren, en niet in je exception. In je catch zou een transaction.rollBack() dan ook voldoende moeten zijn.
Als je al volledige transactions hebt: ja. Maar vaak genoeg, in eenvoudige applicaties, heb je dat niet. En eerst wordt er in de catch alleen een variabele herstelt. Vervolgens komt er nog eentje bij. Daarna moet ook een file gecontroleerd worden. Software evolueert en grote try...catch blokken, laat staan exception afhandeling op hoger niveau, resulteren in brakke software.
Dat is een beetje onzin. Als je loglevel nog niet goed was, dan pas je dat life aan waardoor maximaal een herstart van de applicatie nodig is, maar over het algemeen is een onverwachte stacktrace iets wat je standaard in je log opneemt.
Ik had het niet over onverwachte stacktraces, maar over verwachte excepties, die op de verkeerde plaats worden afgehandeld. Daarvan wordt de stacktrace meestal niet gelogged; uberhaupt wordt alleen op DEBUG niveau melding gemaakt van de exceptie, aangezien het bepaaald niet exceptioneel is en je log er anders mee volstaat.
Runtime exceptions zoals NullPointer exceptions zijn juist weer typische voorbeelden van exceptions die niet in je 'excpetional flow' voor zouden moeten komen
Jij vind het een 'typisch voorbeeld'. Maar maak maar eens hard waarom je een stel database handelingen wel in een try... catch SQLException mag wrappen, maar een stel operaties op data niet in een try...catch NullPointerException. Dat je het tweede op een andere manier kan testen is geen reden om de exceptie niet te gebruiken, als dat als makkelijker ervaren wordt.

Wie trösten wir uns, die Mörder aller Mörder?


Acties:
  • 0 Henk 'm!

  • Bobco
  • Registratie: Januari 2001
  • Laatst online: 30-10-2023

Bobco

I used to dream about Verona.

Confusion schreef op maandag 10 december 2007 @ 11:07:
[...]
Als je al volledige transactions hebt: ja. Maar vaak genoeg, in eenvoudige applicaties, heb je dat niet. En eerst wordt er in de catch alleen een variabele herstelt. Vervolgens komt er nog eentje bij. Daarna moet ook een file gecontroleerd worden. Software evolueert en grote try...catch blokken, laat staan exception afhandeling op hoger niveau, resulteren in brakke software.
Klopt, bovendien hebben veel acties nauwelijks een goede undo mogelijkheid. Hoe undo je bijvoorbeeld het versturen van een e-mail? Door een e-mail te sturen met de inhoud 'ignore the previous e-mail?
[...]
Jij vind het een 'typisch voorbeeld'. Maar maak maar eens hard waarom je een stel database handelingen wel in een try... catch SQLException mag wrappen, maar een stel operaties op data niet in een try...catch NullPointerException. Dat je het tweede op een andere manier kan testen is geen reden om de exceptie niet te gebruiken, als dat als makkelijker ervaren wordt.
Een onderscheid dat ik me kan voorstellen is dat tussen intern/extern. In het geval van calls naar een database roep je dingen aan buiten je eigen runtime omgeving. Daarbij kan het nodig mis gaan en daarom kan de call een exceptie opleveren. Bij data validatie in je eigen applicatie ligt dat anders: daar heb je in principe alles in de hand en is een validatie een flow met maar twee uitkomsten: goed of niet goed, eventueel aangevuld met informatie wat er dan niet goed is. Excepties komen daar IMHO niet aan te pas.

De JavaDoc voor Exception zegt: "The class Exception and its subclasses are a form of Throwable that indicates conditions that a reasonable application might want to catch." Het belangrijke in deze definitie is natuurlijk het woord reasonable. Ik heb het gevoel dat je dit ook moet toepassen op het gooien: dit moet ook redelijk zijn. Dan ben je weer terug op het punt waarbij het gaat om wat je als een normale en wat je als een exceptionele flow wilt zien. Natuurlijk kun je exceptions gooien waar je maar wilt, maar een validatieroutine is een goed voorbeeld van iets waarbij je data aanreikt en een OK of niet OK terugkrijgt. De verwerking van die data mag normaal gesproken niet tot problemen leiden. IMHO hoef je daarvoor dus bepaald geen excepties te gebruiken.

With the light in our eyes, it's hard to see.


Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 09:39

Janoz

Moderator Devschuur®

!litemod

Confusion schreef op maandag 10 december 2007 @ 11:07:
[...]

Als je al volledige transactions hebt: ja. Maar vaak genoeg, in eenvoudige applicaties, heb je dat niet. En eerst wordt er in de catch alleen een variabele herstelt. Vervolgens komt er nog eentje bij. Daarna moet ook een file gecontroleerd worden. Software evolueert en grote try...catch blokken, laat staan exception afhandeling op hoger niveau, resulteren in brakke software.
Waarom zou dat afhandelen ingewikkelder worden dan het afhandelen binnen de code zelf? Bedenk wel dat je de verantwoordelijke onderdelen ook op het juiste niveau afhandeld. Dat het op een iets hoger niveau het terugdraaien van een file is dan weet je ook op dat specifieke niveau om welke file het gaat en wat er mee moet gebeuren. Dat het op een veel lager niveau een variabele is en op een veel hoger niveau iets anders maakt voor dit niveau helemaal niks uit.
Ik had het niet over onverwachte stacktraces, maar over verwachte excepties, die op de verkeerde plaats worden afgehandeld. Daarvan wordt de stacktrace meestal niet gelogged; uberhaupt wordt alleen op DEBUG niveau melding gemaakt van de exceptie, aangezien het bepaaald niet exceptioneel is en je log er anders mee volstaat.
Zodra ik een catch doe log ik dat, eventueel op een lager log niveau zoals TRACE. Verder lijkt het me dat je door goede exceptions te gebruiken en ze eventueel te wrappen juist beter af kunt dwingen op welke plek iets afgehandeld moet worden. Wil je immers iets afhandelen dat zul je specifiek die exception moeten catchen. Je wordt tijdens het ontwikkelen dus actief getriggered om na te denken wat je waar afhandelt.
Jij vind het een 'typisch voorbeeld'. Maar maak maar eens hard waarom je een stel database handelingen wel in een try... catch SQLException mag wrappen, maar een stel operaties op data niet in een try...catch NullPointerException. Dat je het tweede op een andere manier kan testen is geen reden om de exceptie niet te gebruiken, als dat als makkelijker ervaren wordt.
Ik lees en schrijf inderdaad met Java en daardoor komen veel dingen inderdaad erg triviaal op me over. Dat is zeker waar. Verschil tussen beiden is dat het wel of niet mee kunnen geven van null data een onderdeel van de specs is. In je methode definitie kun je aangeven hoe null waardes afgehandeld worden. Accepteert de methode geen null dan is het inderdaad niet vreemd dat deze een nullpointer exception kan gooien.

Het afvangen van een NullPointer exception is daarintegen behoorlijke onzin. Je hebt zelf de volledige controle over het hoe en wat van je gegevens binnen de scope van je methode aan toe. Je kunt het dus al keurig van te voren oplossen.

Een SQLException daarentegen is afhankelijk van een niet door jezelf gecontroleerde externe bron. Je kunt dus nooit van te voren uitsluiten dat alles goed gaat. In dat geval kan er dus wel een uitzondering plaatsvinden die je niet kunt voorkomen.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • qless
  • Registratie: Maart 2000
  • Laatst online: 16:10

qless

...vraag maar...

Eigenlijk is het simpel, Exceptions moet je alleen gebruiken bij alles wat te maken heeft met I/O, dus
-SQL
-Files
-RMI
-Corba
-Sockets

De rest hoor je in je eigen code te kunnen oplossen, zodat je nooit een exception krijgt. Je eigen code tenslote zou voorspelbaar moeten zijn, (remote) I/O is dat nooit.

Website|Air 3s|Mini 4 Pro|Avata 2|Canon R6|Canon 5d2|8 fisheye|14f2.8|24f2.8|50f1.8|135f2|10-22|17-40|24-105|70-300|150-600


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

qless schreef op maandag 10 december 2007 @ 12:19:
Eigenlijk is het simpel, Exceptions moet je alleen gebruiken bij alles wat te maken heeft met I/O, dus
-SQL
-Files
-RMI
-Corba
-Sockets

De rest hoor je in je eigen code te kunnen oplossen, zodat je nooit een exception krijgt. Je eigen code tenslote zou voorspelbaar moeten zijn, (remote) I/O is dat nooit.
Wat is dat nou weer voor opmerking? Waarom is code die exceptions gooit niet voorspelbaar?

Ik vind het voorspelbaar als ik in een method signature een "throws NonUniqueException" zet en documenteer wanneer dat kan voorkomen.

Exceptions is gewoon een return type van een methode die als gevolg heeft dat de stack teruggerold wordt tot een bepaald punt. En met het oog op principes zoals Separation of Concerns is dat een heel elegant hulpmiddel. (zeker met RuntimeExceptions).

Ja, Exceptions zijn iets duurder dan "gewone" programma flow. Ja, je code kan een bende worden. Het is gewoon een kwestie van gebruik met mate.

In mijn eerdere voorbeeld vind ik het netter dat er een NonUniqueException kan optreden dan dat je een returnwaarde gaat misbruiken voor het teruggeven van statusinformatie.

Fat Pizza's pizza, they are big and they are cheezy

Pagina: 1