[GP] Gebruik van exceptions

Forum van 2de Bachelor Informatica.

Moderator: Praesidium

User avatar
Fristi
WOZ
Posts: 4565

[GP] Gebruik van exceptions

Post#1 » Tue Dec 23, 2008 11:20 pm

Loha
Een tijd geleden was er op irc een nogal "verhitte en heftige" discussie over het gebruik van exceptions in c++.

Ik heb toen naar zowel broeckie als naar Kelly gemaild. Intussen heb ik van beide een antwoord gekregen, dit wil ik nu met jullie delen:

Broeckie:

Code: Select all


Beste Kevin,

Het gaat bij exceptions idd om de uitzonderlijke gevallen. Foutieve user input valt hier m.i. niet onder.

Het valt er niet onder omdat het no relatief vaak kan voorkomen en omdat zonder meer duidelijk is waar en hoe het probleem te ondervangen met "normale" programma logica zoals je zelf aangeeft.

Exceptions voor "alles" gebruiken is zeker de bedoeling niet. Ik heb dat rwouwens duidelijk in de les aangegeven en staat ook duidelijk in Stroustrup.

Mvg,
Jan Broeckhove
Kelly:

Code: Select all


Beste Kevin,

Asserts mag je niet gebruiken als foutafhandeling naar de gebruiker toe. Je programma stopt dan meteen zonder dat de gebruiker de fout nog kan herstellen door bv een andere input te geven.
Je gebruikt exceptions wanneer de methode die je wil uitvoeren niet lukt. Bv stel je wil een plaats reserveren via de methode Plaats.Reserveer(nr,...). Als dit niet lukt omdat de plaats bv al gereserveerd is of niet bestaat, dan throw je een exception. Het reserveren van die plaats is immers niet gelukt.

Als je puur op input gaat controleren of de gebruiker wel een INTEGER of dergelijke heeft ingegeven, dan werk je niet met exceptions.
Exceptions gebruik je alleen bij foutmeldingen die in de onderliggende code niet kunnen afgehandeld worden. We gaan dus in de onderliggende klasses niet meer rechtstreeks printen. Het printen wordt alleen nog maar gedaan in je testmethode/klasse.
Gewone foute input kan je dus makkelijk met een if en cout doen, want je zit dan al in de juiste methode om iets af te drukken, namelijk je testmethode/klasse.

Kortom, alle andere methodes die je vanuit je testmethode/klasse aanroept, moeten exceptions throwen en mogen geen printstatements doen.
Hopelijk is dit voor anderen ook nog van nut
Fristi
Fristi Ad Infinitum

WINAK WOZ 2013 - ...
WINAK Magister Fristi 2012-2013
WINAK Feest 2011-2012
WINAK Schachtentemmer 2010-2011
WINAK Scriptor 2008-2009 | 2009-2010

User avatar
Sebastiaan
Posts: 1184

Post#2 » Wed Dec 24, 2008 10:49 am

dees is wel handig om te weten, thx

User avatar
PieterK
Posts: 118

Post#3 » Wed Dec 24, 2008 12:14 pm

Ik vind het nog altijd niet helemaal duidelijk. Stel in de 2e opdracht. De constructor van de klasse "Optreden" krijgt oa als parameters beginuur en einduur. Als het einduur nu vroeger is dan het beginuur dan is dat een fout en kan de constructor nie verder. Moet je dat dan checken met een if en dan een foutmelding cout-en in de constructor zelf of een exception throwen? :?

Pieter Belmans
Posts: 593
Contact:

Post#4 » Wed Dec 24, 2008 12:28 pm

Dat is een preconditie, en moet dus gecontroleerd worden vooraleer die constructor wordt aangeroepen.

User avatar
PieterK
Posts: 118

Post#5 » Wed Dec 24, 2008 12:48 pm

Ok. Das duidelijk. Merci. :)

User avatar
Tom
Posts: 602

Post#6 » Wed Dec 24, 2008 3:18 pm

Om goede interne en externe werking te garanderen en het oplossen van problemen heb ik even een samenvatting gemaakt, als er iets fout was laat dan iets weten, dan pas ik het aan.

Asserts (Problemen/werking intern)
  • Precondities controleren
    • Is de meegegeven data juist?
    • Klopt de meegegeven index?
    • Verwijst een pointer naar een object?
    • Zijn de benodigde andere functie(s) aangeroepen?
  • Loops controleren
    • Verwijst de iterator nog naar een object?
    • Worden er geen extreme waarden bereikt?
  • Postcondities controleren
    • Heeft de procedure zijn werk goed gedaan?
    • Kunnen we nu de andere functie(s) aanroepen?
Exceptions (Problemen naar buiten toe)
  • Fout bij het lezen van een bestand.
  • Fout die binnen de module niet kan worden opgelost en niet onder asserts valt.
Testen (Werking naar buiten toe)
  • Unit: Bij goede invoer de verwachte handelingen en uitvoer controleren op een enkele klasse.
  • Integretion: De samenwerking tussen verschillende klassen testen.
  • Regression: Het geheel testen.
Plaats.Reserveer(nr,...). Als dit niet lukt omdat de plaats bv al gereserveerd is of niet bestaat, dan throw je een exception. Het reserveren van die plaats is immers niet gelukt.
Uitwerking Voorbeeld

Dit kan niet binnen de module worden opgelost, dit is verder ook geen preconditie omdat de meegegven data niet foutief is en het object gewoon bestaat. (Het controleren binnen een object lijkt me geen preconditie [dus ook niet isGereserveerd()], zelfs niet als dit invoer van de gebruiker is, want deze is reeds gecontroleert geweest door de constructors/setters van dat object)[/b]

FAQ:
Is there any valid reason to ever ignore a caught exception?
Return null or throw exception?
Test cases VS Assertion statement
What is the best way of implementing assertion checking in C++
Which and why do you prefer exceptions or return codes?
Why aren't variables declared in try in scope in catch? (Let niet op finally)
Why re-throw exceptions?

User avatar
Midori
Posts: 46

Post#7 » Sat Dec 27, 2008 1:12 pm

Ik vind het vreemd dat je bij een hard-coded testmodule precondities moet gaan nakijken. Dan krijg je zoiets in den aard van:

if(isString("Jan")){
System.addUser("Jan");
}
else{
cout<<"Error: ingegeven naam is geen string!\n";
}

Bij softcoded testen kan de user ingeven wat hij wilt. Nu is het min of toch al duidelijk dat Jan een string is...

En hoe doen jullie de exceptions? Ik had gedacht een header file te maken die alle exception header files include, zodat je niet in elke module alle exception header files (met de klasse erin) moet includen, aangezien je elke klasse in een aparte header file moet plaatsen.

Bvb. Exceptions.h
#include "Exception1.h"
#include "Exception2.h"
etc

En dan in elke module: #include "Exceptions.h"

User avatar
Tom
Posts: 602

Post#8 » Sat Dec 27, 2008 1:37 pm

De precondities worden gecontroleerd door asserts in je functies en die moet je in jouw test module niet meer gaan controleren. (Doe je dit wel dan crasht jouw programma gewoon) Je moet dus enkel testen of je bij geldige waarden de juiste uitvoer krijgt.

Bij het meegeven van informatie van de gebruiker of uit het xml bestand moet je voor elke oproep gaan controleren of alle data juist is. (Het contract tussen de twee procedures is dat er de juiste data wordt doorgegeven, dit is ook een eis die in de use cases [= Project PDF] staat opgesteld en zou normaal ook betere praktijk moeten zijn)

Zelf heb ik een header file gemaakt met de naam van de namespace en daar de exceptions ingezet. Een apart bestand gaat natuurlijk ook. Meerdere lijkt me niet nodig aangezien het beperkt aantal exceptions dat je bij dit project nodig hebt.

User avatar
Fristi
WOZ
Posts: 4565

Post#9 » Wed Dec 31, 2008 12:12 pm

Waarom is controleren binnen een object geen preconditie?
als in:
Als ik een optreden wil uit men lijst van optredens maar een of andere fucker geeft ne naam in van een optreden dat niet bestaat, exception throwen of preconditie?

Heb dit al gevraagd op irc en Pïeter zei preconditie en ik zou dat ook zeggen omdat dit niet zo uitzonderlijk is in mijn ogen, maar wat is dan het verschil met een plaats die al gereserveerd is?
Fristi Ad Infinitum

WINAK WOZ 2013 - ...
WINAK Magister Fristi 2012-2013
WINAK Feest 2011-2012
WINAK Schachtentemmer 2010-2011
WINAK Scriptor 2008-2009 | 2009-2010

User avatar
Tom
Posts: 602

Post#10 » Wed Dec 31, 2008 4:54 pm

Fristi wrote:Waarom is controleren binnen een object geen preconditie?
als in:
Als ik een optreden wil uit men lijst van optredens maar een of andere fucker geeft ne naam in van een optreden dat niet bestaat, exception throwen of preconditie?

Heb dit al gevraagd op irc en Pïeter zei preconditie en ik zou dat ook zeggen omdat dit niet zo uitzonderlijk is in mijn ogen, maar wat is dan het verschil met een plaats die al gereserveerd is?
Om hier een preconditie te gebruiken moet je de namen apart gaan opslaan of een procedure binnen het object gaan voorzien die controleert of de naam aanwezig is. Dit resulteert in een minder efficiente methode (meer dataopslag of meer instructies) dan het opgooien van een exception indien de naam niet gevonden wordt. Bij het extern opslaan of aanroepen van de controle functie overloop je de lijst dubbel in tegenstelling tot het verwaarloosbaar opzetten van een exception stack (en een throw na een return). De return via controle is immers de oude C manier van een exception.

Voor dit voorbeeld lijkt me een exception beter. Het gebruik van asserts is handig zolang je geen extra data moet gaan opslaan of inefficiente praktijken moet gaan gebruiken om te gaan controleren dat je het contract niet breekt. Let er op dat je asserts steeds moet voorkomen en exceptions steeds moet afhandelen. (Als je een stabiele werking wil garanderen)

Pieter Belmans
Posts: 593
Contact:

Post#11 » Wed Dec 31, 2008 7:34 pm

1 of 2 maal een gelinkte lijst doorlopen is nog steeds 0(n).

En als dit soort fouten met exceptions wordt afgehandeld, wordt je code 1 groot try catch statement en dat is niet de bedoeling. En vaak zijn het dan nog try catch statements die 1 niveau hoger al worden afgevangen, namelijk de caller vangt de fout in de callee op. Daar is weinig "andere context" aan, terwijl exceptions net bedoeld zijn voor dingen die net in dezelfde context kunnen afgehandeld worden omdat er daar geen wetenschap is over hoe dit dient te gebeuren.

User avatar
Fristi
WOZ
Posts: 4565

Post#12 » Sat Jan 03, 2009 12:13 am

Nu valt mij eigelijk pas da laatste zinneke op uit kelly hare mail: (ni dak moeilijk wil blijven doen , allesbehalve, ik denk dattek zelf wel min of meer een degelijk ideeh eb waar ik ze bij mij moet gebruiken, tis gewoon een discussie waar volgens mij meerdere mensen iets uit kunnen leren, ikzelf ben daar een van)

"alle andere methodes die je vanuit je testmethode/klasse aanroept, moeten exceptions throwen en mogen geen printstatements doen."

hier zegt ze eigenlijk letterlijk da elke functie die ik uit men testding oproep exceptions moet throwen voor als er iets misgaat, hiermee spreekt ze in mijn ogen den Broeckie dan toch tegen.

Als ik voor alle dingen die mis kunnen gaan in een methode een exception voorzie, dan ist allesbehalve uitzonderlijk zenne :P

edit: tis ook een pak semantiek, wanneer is iets "uitzonderlijk", n klant die gene vip is maar toch een vipplaats probeert te reserveren, is in mijn ogen niet uitzonderlijk..
Fristi Ad Infinitum

WINAK WOZ 2013 - ...
WINAK Magister Fristi 2012-2013
WINAK Feest 2011-2012
WINAK Schachtentemmer 2010-2011
WINAK Scriptor 2008-2009 | 2009-2010

User avatar
Sebastiaan
Posts: 1184

Post#13 » Sat Jan 03, 2009 10:33 am

Fristi wrote: ...

edit: tis ook een pak semantiek, wanneer is iets "uitzonderlijk", n klant die gene vip is maar toch een vipplaats probeert te reserveren, is in mijn ogen niet uitzonderlijk..
Bij mij is nen klant die nen een Vipplaats probeert te reserveren ook een Exception waard.

Anders kunde voor elke pointer dagge gaat gebruiken, wel zetten van Moest deze pointer NILL zijn (ik heb wel geen idee hoe het zou kunnen maar toch) throw exception.

User avatar
Norfolk
WOZ
Posts: 780
Contact:

Post#14 » Sat Jan 03, 2009 11:05 am

Als ge het in die functie kunt afhandelen dat die klant geen VIP plaats mag reserveren dan doet ge dat. Kunt ge dat niet afhandelen op dat moment, dan gooit ge een exception.

User avatar
Sebastiaan
Posts: 1184

Post#15 » Sat Jan 03, 2009 11:19 am

Norfolk wrote:Als ge het in die functie kunt afhandelen dat die klant geen VIP plaats mag reserveren dan doet ge dat. Kunt ge dat niet afhandelen op dat moment, dan gooit ge een exception.
Maar ge kunt toch bijna alles afhandelen in die functie zelf? Het enige wagge dan moet doen is nen "if" en als het fout loopt nen "print" van wat er fout liep? of is het juist diene print dagge moet throwen?

Return to “2de Bachelor”

Who is online

Users browsing this forum: No registered users and 49 guests

cron