[Alg] Exceptions: zin en onzin

Pagina: 1 2 Laatste
Acties:
  • 1.289 views sinds 30-01-2008
  • Reageer

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Jaap-Jan
  • Registratie: Februari 2001
  • Laatst online: 07:09
Modbreak:Dit topic is afgesplitst van [alg] Slechtste programmeervoorbeelden deel 2.
uruviel359 schreef op dinsdag 08 mei 2007 @ 19:03:
Dan maar zo :+
Java:
1
2
3
4
5
6
7
boolean isInteger(String s) {
    try{
        Integer.valueOf(s).intValue();
    } catch(NumberFormatException e) {
        return false;
    } return true;
}
Mja, inderdaad, dat is de methode zoals ik hem ook op internet weleens zie. Ik vraag me alleen af waarom mensen dit nodig zouden hebben. Als het is om dit te kunnen doen:

Java:
1
2
3
4
int month;
if (isInteger(monthString)) {
    month = Integer.parseInt(monthString);
}


Dan is het vrij zinloos natuurlijk :P. Ik bedoel, waarom zou je alléén willen weten of een string een getal is, zonder dat iemand deze string zou willen parsen naar een integer? Ik kan het zo eigenlijk niet bedenken.

Oké, misschien omdat je de string wilt gebruiken om een SQL query op te bouwen en dus zeker te stellen dat je een getal in de database probeert te proppen, maar daar heb je toch prepared statements voor, lijkt me :).

[ Voor 5% gewijzigd door NMe op 11-05-2007 10:56 ]

| Last.fm | "Mr Bent liked counting. You could trust numbers, except perhaps for pi, but he was working on that in his spare time and it was bound to give in sooner or later." -Terry Pratchett


Acties:
  • 0 Henk 'm!

Verwijderd

Jaap-Jan schreef op dinsdag 08 mei 2007 @ 19:29:
[...]

Mja, inderdaad, dat is de methode zoals ik hem ook op internet weleens zie. Ik vraag me alleen af waarom mensen dit nodig zouden hebben. Als het is om dit te kunnen doen:

Java:
1
2
3
4
int month;
if (isInteger(monthString)) {
    month = Integer.parseInt(monthString);
}


Dan is het vrij zinloos natuurlijk :P. Ik bedoel, waarom zou je alléén willen weten of een string een getal is, zonder dat iemand deze string zou willen parsen naar een integer? Ik kan het zo eigenlijk niet bedenken.

Oké, misschien omdat je de string wilt gebruiken om een SQL query op te bouwen en dus zeker te stellen dat je een getal in de database probeert te proppen, maar daar heb je toch prepared statements voor, lijkt me :).
Omdat je strongly typed wil werken en dus een integer ook als een integer wil gebruiken. Een textbox geeft bijvoorbeeld altijd een string terug. Als daar alleen integers in zouden mogen moet je hem casten naar een integer.... Daarnaast is het erg verstandig om te controleren of iets inderdaad een Integer is om hem daarna pas te casten. Dit voorkomt een hoop problemen die anders kunnen ontstaan....

Een Integer moet je als een integer gebruiken en niet maar lekker een string laten, omdat het straks toch weer in de query verdwijnt die als string uitgevoerd wordt.

[ Voor 6% gewijzigd door Verwijderd op 08-05-2007 19:35 ]


Acties:
  • 0 Henk 'm!

  • MetroidPrime
  • Registratie: Oktober 2003
  • Laatst online: 20-09 10:11

MetroidPrime

Turn it up loud, captain!

Jaap-Jan schreef op dinsdag 08 mei 2007 @ 19:29:
[...]

Mja, inderdaad, dat is de methode zoals ik hem ook op internet weleens zie. Ik vraag me alleen af waarom mensen dit nodig zouden hebben. Als het is om dit te kunnen doen:

Java:
1
2
3
4
int month;
if (isInteger(monthString)) {
    month = Integer.parseInt(monthString);
}


Dan is het vrij zinloos natuurlijk :P. Ik bedoel, waarom zou je alléén willen weten of een string een getal is, zonder dat iemand deze string zou willen parsen naar een integer? Ik kan het zo eigenlijk niet bedenken.
Ik heb net een klein programmatje geschreven waarbij ik command line arguments wil parsen. Als een bepaald argument geen positief getal is, dan moet de usage tekst met de melding dat er een getal verwacht wordt naar System.out geschreven worden. Je zou het ook kunnen afvangen met behulp van de NumberFormatException die Integer.parseInt gooit, maar dat vind ik een minder nette oplossing.

"Some girl on the street outside the bar just asked me if I was saved yet." "Yeah? What did you say?" "I told her 'I saved at the checkpoint a couple of minutes back and I can reload from there if I die.'


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 19:07
uruviel359 schreef op dinsdag 08 mei 2007 @ 19:03:
Dan maar zo :+
Java:
1
2
3
4
5
6
7
boolean isInteger(String s) {
    try{
        Integer.valueOf(s).intValue();
    } catch(NumberFormatException e) {
        return false;
    } return true;
}
Het nadeel van deze functie is natuurlijk wel dat excepties gooien wel een heel stuk trager zijn dan het parsen van een String (tot op zekere hoogte) ;) En aangezien de Integer.parseInt(s) (welke ik zou gebruiken) niets anders doet dan controleren of de String uit alleen maar cijfers bestaat (met eventueel een min ervoor) zou ik dit doen:

Java:
1
2
3
4
5
6
7
8
public boolean isInteger(String s) {
  for(int i = s.length() - 1; i >= 0; i--) {
    if(s.charAt(i) < '0' || s.charAt(i) > '9') {
      return (i == 0 && s.length() > 1 && s.charAt(0) == '-');
    }
  }
  return s.length() > 0;
}


:P Wie ziet hier nog een mogelijke fout in? (Ook de String "-" wordt nu niet meer gezien als integer namelijk ;))

Acties:
  • 0 Henk 'm!

  • brama
  • Registratie: Februari 2001
  • Niet online
Marcj schreef op dinsdag 08 mei 2007 @ 22:58:
[...]

Het nadeel van deze functie is natuurlijk wel dat excepties gooien wel een heel stuk trager zijn dan het parsen van een String (tot op zekere hoogte) ;) En aangezien de Integer.parseInt(s) (welke ik zou gebruiken) niets anders doet dan controleren of de String uit alleen maar cijfers bestaat (met eventueel een min ervoor) zou ik dit doen:

Java:
1
2
3
4
5
6
7
8
public boolean isInteger(String s) {
  for(int i = s.length() - 1; i >= 0; i--) {
    if(s.charAt(i) < '0' || s.charAt(i) > '9') {
      return (i == 0 && s.length() > 1 && s.charAt(0) == '-');
    }
  }
  return s.length() > 0;
}


:P Wie ziet hier nog een mogelijke fout in? (Ook de String "-" wordt nu niet meer gezien als integer namelijk ;))
Jij schrijft liever een hoop extra code, dan dat je die exception afvangt en gebruik maakt van bewezen en bestaande code? Dat lijkt mij in dit geval *zwaar* overdreven, tenzij je echt elke cpu-cycle zeer, zeer hard nodig hebt, en je deze code gruwelijk vaak uit moet voeren.

I mentioned it once, but I think I got away with it.


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

brama schreef op dinsdag 08 mei 2007 @ 23:24:
Jij schrijft liever een hoop extra code, dan dat je die exception afvangt en gebruik maakt van bewezen en bestaande code? Dat lijkt mij in dit geval *zwaar* overdreven, tenzij je echt elke cpu-cycle zeer, zeer hard nodig hebt, en je deze code gruwelijk vaak uit moet voeren.
Ik heb zelf liever wat extra code (voor wat checks) dan dat ik moedwillig een exception ga gebruiken.

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Erkens schreef op dinsdag 08 mei 2007 @ 23:28:
[...]

Ik heb zelf liever wat extra code (voor wat checks) dan dat ik moedwillig een exception ga gebruiken.
Voor simpele dingen op zich wel. Maar voor het dingen als parsen enzo, wat toch redelijk complex kan worden, gebruik ik toch liever bestaande functies. Dan zorg ik er wel voor dat de exceptions idd in mijn "wrapper" method af gevangen worden.

Mijn baas wil er liever niet voor betalen dat ik telkens het wiel opnieuw uitvindt. Alleen als het in een performance critisch gedeelte zit zal ik er mischien nog even over nadenken of het niet beter is om het zelf te doen.

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 10:15

MBV

Erkens schreef op dinsdag 08 mei 2007 @ 23:28:
[...]

Ik heb zelf liever wat extra code (voor wat checks) dan dat ik moedwillig een exception ga gebruiken.
Doe voor de gein eens een testje:
Java:
1
2
3
4
5
6
int aantallen[ ] = {1,5,3,7,8,45,2,5,7,3,2,6,7,2,6,8};
int totaal=0;
for (int i=0; i<aantallen.length; i++)
{
totaal+=aantallen[i];
}
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
int aantallen[] = {1,5,3,7,8,45,2,5,7,3,2,6,7,2,6,8};
int i=0;
int totaal = 0;
try
{
while (true)
{
totaal+=aantallen[i];
i++;
}
} catch (ArrayIndexOutOfBoundsException e)
{
}


Een oud-leraar heeft me verteld dat de 2e manier bijna constant was... Misschien is JVM in 2,5 jaar wel wat verbeterd, magoed ;)

Acties:
  • 0 Henk 'm!

Verwijderd

Erkens schreef op dinsdag 08 mei 2007 @ 23:28:
[...]

Ik heb zelf liever wat extra code (voor wat checks) dan dat ik moedwillig een exception ga gebruiken.
Je onderbouwing?

Ik heb zelf wel eens een (C++) exception gebruikt om uit een 4-diep geneste f-call te springen. Het alternatief was de introductie van een status-variabele, die in een stuk of 15 if-statements getest moest worden. Het throwen van een exception was een elegante manier om de code leesbaarder te maken, niets meer dan dat.

En ja, het was een redelijk performance-kritieke applicatie, echter de overhead van de exception op het gehele programma was volstrekt verwaarloosbaar.

Overigens zijn exceptions heel wat prettiger in gebruik dan setjmp/longjmp. En gemak dient de mens, niet omgekeerd.

Acties:
  • 0 Henk 'm!

Verwijderd

Zo heb ik net nog een stukje code geschreven dat een bestand uitleest, waarbij hij niet naar een EOF kijkt, maar in dat geval de catch (EOFException) in schiet. Toch niets mis mee? Daar zijn ze voor :)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op woensdag 09 mei 2007 @ 00:13:
En ja, het was een redelijk performance-kritieke applicatie, echter de overhead van de exception op het gehele programma was volstrekt verwaarloosbaar.
Klopt, maar het verschil tussen diezelfde applicatie zonder exceptions en die applicatie gecompileerd met exceptions algeheel uitgezet is niet verwaarloosbaar, waardoor exceptions in onze performance kritieke applicaties (games met name) altijd worden gecompileerd zonder exception support.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 19:07
Oeps, een hele discussie gestart :X Het was een beetje met een knipoog bedoelt ;)

Maar goed, ik zou persoonlijk excepties alleen gebruik voor exceptionele gevallen, dus als er iets gebeurt wat je in de normale control flow niet verwacht. Voor de normale control flow zou ik nooit excepties gebruiken. Excepties is bijvoorbeeld voor fouten tijdens het lezen van een bestand of voor fout input ofzo.

Daarnaast moet je onthouden dat de JVM bij het aanmaken van een exceptie de huidige stack moet bekijken voor een call trace, dus dat het wel erg traag is.

Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op woensdag 09 mei 2007 @ 00:26:
[...]
Klopt, maar het verschil tussen diezelfde applicatie zonder exceptions en die applicatie gecompileerd met exceptions algeheel uitgezet is niet verwaarloosbaar, waardoor exceptions in onze performance kritieke applicaties (games met name) altijd worden gecompileerd zonder exception support.
Wat wil je nou zeggen, klopt wel maar klopt niet? :) Dan is mijn reaktie: je hebt gelijk, maar let wel op de context van je gelijk.

Ik zal eerst mijn vorige post wat nauwkeuriger stellen: in dat bewuste programma dat gecompileerd werd met exceptions enabled (compiler: MSVC 4.2 - dus dit voorbeeld dat me als eerste te binnen schoot is al een jaartje of 10 oud) maakte het al dan niet gebruiken van die ene exception op genoemde plaats geen door de profiler meetbaar, significant verschil. Dat weet ik nog goed, omdat ik de profiler heb moeten gebruiken om hoogstpersoonlijk de grootste door de jongens op knullige wijze geïntroduceerde bottlenecks te elimineren. Die trouwens 'tig meer performance kostten dan ooit door exceptions veroorzaakt zouden kunnen worden, maar dat terzijde.

Je kunt inderdaad overwegen om dat laatste (al dan niet would-be) beetje performance te winnen door helemaal geen exceptions te gebruiken (disclaimer: ik praat over C++). Maar mijn ervaring is dat je dan echt over het allerlaatste beetje praat, omdat je dan kennelijk niets meer weet te winnen door betere algorithmen en/of andere datastructuren. Er is dan sprake van een ruim bovengemiddeld ervaren programmeur, die zijn methoden & technieken bijzonder grondig kent - en ook heeft toegepast. En extreme eisen stelt aan de applicatie.

Ik heb onder meer dingen gedaan als het maken van een vga-driver voor het vanuit C kunnen tekenen van 2-D graphics primitieven onder ms-dos (msc 4.0, lijkt alweer een eeuwigheid geleden). Het eerste wat ik deed voor een goede performance, was het gebruik van zo optimaal mogelijke algorithmen (zoals cirkels en ellipsen kunnen plotten zonder vermenigvuldigingen), en implementeren in C. Daarna was het eindeloos sleutelen door eerst de door de compiler gegenereerde code te bekijken met het boekje met de 8088/8086 instructieset inclusief de executietijden ernaast, en dan subtiele wijzigingen in de code aan te brengen om een door de compiler gegenereerde jump te voorkomen, of een iets andere registerallocatie af te dwingen. Dat soort dingen.
Wetende dat dit laatste voor niets kan zijn, als er een nieuwe compiler-release aankomt...
Inline assembler was hierbij trouwens geen optie, omdat mijn eventuele opvolger de code moest kunnen begrijpen zonder al te lange leercurve.

Wij hebben toenmaals wat aardige orders weten binnen te halen omdat onze ms-dos implementatie aanzienlijk harder liep dan die van onze concurrenten. Dit geeft aan hoe die laatste performance-verschillen voor ons in economisch opzicht belangrijk waren. Maar je wilt niet weten wat ik daar allemaal voor heb moeten doen. Wel uitermate leerzaam trouwens, vanwege de opgedane inzichten.

Nu mijn punt: het bovenstaande verhaal behoort niet tot de standaard-werkzaamheden van de gemiddelde programmeur. En die van jou - games developen - ook niet. Voor dat soort dingen gelden m.i. andere maatstaven, waar inderdaad de door jou genoemde opmerking van toepassing is. Aan de andere kant ben ik van mening dat het voor het standaard-werk (C++) kwa performance in het algemeen niet bijster spannend is of iemand exceptions gebruikt of niet. Ook niet voor bijvoorbeeld de GoT contest. Eventueel kan ik altijd nog de doelmachine 5% overklokken... Of twee maanden later een andere (nieuwer en dus snellere) kopen.

Mijn statement in dezen is dus: als je bij een standaard applicatie overweegt om vanwege performance redenen geen exceptions te gebruiken, ga dan eerst nog eens een paar keer goed naar je algorithmen kijken, en probeer wat alternatieven uit.

Terzijde: je klinkt als iemand die boeiend werk doet.

Acties:
  • 0 Henk 'm!

Verwijderd

Nog even voor alle duidelijkheid: in de vorige post had ik het over C++ exceptions, en ik realiseer me net dat de diskussie over Java gaat. Door een speling van het lot heb ik nog nooit iets serieus met Java gedaan, dus daar kan ik niets over zeggen. Het kan dus heel goed mogelijk zijn dat het daar anders ligt.

Aan de andere kant rijst dan de vraag - .oisyn: implementeer jij je game(s) soms in Java?

Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

MBV schreef op woensdag 09 mei 2007 @ 00:06:
[...]

Doe voor de gein eens een testje:
Java:
1
2
3
4
5
6
int aantallen[ ] = {1,5,3,7,8,45,2,5,7,3,2,6,7,2,6,8};
int totaal=0;
for (int i=0; i<aantallen.length; i++)
{
totaal+=aantallen[i];
}
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
int aantallen[] = {1,5,3,7,8,45,2,5,7,3,2,6,7,2,6,8};
int i=0;
int totaal = 0;
try
{
while (true)
{
totaal+=aantallen[i];
i++;
}
} catch (ArrayIndexOutOfBoundsException e)
{
}


Een oud-leraar heeft me verteld dat de 2e manier bijna constant was...
wat bedoel je met "constant" :?
maar verder, vind je werkelijk de die 2e versie beter leesbaar? ik zie daar als eerste een endless loop dan dat ik zie dat je door een array loopt. Leebaarheid van de code staat bij op de eerste plaats, daarna komt eventueel performance.

Acties:
  • 0 Henk 'm!

  • HawVer
  • Registratie: Februari 2002
  • Laatst online: 13-09 16:51
Erkens schreef op woensdag 09 mei 2007 @ 07:58:
[...]

wat bedoel je met "constant" :?
maar verder, vind je werkelijk de die 2e versie beter leesbaar? ik zie daar als eerste een endless loop dan dat ik zie dat je door een array loopt. Leebaarheid van de code staat bij op de eerste plaats, daarna komt eventueel performance.
Zou hij constante tijd bedoelen? Beide loops doen exact hetzelfde dus het lijkt me niet een verschil in performance.

[ Voor 8% gewijzigd door HawVer op 09-05-2007 08:29 ]

http://hawvie.deviantart.com/


Acties:
  • 0 Henk 'm!

  • brama
  • Registratie: Februari 2001
  • Niet online
Marcj schreef op woensdag 09 mei 2007 @ 01:32:
Oeps, een hele discussie gestart :X Het was een beetje met een knipoog bedoelt ;)

Maar goed, ik zou persoonlijk excepties alleen gebruik voor exceptionele gevallen, dus als er iets gebeurt wat je in de normale control flow niet verwacht. Voor de normale control flow zou ik nooit excepties gebruiken. Excepties is bijvoorbeeld voor fouten tijdens het lezen van een bestand of voor fout input ofzo.
In het geval en een string naar een nummertje converteren, waarbij de string user-input data is, zou ik de NumberFormatException gebruiken. Ook om te kijken *of* iets een nummertje is (isInteger()), omdat dit simpelweg erg leesbaar is, en niet betekent dat ik het wiel uitvindt.

Als ik mijn apps profile, dan ligt de bottleneck vrijwel altijd op een totaal niet verwachtte plek. Om dan maar even een leuk zijstraatje in te slaan:

Laatst had ik een applicatie die veel (paar miljoen) textdocumenten inlas, en vervolgens een hashtable bouwde met een vaste max. grootte, waarbij woorden uit die text gemapt werden naar getalletjes.

Ondanks het feit dat die table een vaste max. grootte had, groeide het geheugengebruik toch behoorlijk. Genoeg om de performance totaal om zeep te helpen omdat de garbage collector het te druk had, bovendien werd de max. te gebruiken hoeveelheid geheugen overschreden.

Ik las elk textdocument in een enkel String object in. Vervolgens ging mijn (custom) tokenizer door die string heenwandelen om woordjes te vinden. Bepaalde gevonden woorden werden met textDocumentString.subString(begin,end) eruit geplukt, en in die hashtable gestopt.

Waar ging het nou mis? Bij String.subString()! Deze creeert namelijk niet per definitie een nieuw object, maar onthoudt de oorspronkelijke string (zo'n heel text document), en de offsets binnen die string. Met andere woorden, die hashtable bevatte op een gegeven moment een paar miljoen referenties naar volledige textdocumenten, waardoor het geheugen dus volliep. De oplossing: new String(bla.subString()), en de applicatie was (voor grote documenten-sets) opeens een factor X sneller (waarbij X ergens tussen 100 en 1000 lag!).

Dit terwijl ik dus zat te focussen op volledig andere stukken in de code, omdat ik de output van de profiler niet goed kon volgen.

I mentioned it once, but I think I got away with it.


Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Marcj schreef op dinsdag 08 mei 2007 @ 22:58:
[...]

Het nadeel van deze functie is natuurlijk wel dat excepties gooien wel een heel stuk trager zijn dan het parsen van een String (tot op zekere hoogte) ;) En aangezien de Integer.parseInt(s) (welke ik zou gebruiken) niets anders doet dan controleren of de String uit alleen maar cijfers bestaat (met eventueel een min ervoor) zou ik dit doen:

Java:
1
2
3
4
5
6
7
8
public boolean isInteger(String s) {
  for(int i = s.length() - 1; i >= 0; i--) {
    if(s.charAt(i) < '0' || s.charAt(i) > '9') {
      return (i == 0 && s.length() > 1 && s.charAt(0) == '-');
    }
  }
  return s.length() > 0;
}


:P Wie ziet hier nog een mogelijke fout in? (Ook de String "-" wordt nu niet meer gezien als integer namelijk ;))
Dit is best wel een snelle methode.

Je kunt hiervoor ook String#matches() gebruiken ipv NFE te misbruiken. In geval van success-matches is deze slechts fractioneel (~10%) langzamer dan proberen om een Integer ervan te maken. Maar in geval van het falen is matches() zeker 5x (500%) sneller dan wanneer er een NFE wordt geworpen. Zie ook http://balusc.xs4all.nl/s...e.html#StringNumbersCheck

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


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 10:15

MBV

Erkens schreef op woensdag 09 mei 2007 @ 07:58:
[...]

wat bedoel je met "constant" :?
maar verder, vind je werkelijk de die 2e versie beter leesbaar? ik zie daar als eerste een endless loop dan dat ik zie dat je door een array loopt. Leebaarheid van de code staat bij op de eerste plaats, daarna komt eventueel performance.
Ik bedoel idd dat de 2e in bijna constante tijd loopt. Als in: wanneer je van 10.000 naar 20.000 gaat, wordt de looptijd niet 2x zo lang maar 6/5x ofzo. Ik zou het eens uit moeten testen met Java6, maar daar heb ik nu geen zin in.

Of ik dit soort code zou schrijven? Alleen als het ergens een bottleneck vormt, en dan met duidelijk commentaar wat het doet. Misschien zelfs in een aparte functie als fastArraySum o.i.d.
HawVer schreef op woensdag 09 mei 2007 @ 08:27:
[...]

Zou hij constante tijd bedoelen? Beide loops doen exact hetzelfde dus het lijkt me niet een verschil in performance.
Mag jij me uitleggen wat jij dan met performance bedoelt, als de performance gelijk is met verschillende executietijd ;)

[ Voor 20% gewijzigd door MBV op 09-05-2007 11:41 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op woensdag 09 mei 2007 @ 02:04:
[...]

Wat wil je nou zeggen, klopt wel maar klopt niet? :)
Wat ik wil zeggen is dat er een groot verschil zit tussen je app compileren met exception support en je app compileren zonder exception support. Het daadwerkelijk wel of niet gebruiken van exceptions terwijl er wel support voor is maakt idd niet zo heel erg veel uit. Het was bedoeld als aanvulling op jouw reactie, ik zeg niet dat je ongelijk hebt oid :)
[.. leuk verhaal ..]

Nu mijn punt: het bovenstaande verhaal behoort niet tot de standaard-werkzaamheden van de gemiddelde programmeur. En die van jou - games developen - ook niet. Voor dat soort dingen gelden m.i. andere maatstaven, waar inderdaad de door jou genoemde opmerking van toepassing is. Aan de andere kant ben ik van mening dat het voor het standaard-werk (C++) kwa performance in het algemeen niet bijster spannend is of iemand exceptions gebruikt of niet.
Helemaal mee eens en ik wil ook niemand aanraden om je C++ apps maar zonder exception support te compileren :). Exceptions zijn A Good ThingTM (mits juist toegepast).
Terzijde: je klinkt als iemand die boeiend werk doet.
Klopt :Y) (dat ik boeiend werk doe, of ik zo klink weet ik niet :P). Zie m'n sig voor een van onze titles.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

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

Robtimus

me Robtimus no like you

HawVer schreef op woensdag 09 mei 2007 @ 08:27:
[...]

Zou hij constante tijd bedoelen? Beide loops doen exact hetzelfde dus het lijkt me niet een verschil in performance.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class Test
{
    public static void main(String[] args)
    {
        int count = Integer.MAX_VALUE;
        int[] array = new int[count];
        for (int i = 0; i < count; i++)
        {
            array[i] = i;
        }
        long total = 0;
        long start = System.currentTimeMillis();
        for (int i = 0; i < array.length; i++)
        {
            total += array[i];
        }
        long time = System.currentTimeMillis() - start;
        System.out.println(total + ": " + time);
        total = 0;
        int i = 0;
        start = System.currentTimeMillis();
        try
        {
            while (true)
            {
                total += array[i++];
            }
        }
        catch (IndexOutOfBoundsException e)
        {
            time = System.currentTimeMillis() - start;
            System.out.println(total + ": " + time);
        }
    }
}

code:
1
2
3
D:\>java -Xmx512m Test
4999999950000000: 672
4999999950000000: 719

Er is dus wel een verschil in performance, van gemiddels zo'n 50ms.

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


Acties:
  • 0 Henk 'm!

  • HawVer
  • Registratie: Februari 2002
  • Laatst online: 13-09 16:51
Oke! Nou weer wat geleerd. Het zal wel te maken hebben met het aantal instructies.

http://hawvie.deviantart.com/


Acties:
  • 0 Henk 'm!

  • Blackbird-ce
  • Registratie: September 2005
  • Laatst online: 25-09 23:47
Komt dat niet simpelweg omdat er in het tweede geval nog een error gegooid wordt? Vraag me af of er veel verschil is als je de while-loop uit het try-catch block trekt en er een while(i < count) van maakt.
(kan hem zelf helaas niet testen op het moment)

[ Voor 10% gewijzigd door Blackbird-ce op 09-05-2007 12:44 ]


Acties:
  • 0 Henk 'm!

  • Fiander
  • Registratie: Februari 2001
  • Laatst online: 28-05 12:35
MBV schreef op woensdag 09 mei 2007 @ 11:40:
Ik bedoel idd dat de 2e in bijna constante tijd loopt. Als in: wanneer je van 10.000 naar 20.000 gaat, wordt de looptijd niet 2x zo lang maar 6/5x ofzo. Ik zou het eens uit moeten testen met Java6, maar daar heb ik nu geen zin in.

Of ik dit soort code zou schrijven? Alleen als het ergens een bottleneck vormt, en dan met duidelijk commentaar wat het doet. Misschien zelfs in een aparte functie als fastArraySum o.i.d.
dus behalve dat die tweede ( in verhouding ) onleesbaar is, ( veel moeite doen om op het oog te bepalen waneer iets stopt. ) gaat bij een verdubbeling van het aantal iteraties de doorlooptijd met een factor 5 a 6 omhoog ??

En waarom zou ik dat ooit willen gebruiken ? het is moeilijker te lezen, en trager met gekke factor.

edit : of bedoel je letterlijk 6 delen door 5 keer (1.2x) ? want dat zou ik nog moeilijker te geloven vinden.

[ Voor 6% gewijzigd door Fiander op 09-05-2007 12:50 ]

Deze sig is een manueel virus!! Als je dit leest heb je het. Mail dit bericht naar iedereen die je kent, en verwijder alle bestanden van je computer.


Acties:
  • 0 Henk 'm!

  • Marcj
  • Registratie: November 2000
  • Laatst online: 19:07
IceManX schreef op woensdag 09 mei 2007 @ 12:35:
[...]
...
code:
1
2
3
D:\>java -Xmx512m Test
4999999950000000: 672
4999999950000000: 719

Er is dus wel een verschil in performance, van gemiddels zo'n 50ms.
Die 50 ms komt me wel bekent voor als de tijd die nodig is voor het gooien van een exceptie. Daarom zei ik ook dat excepties wel goed zijn, maar alleen moeten worden gebruikt om een exceptioneel geval af te vangen en niet in de normale control flow. Je moet er toch niet aan denken dat er tientallen of zelfs honderden excepties per seconde worden aangemaakt puur om te kijken of iets een cijfer is of niet...

Maar nogmaals: excepties zijn goed, zolang goed gebruikt! (zoals eigenlijk alles binnen een programmeertaal ;))

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 10:15

MBV

Fiander schreef op woensdag 09 mei 2007 @ 12:48:
[...]


dus behalve dat die tweede ( in verhouding ) onleesbaar is, ( veel moeite doen om op het oog te bepalen waneer iets stopt. ) gaat bij een verdubbeling van het aantal iteraties de doorlooptijd met een factor 5 a 6 omhoog ??

En waarom zou ik dat ooit willen gebruiken ? het is moeilijker te lezen, en trager met gekke factor.

edit : of bedoel je letterlijk 6 delen door 5 keer (1.2x) ? want dat zou ik nog moeilijker te geloven vinden.
die 2e, 6 delen door 5. Dat was het verhaal wat hij toen vertelde, ik heb het nooit getest. Er zijn mogelijke verklaringen voor, maar erg plausibel vond ik ze niet. Gewoon een rariteit uit de JVM van toen gok ik ;)

Misschien ligt het eraan dat array.length een soort van functie is/was? Zo werkt dat iig in PHP. En als je elke iteratie een functie uitvoert, is dat natuurlijk erg sloom ;)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

MBV schreef op woensdag 09 mei 2007 @ 11:40:
[...]

Ik bedoel idd dat de 2e in bijna constante tijd loopt. Als in: wanneer je van 10.000 naar 20.000 gaat, wordt de looptijd niet 2x zo lang maar 6/5x ofzo. Ik zou het eens uit moeten testen met Java6, maar daar heb ik nu geen zin in.
Tja, O(2n) of O(1.2n), het blijft O(n) en dus linair :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 10:15

MBV

.oisyn schreef op woensdag 09 mei 2007 @ 15:14:
[...]


Tja, O(2n) of O(1.2n), het blijft O(n) en dus linair :)
ik ben de laatste om dat te ontkennen. Alleen zijn er situaties waar ik liever een theta(0.0001n^2) dan theta(1337n) algoritme gebruik, ondanks dat theta(1337n) <= theta(0.0001n^2) :P

edit:
voor degenen die het niet weten: O(n) betekent dat de tijd* maximaal lineair groeit, dus 2x zoveel erin is maximaal 2x zoveel tijd. theta(n) betekent dat de tijd strict lineair groeit, dus 2x zoveel erin is ook minimaal 2x zoveel tijd eruit.
* tijd is meest gebruikelijk, mag ook geheugengebruik ofzo zijn.

[ Voor 30% gewijzigd door MBV op 09-05-2007 15:22 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Dat ontken ik ook niet, maar de opmerking van je docent dat het met exceptions ineens constant wordt slaat natuurlijk als een lul op een drumstel ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • writser
  • Registratie: Mei 2000
  • Laatst online: 15:05
De docent in kwestie is ook een slecht programmeervoorbeeld.

Onvoorstelbaar!


Acties:
  • 0 Henk 'm!

Verwijderd

@.oisyn: Ah, vanuit die hoek. Dan zijn we het eens. Nog bedankt voor de aanvulling :) .

Ik wil bij dezen nog een toelichting geven op mijn stelling dat het afhandelen van een exception in C++ iha. een te verwaarlozen tijd kost is. Dat is in algemene zin zo, maar er zijn situaties denkbaar waar andere factoren (onverwacht?) een mede-rol gaan spelen, en niet zo'n kleine ook. Ik wil dat demonstreren middels het volgende, op dat van IceManX gebaseerde, programmaatje (3 files):

tarr.hpp:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef __TARR_HPP__
#define __TARR_HPP__


// YStd include files

#ifndef __YSTD_YTIMER_HPP__
#include  "ytimer.hpp"
#endif


// Array size (1 GB will do)
#define ARR_SIZE    (INT_MAX / (2 * sizeof(int)))


typedef
struct  TArr
{
    // The referator
    int &  operator[] (int);

    // The data
    int  m_nData [ARR_SIZE];

    // For logging exception throw time
    static  YStd::YTimerUs  *  s_pcThrowTime;

} TArr;


#endif  // __TARR_HPP__



tarr.cpp:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include  "tarr.hpp"


/*
 *  Return a ref to the object at the specified position
 */

int &
TArr::operator [] (int nIdx)
{
    if (nIdx >= ARR_SIZE)
    {
        s_pcThrowTime->Update();
        throw 0;
    }

    return m_nData[nIdx];
}


/*static*/  YStd::YTimerUs  *  TArr::s_pcThrowTime;


#pragma warning ( disable : 4514 )


main.cpp:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include  "tarr.hpp"


int
main (void)
{
    YStd::YTimerUs  cThrowTime;
    TArr::s_pcThrowTime = &cThrowTime;

    /*
     *  0) Init
     */

    TArr *  pcArr  =  new TArr;

    for (int nIdx = 0;  nIdx < ARR_SIZE;  ++nIdx)
    {
        pcArr->m_nData[nIdx] = nIdx;
    }


    /*
     *  1) For-loop: no thry/catch, no throw
     */

    YStd::YTimerUs  cStart;
    long  lTotal  =  0;
    for (nIdx = 0;  nIdx < ARR_SIZE;  ++nIdx)
    {
        lTotal += (*pcArr)[nIdx];
    }
    YStd::YTimerUs  cEnd;
    printf ("Loop #1 took %ld ms, total = %ld\n", (cEnd - cStart) / 1000, lTotal);


    /*
     *  2) For-loop: thry/catch, no throw
     */

    cStart.Update();
    lTotal = 0;
    try
    {
        for (nIdx = 0;  nIdx < ARR_SIZE;  ++nIdx)
        {
            lTotal += (*pcArr)[nIdx];
        }
    }
    catch (...)
    {
    }
    cEnd.Update();
    printf ("Loop #2 took %ld ms, total = %ld\n", (cEnd - cStart) / 1000, lTotal);


    /*
     *  3) Infinite-loop, thry/catch, throw
     */

    cStart.Update();
    lTotal = 0;

    try
    {
        for (nIdx = 0;  /*empty*/ ;  /*empty*/)
        {
            lTotal += (*pcArr)[nIdx++];
        }
    }
    catch (...)
    {
    }

    cEnd.Update();
    printf ("Loop #3 took %ld ms, total = %ld\n", (cEnd - cStart) / 1000, lTotal);
    printf ("Handling the exception did cost %ld us\n", cEnd - cThrowTime);

    return 0;
}

#pragma warning ( disable : 4514 )


De reden van het verdelen van de code over drie files wordt later duidelijk.

Het programma (gebouwd met VS in release mode) heeft de volgende uitvoer:
code:
1
2
3
4
Loop #1 took 1326 ms, total = -402653183
Loop #2 took 1476 ms, total = -402653183
Loop #3 took 1474 ms, total = -402653183
Handling the exception did cost 18 us

Merk om te beginnen op dat timing-resultaten nooit helemaal stabiel zijn in een multi-process omgeving. Dit verklaart de verschillen tussen loops #2 en #3. Bij andere runs kunnen de loop-tijden enkele ms varieren. De exception handling tijd van 18 us lag bij diverse tests tussen de 10 en 20 us.

Conclusie: ondanks de variatie is de afhandelingstijd van de exception in de orde van 0.001% van de loop0tijd. Uitzonderingssituaties daargelaten, dus verwaarloosbaar.

Er is echter nog een andere factor van belang. De oplettende lezer vraagt zich vast al af waarom loop #2 evenveel tijd kost als loop #3, in plaats van evenveel als loop #1.

Wel, dat wordt veroorzaakt door de optimizer. Bovenstaande code heb ik gecompileerd in release mode met optimize-for-speed. Wanneer we nu de door de compiler gegenereerde code voor de loops 1 & 2 bekijken, dan valt ogenblikkelijk iets afwijkends op @ 00192:

inner-loop #1
GAS:
1
2
3
4
5
6
7
8
9
10
11
12
13
$L65344:

; 31   :     {
; 32   :        lTotal += (*pcArr)[nIdx];

000da   56               push    esi
000db   8b cb            mov     ecx, ebx
000dd   e8 00 00 00 00   call    ??ATArr@@QAEAAHH@Z     ; TArr::operator[]
000e2   03 38            add     edi, DWORD PTR [eax]
000e4   46               inc     esi
000e5   81 fe ff ff ff
        0f               cmp     esi, 268435455         ; 0fffffffH
000eb   72 ed            jb      SHORT $L65344

inner-loop #2
GAS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$L65352:

; 45   :        {
; 46   :            lTotal += (*pcArr)[nIdx++];

00185   8b c6            mov     eax, esi
00187   50               push    eax
00188   8b cb            mov     ecx, ebx
0018a   46               inc     esi
0018b   e8 00 00 00 00   call    ??ATArr@@QAEAAHH@Z     ; TArr::operator[]
00190   03 38            add     edi, DWORD PTR [eax]
00192   89 7d ec         mov     DWORD PTR _lTotal$[ebp], edi

; 47   :        }

00195   eb ee            jmp     SHORT $L65352


In loop 2 wordt - in tegenstelling tot in loop 1 - de waarde van lTotal niet in een register gehouden, maar naar het main memory geschreven. De reden voor het schrijven is natuurlijk dat de scope van lTotal het try/catch block van loop #2 extends. En omdat de waarde van lTotal consistent moet zijn, mag de optimiser de waarde dus niet binnen de loop in een register cachen. En dat kost tijd, ondanks een L1/L2/L3 cache. Hoewel de tijdsduur van één MOV(mem,reg) te verwaarlozen is, geldt dat niet meer per sé voor 2^28 MOVs cumulatief...
Wordt in loop #1 een exception gethrowd, dan wordt deze buiten de scope van lTotal gevangen (of helemaal niet natuurlijk). Dus kan in loop #1 lTotal wél in een register gecached worden. Waarmee het verschil in performance-verlies tussen de loops 1 en 2 verklaard is.

Merk op dat de code van TArr::operator[] zich in een andere file bevindt, dus de optimizer kan niet het gehele executie-pad zien. Is dat wel het geval, dan is de optimiser in staat om in loops 1 & 2 te constateren dat de boundary-check binnen TArr::operator[] nooit true oplevert, en dus weggelaten mag worden. Dit levert een aanzienlijke versnelling op, die de vergelijking tussen de loops volledig zou verstoren. Hiermee is de reden gegeven, waarom ik de code over drie files verdeeld heb.

Moraal van het C++ verhaal: theorieën kunnen leuk zijn, maar meten = weten. Dit voorbeeld laat zien dat het heel eenvoudig is om in een verkeerde richting te zoeken: de introductie van een try/catch blok vanwege optimiser-afhankelijkheden heeft in dit voorbeeld (indirect!) een aanzienlijk grotere invloed op de overall-performance (10%), dan het gooien & afhandelen van die ene exception (0.001%).

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 10:15

MBV

.oisyn schreef op woensdag 09 mei 2007 @ 15:38:
Dat ontken ik ook niet, maar de opmerking van je docent dat het met exceptions ineens constant wordt slaat natuurlijk als een lul op een drumstel ;)
"Bijna constant", ik weet niet meer hoe hij dat zei. Als je tijd 5000 + 0,001n is, dan lijkt dat heel sterk op een constante functie ondanks dat het dat niet is. Ik zie daarbij geen lul en geen drumstel. Die docent raadde het ook niet als 'universele waarheid' aan, hij liet het meer zien als gekkigheidje :)

En die docent (Schepers) was de beste 'programmeer'-docent van de hele TH Rijswijk, misschien op Broeders na dan ;). Zit nu weer in het bedrijfsleven :)

[ Voor 26% gewijzigd door MBV op 09-05-2007 18:17 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op woensdag 09 mei 2007 @ 00:18:
Zo heb ik net nog een stukje code geschreven dat een bestand uitleest, waarbij hij niet naar een EOF kijkt, maar in dat geval de catch (EOFException) in schiet. Toch niets mis mee? Daar zijn ze voor :)
Daar zijn ze niet voor. Exceptions zijn situaties die je niet verwacht of had kunnen voorzien.
In jouw geval had je die EOF check prima in code kunnen afvangen. Komt die EOF dan onverwachts, dan is er niks mis met een exception handler. Maar exceptions gebruiken in de normale flow van je programma is IMHO doodgewoon een beroerd design.

Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Verwijderd schreef op woensdag 09 mei 2007 @ 23:27:
[...]
Daar zijn ze niet voor. Exceptions zijn situaties die je niet verwacht of had kunnen voorzien.
In jouw geval had je die EOF check prima in code kunnen afvangen. Komt die EOF dan onverwachts, dan is er niks mis met een exception handler. Maar exceptions gebruiken in de normale flow van je programma is IMHO doodgewoon een beroerd design.
Precies, daarom heten die dingen ook exceptions, uitzonderingen. Van een EOF weet je dat die eraan zit te komen, dus kan je het moeilijk een uitzondering noemen dat het voorkomt :)

Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
Verwijderd schreef op woensdag 09 mei 2007 @ 23:27:
Maar exceptions gebruiken in de normale flow van je programma is IMHO doodgewoon een beroerd design.
99 van de 100 keer, of 999 van de 1000 keer is dat zo. Heel af en toe echter is er wel eens een case waarbij het exception mechanisme als 'normale' control flow duidelijkere code oplevert. Vergelijk dit met het goto statement. Binnen 1 functie, kun je meerdere loops nesten, en dan ergens midden in de diepste loop iets vinden. Je kunt dan de goto (break to label in java) gebruiken om in 1 keer uit de tig geneste loops te komen. In elke loop condition een extra stop conditie inbouwen kan, maar leverd niet altijd duidelijke code op.

Als je nu die tig geneste loops vervangt door tig geneste functies, dan kan de exception handig zijn om in 1 keer naar de top level function te 'breaken'. Natuurlijk kun je in elke geneste functies speciale waardes gaan terug geven, daar in de oproepende functie op checken en dan in die functie meteen een return doen (etc voor de andere functies). Dat kan echter zeer onduidelijke code opleveren.

Maar van alle 100 duizenden regels code die ik in m'n leven geschreven heb, heb ik dit precies 1 keer echt nodig gehad ;)

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

Verwijderd

flowerp schreef op donderdag 10 mei 2007 @ 20:37:
[...]


99 van de 100 keer, of 999 van de 1000 keer is dat zo. Heel af en toe echter is er wel eens een case waarbij het exception mechanisme als 'normale' control flow duidelijkere code oplevert. Vergelijk dit met het goto statement. Binnen 1 functie, kun je meerdere loops nesten, en dan ergens midden in de diepste loop iets vinden. Je kunt dan de goto (break to label in java) gebruiken om in 1 keer uit de tig geneste loops te komen. In elke loop condition een extra stop conditie inbouwen kan, maar leverd niet altijd duidelijke code op.

Als je nu die tig geneste loops vervangt door tig geneste functies, dan kan de exception handig zijn om in 1 keer naar de top level function te 'breaken'. Natuurlijk kun je in elke geneste functies speciale waardes gaan terug geven, daar in de oproepende functie op checken en dan in die functie meteen een return doen (etc voor de andere functies). Dat kan echter zeer onduidelijke code opleveren.
Dan is het nog steeds een bad practise in dit voorbeeld. Ook bij geneste loops dien je er netjes uit te gaan en niet er uit te breaken met een exception omdat dat handig is...

Acties:
  • 0 Henk 'm!

Verwijderd

Erkens schreef op woensdag 09 mei 2007 @ 23:31:
Precies, daarom heten die dingen ook exceptions, uitzonderingen.
Verwijderd schreef op donderdag 10 mei 2007 @ 20:40:
Dan is het nog steeds een bad practise in dit voorbeeld.
Merkwaardig: ik zie hier driemaal een uitgesproken standpunt, en driemaal mis ik een degelijke, objectieve onderbouwing. Dus, heren?

Acties:
  • 0 Henk 'm!

  • Serpie
  • Registratie: Maart 2005
  • Laatst online: 01-07-2023
Verwijderd schreef op donderdag 10 mei 2007 @ 21:40:
Merkwaardig: ik zie hier driemaal een uitgesproken standpunt, en driemaal mis ik een degelijke, objectieve onderbouwing. Dus, heren?
Kwestie van 'Zo hoort het, dus zo moet het'? Ik heb er zelf ook vaak een handje van hoor moet ik zeggen.

Aan de andere kant geldt ook altijd:
- Als je de regels kent mag je ze breken.
- Uitzondering bevestigt de regel
etc.

Het is goed om richtlijnen, best practices en regels aan te houden. Maar er zijn situaties waarin een andere oplossing beter past, of sneller is.

Acties:
  • 0 Henk 'm!

Verwijderd

Verwijderd schreef op donderdag 10 mei 2007 @ 21:40:
[...]


[...]


[...]


Merkwaardig: ik zie hier driemaal een uitgesproken standpunt, en driemaal mis ik een degelijke, objectieve onderbouwing. Dus, heren?
Exceptions zijn bedoeld voor uitzonderingen op de normale programma flow. Situaties die alleen kunnen ontstaan door onverwachte gebeurtenissen. Bijvoorbeeld: Je hebt een applicatie die een webservice call doet, als de webservice eruit valt dan dien je een exception te gebruiken. Dit is immers een onverwachte situatie.

Daarnaast zijn exceptions wel degelijk "zwaar" om te gebruiken en kunnen ze er voor zorgen dat veel resources blijven hangen, waar ze reeds vrij gegeven waren.

Meer informatie:
http://www.javaworld.com/...999-06/04-exceptions.html
http://www.codeproject.co...hen_to_use_exceptions.asp

Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
Verwijderd schreef op donderdag 10 mei 2007 @ 20:40:
[...]
Dan is het nog steeds een bad practise in dit voorbeeld. Ook bij geneste loops dien je er netjes uit te gaan en niet er uit te breaken met een exception omdat dat handig is...
Kom op zeg ;) Ik leg net uit dat het bij zeer diepe nesting nogal wat 'clutter' veroorzaakt, en dat het af en toe een meer elegante manier is om het zo te doen. Die situatie is juist 1 van de vooraanstaande voorbeelden waar het redelijk algemeen geaccepteerd is -wel- een veredelde goto te gebruiken.

Er zijn grofweg 3 categorieën van programmeurs:

1) Beginners - Gebruiken en misbruiken alles wat ze maar voor handen krijgen. In het geval van goto zetten ze deze kris-kras door al hun code neer.

2) Gevorderden - Hebben geleerd dat sommige dingen 'evil' zijn en mijden dit. Ze weten echter niet altijd waarom het vermeden moet worden.

3) Professionals - Hebben grote kennis van de technieken die ze gebruiken. Kunnen beredeneren -waarom- en wanneer bepaalde technieken niet goed zijn, maar kunnen ook de situaties herkennen waarin die technieken wel nuttig toegepast kunnen worden.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

  • roy-t
  • Registratie: Oktober 2004
  • Laatst online: 19-09 10:19
flowerp schreef op donderdag 10 mei 2007 @ 20:37:
[...]


99 van de 100 keer, of 999 van de 1000 keer is dat zo. Heel af en toe echter is er wel eens een case waarbij het exception mechanisme als 'normale' control flow duidelijkere code oplevert. Vergelijk dit met het goto statement. Binnen 1 functie, kun je meerdere loops nesten, en dan ergens midden in de diepste loop iets vinden. Je kunt dan de goto (break to label in java) gebruiken om in 1 keer uit de tig geneste loops te komen. In elke loop condition een extra stop conditie inbouwen kan, maar leverd niet altijd duidelijke code op.

Als je nu die tig geneste loops vervangt door tig geneste functies, dan kan de exception handig zijn om in 1 keer naar de top level function te 'breaken'. Natuurlijk kun je in elke geneste functies speciale waardes gaan terug geven, daar in de oproepende functie op checken en dan in die functie meteen een return doen (etc voor de andere functies). Dat kan echter zeer onduidelijke code opleveren.

Maar van alle 100 duizenden regels code die ik in m'n leven geschreven heb, heb ik dit precies 1 keer echt nodig gehad ;)
Je kunt toch uit een diepe loop escapen door een simpel goto-tje?

Ik denk dat de meeste mensen hier niet willen dat je een Exception gebruikt om een stuk normale programma bezigheden te runnen door de overhead, je krijgt niet alleen de kans om een eigen stuk code uit te voeren, maar het hele programma (inc background workers en alles) wordt stopgezet totdat je stukje fout-afhandel code is uitgevoerd. (verschilt per taal/compiler natuurlijk)

Als je in een loop kunt zetten "if x = 10 then throw exception" dan kun je daar toch ook "if x = 10 then goto Afhandel" neer zetten, hier mee skip je een hoop overhead en toch ben je per direct uit de loop.

En als er helemaal geen overhead is (bijv je moet alle foutafhandel code zelf schrijven ook de stop / debug etc. code) dan is het misschien toch raar voor degene die later met je code moet werken, en een exception is ergens anders voor bedoelt (hoewel dat natuurlijk geen argument is)

:) zo zie ik het iig *denkt weer aan zijn geweldige eerste visual basic progje waar in ik alleen kon iffen (zonder else of meer statemensts in de if) en als er dus meer gebeuren moest ik met tientallen loopjes en gotos kwam :)

~ Mijn prog blog!


Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
therat10430 schreef op donderdag 10 mei 2007 @ 21:58:
[...]
Je kunt toch uit een diepe loop escapen door een simpel goto-tje?
Lees nog eens terug wat ik schreef ;) Voor geneste loops een goto/'break to label', maar in ieder geval in Java kan dat niet als je nestings bestaan uit method calls. Je gebruikt dan een exception (generieker: stack unwind) om uit de nested methods te 'breaken'.

Performance is geen issue als je nestings bestaan uit 1000'en itteraties en je er slechts 1 maal uit breaked.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

  • brama
  • Registratie: Februari 2001
  • Niet online
Serpie schreef op donderdag 10 mei 2007 @ 21:48:
[...]


Kwestie van 'Zo hoort het, dus zo moet het'? Ik heb er zelf ook vaak een handje van hoor moet ik zeggen.

Aan de andere kant geldt ook altijd:
- Als je de regels kent mag je ze breken.
- Uitzondering bevestigt de regel
etc.

Het is goed om richtlijnen, best practices en regels aan te houden. Maar er zijn situaties waarin een andere oplossing beter past, of sneller is.
Daar ben ik het roerend mee eens. Een bad practise != "altijd fout". Wat dat betreft vind ik dit een hele mooie uitleg dit netjes onderbouwt:

http://netevil.org/node.p...da-4c25-877e-e761c8fa4dc6

I mentioned it once, but I think I got away with it.


Acties:
  • 0 Henk 'm!

Verwijderd

flowerp schreef op donderdag 10 mei 2007 @ 21:57:
Kom op zeg ;) Ik leg net uit dat het bij zeer diepe nesting nogal wat 'clutter' veroorzaakt, en dat het af en toe een meer elegante manier is om het zo te doen. Die situatie is juist 1 van de vooraanstaande voorbeelden waar het redelijk algemeen geaccepteerd is -wel- een veredelde goto te gebruiken.
Eruit knallen is dus niet handiger en eleganter om uit een diep geneste loop te komen. Dat verandert namelijk je programma flow wat voor meer problemen kan zorgen dan het netjes af te handelen. Het zorgt dus voor meer onoverzichtelijkerheid en een grotere kans op bugs.
brama schreef op donderdag 10 mei 2007 @ 22:21:
[...]


Daar ben ik het roerend mee eens. Een bad practise != "altijd fout". Wat dat betreft vind ik dit een hele mooie uitleg dit netjes onderbouwt:

http://netevil.org/node.p...da-4c25-877e-e761c8fa4dc6
Ik krijg bij die blog meer het idee van: "Ik snap het niet waarom dit een bad practise zou zijn en vind hun dus maar dom, dus is het dom.". Het wordt ieg totaal niet onderbouwd en het enigste wat ie doet is zeiken. Imao een hele slechte blog mijns inziens.

[ Voor 35% gewijzigd door Verwijderd op 10-05-2007 22:28 ]


Acties:
  • 0 Henk 'm!

  • Erkens
  • Registratie: December 2001
  • Niet online

Erkens

Fotograaf

Verwijderd schreef op donderdag 10 mei 2007 @ 21:40:
Merkwaardig: ik zie hier driemaal een uitgesproken standpunt, en driemaal mis ik een degelijke, objectieve onderbouwing. Dus, heren?
lees aub ook de andere posts eens, ik ben echt niet van plan om in elke post mijn argumenten te gaan herhalen, maargoed ik zal speciaal nogmaals het belangrijkste argument herhalen: "leesbaarheid van de code"

Als je een exception moet afvangen om ervoor te zorgen dat je program flow doorgaat is er imo iets goed mis. Je weet bijvoorbeeld voor 100% zeker dat er ooit een einde aan een file komt, waarom dan toch domweg door blijven lezen totdat je een error krijgt?

Maargoed, genoeg over dit onderwerp in dit topic. Wellicht een idee om over dit onderwerp een nieuw topic te openen (al dan niet afsplitsen) zodat "we" weer ontopic kunnen :)

Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
Verwijderd schreef op donderdag 10 mei 2007 @ 22:25:
[...]
Eruit knallen is dus niet handiger en eleganter om uit een diep geneste loop te komen. Dat verandert namelijk je programma flow
Het veranderen van de programma flow en state is juist de taak van een imperatief programma. Je bedoeld dat het in een gestructureerde manier dient te gebeuren. Als er niets netjes valt af te handelen is het soms onzin om dan toch maar 'iets' te gaan afhandelen, omdat dat netjes is.

Een triviaal voorbeeld, stel je voor dat we aan de hand van 4 variablen, een find first search doen. In de innermost loop bepalen we of we een hit hebben. Zodra we die hebben kunnen we uit de gehele geneste structuur breaken:


Java:
1
2
3
4
5
6
7
8
9
10
11
for ( foo : foos ) {
   for ( bar : bars) {
      for ( kaz : kazs) {
         for( zap: zaps) {
            if ( myObj.check( foo, bar, kaz, zap ) {
                // we have a hit
            }
         }
      }
   }
}


Je kunt dit nu herschrijven, en overal een boolean (found == true) checken. Maakt de code er niet mooier op. En waarom? Er is helemaal niets dat netjes moet worden afgesloten. Na de hit wil je gewoon uit de geneste structuur. Nu is dit een redelijk triviaal voorbeeld, maar stel je een iets meer complexere situatie voor, waarbij er mogelijk nog code komt na elke loop, en je mag overal extra if statements tussen gaan prakken.

Stel je nu eens voor dat er 2 situaties zijn waarmee je uit de structuur moet, bv een limit die exceeded wordt. Ga je dan overal 2 conditionals achter zetten? ( found == true && limit == true) of maak je een nieuwe boolean die je break noemt? Dan zet je overal ( break == true ) achter, zodat je midden in de loop break = true; kan zetten. Maar... dan heb je gewoon zelf min of meer de break functionaliteit nagemaakt op een minder goed leesbare manier.

In dat geval zet je gewoon dit neer:

Java:
1
2
3
4
5
6
7
8
9
10
11
12
outerloop: for ( foo : foos ) {
   for ( bar : bars) {
      for ( kaz : kazs) {
         for( zap: zaps) {
            if ( myObj.check( foo, bar, kaz, zap ) {
                // we have a hit
                break outerloop;
            }
         }
      }
   }
}


Soms is het ook twijfelachtig of iets een 'uitzondering' is. Stel je de volgende pseudo servlet code voor.

Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public void service(HttpServletRequest request,HttpServletResponse response) {

    // pre-process request.
    // [... code... ]

    Object obj1 = getFromRemoteServer("server1" );
    
    // Do lots of stuff with obj

    Object obj2 = getFromRemoteServer("server2" );
}

Object getFromRemoteServer() {
    // Get server credentials
    // [... code ...]

    // Set up initial connection
    // [ ... expensive code ...]

   LogInToRemoteServer();

   // Retrieve Object, do some processing, etc...
}

void LogInToRemoteServer() {

   // [ ... code ... ]

   // First point we can determine user is not loggedin
   // 
   // Redirect to remote server and Throw Exception if not loggedin?
   // 
}


In bovenstaande geval -kun- je redeneren dat het niet ingelogt zijn van de user op de remote server geen uitzondering is; users zijn tenminste altijd 1 maal nog niet ingelogd. Voor de 'gewone' flow van het programma is het echter wel een uitzondering.

Je kunt hier ook van te voren een check doen; een reeks calls die begint met iets als if (UserLoggedInToRemote() ) en dan pas getFromRemoteServer();. Dit kan echter, afhankelijk van de rest van het design, een nogal dure en in de meeste gevallen overbodige operatie zijn. Een alternatief zou dan kunnen zijn:

Java:
1
2
3
4
5
6
7
8
try {
   getFromRemoteServer("1");
   // ...
   getFromRemoteServer("2");
}
catch( UserNotLoggedInException exc ) {
   return;
}

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

Verwijderd

flowerp schreef op donderdag 10 mei 2007 @ 23:39:

Java:
1
2
3
4
5
6
7
8
9
10
11
for ( foo : foos ) {
   for ( bar : bars) {
      for ( kaz : kazs) {
         for( zap: zaps) {
            if ( myObj.check( foo, bar, kaz, zap ) {
                // we have a hit
            }
         }
      }
   }
}
Dat is slechte code bij design. Als je zoiets tegen komt moet je je design herzien...

Een UserNotLoggedInException gooien is op zich logisch als de voorgeschreven flow is:
-> Inloggen
-> Acties

Dit zul je dus tegen komen bij LDAP, SSO enz.. situaties. Hier is een exception gerechtvaardigd, alhoewel je dan eigenlijk al niet bij de Acties aanroep zou mogen uit komen natuurlijk.

[ Voor 24% gewijzigd door Verwijderd op 11-05-2007 00:12 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Erkens schreef op woensdag 09 mei 2007 @ 23:31:
Van een EOF weet je dat die eraan zit te komen, dus kan je het moeilijk een uitzondering noemen dat het voorkomt :)
Moeilijk? Nou, nee hoor. Want heb je wel eens van unexpected EOF gehoord? Als ik bijvoorbeeld bij het maken van een complexe scanner kan kiezen tussen een wagonlading tests als 'if (! bEOF) ...' en een try/catch/throw, dan kies ik toch echt voor het laatste. Want dan wordt mijn code kleiner en leesbaarder. En op het aspect control-flow eenvoudiger - en dus binnen kortere tijd! - correct te krijgen.
Verwijderd schreef op woensdag 09 mei 2007 @ 23:27:
[...]
In jouw geval had je die EOF check prima in code kunnen afvangen.
Goed mogelijk, maar niet zeker. Zolang we zijn code niet hebben gezien, kunnen we daar alleen maar over speculeren.
Daar zijn ze niet voor. Exceptions zijn situaties die je niet verwacht of had kunnen voorzien.
Met alle respect: dat is geen absolute waarheid, maar een filosofische kwestie. Probeer eens onderscheid te maken tussen het concept 'exception', en de taalconstructie die 'exception' heet (en dan nog eens voor verschillende programmeertalen - got the point?). Het lijkt logisch het concept te implementeren met de taalconstructie. Maar waarom zou je toepassing van die taalconstructie uitsluitend daartoe beperken?
Maar exceptions gebruiken in de normale flow van je programma is IMHO doodgewoon een beroerd design.
Het is je volste recht om die mening te hebben. Maar als je het zo zwart-wit stelt, dan vind ik dat een duidelijke vorm van hokjesdenken. Exceptions vormen simpelweg een deel van de taal, niets meer en niets minder. Daar kan dan wel een filosofie achter zitten, maar die is niet meer dan een aanwijzing voor het toepassen, en geen verplichting. Als je voldoende weet hoe het werkt en wat de effecten zijn, dan zijn er m.i. geen zwaarwegende argumenten om het alleen toe te passen 'zoals het bedoeld is'.

Het is niet voor niets dat hier (Java) letterlijk staat:
In such situations, however, you must handle the exception anyway, so the cost is tolerable.
en hier (.NET)
A more helpful rule of thumb could be:
staat in plaats van obligation.

Voor alle duidelijkheid: ik pleit niet voor, even plat gezegd, het bij elke gelegenheid aangrijpen om de 'trukendoos' tot op de bodem toe te passen. Maar als ik tijdens een codereview constateer dat een programmeur een exception gebruikt als elegante escape-mogelijkheid, hij (m/v) laat zien goed te weten waar hij mee bezig is, en hij heeft het goed gedocumenteerd, dan krijgt hij daar een positieve waardering voor. Omdat hij laat zien de materie te beheersen, en omdat hij ook heeft laten zien op dat gebied buiten hokjesdenken te kunnen treden.

En bedenk: een programmeertaal is voor een programmeur (puristen en zo buiten beschouwing gelaten) een hulpmiddel, niet een doel op zich. De eindgebruiker is niet geïnteresseerd of een programma nu wel of niet exceptions gebruikt, maar of het doet wat het moet doen.
Verwijderd schreef op donderdag 10 mei 2007 @ 21:53:
Daarnaast zijn exceptions wel degelijk "zwaar" om te gebruiken
Heb je deze post, waarin ik met meetgegevens en verklaringen aan kom zetten, eigenlijk wel gelezen? Of staat mijn conclusie daarin je niet aan?
Verwijderd schreef op donderdag 10 mei 2007 @ 21:53:
en kunnen ze er voor zorgen dat veel resources blijven hangen, waar ze reeds vrij gegeven waren.
1) Kunnen != moeten.
2) Als jij alleen voor Java of zo spreekt, zeg dat er dan bij. Want voor C++ is dit dus echt een onzinnig statement.
Eruit knallen is dus niet handiger en eleganter om uit een diep geneste loop te komen. Dat verandert namelijk je programma flow wat voor meer problemen kan zorgen dan het netjes af te handelen. Het zorgt dus voor meer onoverzichtelijkerheid en een grotere kans op bugs.
Nofi en met alle respect, maar als je dit zo algemeen stelt, dan zeg ik: probeer je blikveld eens wat te verruimen.

Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
Verwijderd schreef op vrijdag 11 mei 2007 @ 00:09:
[...]

Dat is slechte code bij design. Als je zoiets tegen komt moet je je design herzien...
Dat is een standaard sequentiële search in een (ongeordende) 4D structuur. Kom jij dan maar eens met een voorstel om dat met een 'netter' algoritme te doen.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

Verwijderd

Serpie schreef op donderdag 10 mei 2007 @ 21:48:
Het is goed om richtlijnen, best practices en regels aan te houden. Maar er zijn situaties waarin een andere oplossing beter past, of sneller is.
:)
flowerp schreef op donderdag 10 mei 2007 @ 21:57:
Er zijn grofweg 3 categorieën van programmeurs:
Inderdaad. En je omschrijving van categorie 3 zou een stimulans kunnen zijn voor programmeurs in de andere categorieën.
flowerp schreef op donderdag 10 mei 2007 @ 22:18:
Performance is geen issue als je nestings bestaan uit 1000'en itteraties en je er slechts 1 maal uit breaked.
Nuancering rules :) . Net verhaal trouwens @ 23:39.
Verwijderd schreef op vrijdag 11 mei 2007 @ 00:09:
[... 4-diep geneste for-loop ...]

Dat is slechte code bij design. Als je zoiets tegen komt moet je je design herzien.
Twee vragen:
1) waar doel je nou op: de nestingdiepte, de exception, of iets anders?
2) waarom vind je dat?

Acties:
  • 0 Henk 'm!

  • MBV
  • Registratie: Februari 2002
  • Laatst online: 10:15

MBV

flowerp schreef op donderdag 10 mei 2007 @ 21:57:
[...]

Dat is een standaard sequentiële search in een (ongeordende) 4D structuur. Kom jij dan maar eens met een voorstel om dat met een 'netter' algoritme te doen.
Ok. Gesteld dat je meer dan 1 element wilt hebben: in een zoekboom o.i.d. gooien, en dan zoeken :P

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Verwijderd schreef op vrijdag 11 mei 2007 @ 00:33:
Met alle respect: dat is geen absolute waarheid, maar een filosofische kwestie. Probeer eens onderscheid te maken tussen het concept 'exception', en de taalconstructie die 'exception' heet (en dan nog eens voor verschillende programmeertalen - got the point?). Het lijkt logisch het concept te implementeren met de taalconstructie. Maar waarom zou je toepassing van die taalconstructie uitsluitend daartoe beperken?
Ah, dus je kan ook een loop-constructie zoals een while gebruiken om dingen te testen zonder ooit te loopen, en functies hoeven niet per se een functioneel geheel te zijn maar die kun je naar eigen inzicht door elkaar rijgen totdat je een lappendeken hebt die niemand meer begrijpt? :)

Exceptions zijn niet voor niets exceptions genoemd. Een exceptie is volgende het woordenboek een uitzonderingssituatie. Die naamgeving is écht niet zomaar gekozen door de ontwikkelaars van de taal. Als je bij het lezen van een bestand wéét je dat EOF er op die plek aan kan komen in je normale program flow, dan is het ook géén uitzondering wanneer dat gebeurt. Om die reden is het wat mij betreft ook erg krom om uitgerekend daarvoor een exception te gaan misbruiken.

En wat betreft degene die hierboven riep dat het gebruik van een extra "&& !EOF" in elke loop/if in een constructie minder leesbaar is dan uit de constructie springen met een exception: wat rook jij? :P Het kost geen moeite om die extra 7 karakters op te nemen, en het blijft leesbaarder dan wanneer je uit je code breekt. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

flowerp schreef op donderdag 10 mei 2007 @ 22:18:
Lees nog eens terug wat ik schreef ;) Voor geneste loops een goto/'break to label', maar in ieder geval in Java kan dat niet als je nestings bestaan uit method calls. Je gebruikt dan een exception (generieker: stack unwind) om uit de nested methods te 'breaken'.

Performance is geen issue als je nestings bestaan uit 1000'en itteraties en je er slechts 1 maal uit breaked.
Ik vind het eigenlijk een vrij slecht voorbeeld aangezien je met een setje methodes en wat return statements (doorgaans) veel leesbaardere code en geen break en exceptie geneuzel nodig hebt.
==========
Ik ben tot nu toe 1 situatie tegengekomen in Java waar het Exceptie mechanisme op een vrij nette manier gebruikt wordt in de normale flow. Namelijk bij het product OsCache. Dat ziet er vereenvoudigd zo uit:
Java:
1
2
3
4
5
6
7
try {
   return cacheManager.getFromCache("cacheKey");
} catch (NeedsRefreshException e) {
   Object cachedObject = new Object();
   cacheManager.storeInCache("cacheKey", cachedObject);
   return cachedObject;
}


Op deze manier hoef je als ontwikkelaar je helemaal niet bezig te houden met concurrency, dat zit allemaal achter de schermen. Je hebt ook geen wrapper objecten nodig om de state van een bepaalde cache waarde te bepalen.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

-NMe- schreef op vrijdag 11 mei 2007 @ 11:03:
Bij het lezen van een bestand wéét je dat EOF eraan komt, dus het is ook géén uitzondering wanneer dat gebeurt.
Die bewering is onzin natuurlijk, als ik bijvoorbeeld mijn bestanden lees verwacht ik nóóit een EOF. Als er dan wel een blijkt te komen is die weldegelijks onverwachts. Mijn situatie is natuurlijk niet "lees alle regels uit een textfile" maar "unserialize een bepaalde datastructuur". Ik ga niet tijdens het unserializen de hele tijd testen op EOF, want die zou gewoonweg niet moeten komen. Niet omdat mijn files oneindig groot zijn, maar omdat het aantal bytes dat ik moet lezen deterministisch is (adhv de data die ik al heb uitgelezen). Een EOF is in zo'n geval wél een uitzondering, en derhalve klopt jouw bewering niet (dat je het altijd weet).

Testen op EOF kun je imho het beste doen daar waar je 'm verwacht (bijvoorbeeld nadat je een getline() gedaan hebt), niet daar waar je 'm niet verwacht (bijvoorbeeld als de regels die je uit het textbestand aan het lezen bent altijd in groepjes van 4 afgehandeld worden, waardoor je 4x getline() doet en dan pas een EOF test)

[ Voor 15% gewijzigd door .oisyn op 11-05-2007 12:04 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • BalusC
  • Registratie: Oktober 2000
  • Niet online

BalusC

Carpe diem

Dat hangt ook af van het gebruikte programmeertaal lijkt me. In Java en C zullen EOF dingen ongetwijfeld beter implementeerbaar zijn dan in PHP.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 11 mei 2007 @ 11:41:
[...]
Ik vind het eigenlijk een vrij slecht voorbeeld aangezien je met een setje methodes en wat return statements (doorgaans) veel leesbaardere code en geen break en exceptie geneuzel nodig hebt.
==========
Ik ben tot nu toe 1 situatie tegengekomen in Java waar het Exceptie mechanisme op een vrij nette manier gebruikt wordt in de normale flow. Namelijk bij het product OsCache. Dat ziet er vereenvoudigd zo uit:
Java:
1
2
3
4
5
6
7
try {
   return cacheManager.getFromCache("cacheKey");
} catch (NeedsRefreshException e) {
   Object cachedObject = new Object();
   cacheManager.storeInCache("cacheKey", cachedObject);
   return cachedObject;
}


Op deze manier hoef je als ontwikkelaar je helemaal niet bezig te houden met concurrency, dat zit allemaal achter de schermen. Je hebt ook geen wrapper objecten nodig om de state van een bepaalde cache waarde te bepalen.
Ik zie niet in waarom dat niet zo zou kunnen:
Java:
1
2
3
4
5
6
7
Object o = cacheManager.getFromCache("cacheKey");
if (o == null)
{
    o = new Object();
    cacheManger.storeInCache("cacheKey", o);
}
return o;

Dezelfde argumenten die jij geeft gelden ook voor dit stukje code (ergo, het zijn geen argumenten voor het gebruik van exception). Uiteraard ga ik ervanuit dat je zelf controle hebt over de implementatie van de cachemanager, want dat is nou juist waar het hier om gaat in de discussie - als een 3rd party lib ervoor kiest om een exception te gooien dan heb je natuurlijk simpelweg geen keuze.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 11 mei 2007 @ 12:20:
Ik zie niet in waarom dat niet zo zou kunnen:
Java:
1
2
3
4
5
6
7
Object o = cacheManager.getFromCache("cacheKey");
if (o == null)
{
    o = new Object();
    cacheManger.storeInCache("cacheKey", o);
}
return o;

Dezelfde argumenten die jij geeft gelden ook voor dit stukje code (ergo, het zijn geen argumenten voor het gebruik van exception).
Nee dezelfde argumenten gaan niet op. Je kunt nu namelijk geen garanties geven wat betreft concurrency. In het geval van de Exceptie methode kan de aanroep naar 'getFromCache' geblocked worden op het moment dat de exceptie gegooid is. Tevens zou 'null' een waarde kunnen zijn en dien je dus een soort van CacheEntry object te retourneren. In die CacheEntry moet dan de eigenlijke waarde staan die dan wel 'null' kan zijn.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

.oisyn schreef op vrijdag 11 mei 2007 @ 12:00:
[...]

Testen op EOF kun je imho het beste doen daar waar je 'm verwacht (bijvoorbeeld nadat je een getline() gedaan hebt), niet daar waar je 'm niet verwacht (bijvoorbeeld als de regels die je uit het textbestand aan het lezen bent altijd in groepjes van 4 afgehandeld worden, waardoor je 4x getline() doet en dan pas een EOF test)
Dat ben ik zonder meer met je eens, ik had het dan ook over de EOF die je dus wel verwacht. Een EndOfFileException lijkt me inderdaad puur bedoeld voor een onverwacht einde van het bestand, waar jij juist nog meer data verwacht, en níet voor het afhandelen van het gebruikelijke einde van het bestand op de plaats waar dat hoort. Maar voor zoals ik je post lees is dat ook precies wat je probeert te zeggen. :)
BalusC schreef op vrijdag 11 mei 2007 @ 12:10:
Dat hangt ook af van het gebruikte programmeertaal lijkt me. In Java en C zullen EOF dingen ongetwijfeld beter implementeerbaar zijn dan in PHP.
PHP heeft EOF zo'n beetje op de C-manier geïmplementeerd. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 11 mei 2007 @ 12:29:
[...]
Nee dezelfde argumenten gaan niet op. Je kunt nu namelijk geen garanties geven wat betreft concurrency. In het geval van de Exceptie methode kan de aanroep naar 'getFromCache' geblocked worden op het moment dat de exceptie gegooid is.
Kan natuurlijk ook als null wordt gereturned
Tevens zou 'null' een waarde kunnen zijn
Dan neem je een andere speciale waarde die er niet in kan. Bijvoorbeeld CacheEntry.notAvailable.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

-NMe- schreef op vrijdag 11 mei 2007 @ 12:32:
[...]

Dat ben ik zonder meer met je eens, ik had het dan ook over de EOF die je dus wel verwacht. Een EndOfFileException lijkt me inderdaad puur bedoeld voor een onverwacht einde van het bestand, waar jij juist nog meer data verwacht, en níet voor het afhandelen van het gebruikelijke einde van het bestand op de plaats waar dat hoort. Maar voor zoals ik je post lees is dat ook precies wat je probeert te zeggen. :)
Klopt, je post laat dus maar 1 kant van het verhaal zien zonder erbij te zeggen dat die andere kant ook bestaat, waardoor je lijkt te suggereren dat je altijd en overal op EOF moet checken.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 11 mei 2007 @ 12:35:
Kan natuurlijk ook als null wordt gereturned
Het punt is dus dat je moet synchroniseren in de 'client' code. Overal waar je de eventuele cachekey wil gebruiken dien je zelf de synchronisatie te verzorgen. Wanneer er gebruik wordt gemaakt van een Exceptie dan kan je synchronisatie volledig achter de schermen plaats vinden.

En nee je kunt niet op de waarde null rusten in je logica zonder wrapper. Immers null kan betekenen dat het de huidige waarde is maar ook dat de cache outdated is. Je wil natuurlijk niet als de uitkomt van een dure berekening null is deze elke keer uitvoeren omdat je denkt dat de cache verlopen is.

Conclusie: zonder exceptie mechanisme ontkom je niet aan synchronisatie alsmede het gebruik van een info object.

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

.oisyn schreef op vrijdag 11 mei 2007 @ 12:40:
[...]

Klopt, je post laat dus maar 1 kant van het verhaal zien zonder erbij te zeggen dat die andere kant ook bestaat, waardoor je lijkt te suggereren dat je altijd en overal op EOF moet checken.
Daar heb je gelijk in. Ik heb mijn post wat genuanceerd. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 11 mei 2007 @ 12:44:
[...]

Het punt is dus dat je moet synchroniseren in de 'client' code. Overal waar je de eventuele cachekey wil gebruiken dien je zelf de synchronisatie te verzorgen. Wanneer er gebruik wordt gemaakt van een Exceptie dan kan je synchronisatie volledig achter de schermen plaats vinden.
Ik weet wat je probeert te zeggen, maar ik zie niet in waarom dat niet kan als je een speciale waarde returned ipv een exception gooit. Kun je anders eens een mogelijke implementatie van CacheEntry.getFromCache() laten zien om het een en ander te verduidelijken?
En nee je kunt niet op de waarde null rusten in je logica zonder wrapper. Immers null kan betekenen dat het de huidige waarde is maar ook dat de cache outdated is. Je wil natuurlijk niet als de uitkomt van een dure berekening null is deze elke keer uitvoeren omdat je denkt dat de cache verlopen is.
Euh ja, dit punt hadden we al opgelost in mijn vorige post, ik snap niet waarom je nou op null doorgaat. En het lijkt me een beetje onzinnig dat CacheEntry.notAvailable toevalligerwijs uit je berekening komt, of niet? :)
Java:
1
2
3
4
class CacheEntry
{
    public final static Object notAvailable = new Object();
}

[ Voor 9% gewijzigd door .oisyn op 11-05-2007 12:51 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 11 mei 2007 @ 12:49:
Ik weet wat je probeert te zeggen, maar ik zie niet in waarom dat niet kan als je een speciale waarde returned ipv een exception gooit. Kun je anders eens een mogelijke implementatie van CacheEntry.getFromCache() laten zien om het een en ander te verduidelijken?
Okee, dan even voorop het doel. Ik wil geen synchronisatie blokken in mijn client code. Dit moet door de cachemanager geregeld worden.

Een andere implementatie zou bijvoorbeeld zijn om een CacheEntry te retourneren waarbij alle calls naar getFromCache geblocked worden tot het moment dat de CacheEntry weer wordt terug gegeven aan de CacheManager. Het nadeel van een dergelijke methode is dat je een deel van de caching verantwoordelijkheid uit de cachemanager trekt. Je moet namelijk in je client code de state van je CacheEntry bepalen (of deze dus geupdate moet worden). Ik vind dit de verantwoordelijkheid van een cachmanager. Die moet bepalen wanneer er een verse variant van de data nodig is.
.oisyn schreef op vrijdag 11 mei 2007 @ 12:49:
Euh ja, dit punt hadden we al opgelost in mijn vorige post, ik snap niet waarom je nou op null doorgaat
Ik ga er op door omdat je maar een klein deel van het probleem belicht. Namelijk "hoe kan ik onderscheid maken tussen een update en een null waarde". Maar door gebruik te maken van een voorgedefinieerde null entry dien je dus extra logica op te nemen in je client code. Immers de controle of we misschien 'null' bedoelen.

Acties:
  • 0 Henk 'm!

Verwijderd

disclaimer: implementatie is C++
-NMe- schreef op vrijdag 11 mei 2007 @ 11:03:
[...]

Ah, dus je kan ook een loop-constructie zoals een while gebruiken om dingen te testen zonder ooit te loopen,
Tuurlijk, als je dat zou willen: geen probleem, ga je gang. Sterker: je hebt kennelijk geen idee hoe vaak dat gebruikt wordt, en hoe zinvol dat kan zijn. Duik maar eens in bijvoorbeeld een Linux kernel source. Daar vind je aan de lopende band toepassing van een constructie als
C:
1
#define DO_ONCE(BLA)   do { BLA; } while (0)

En dat wordt niet voor niets gebruikt. Heb je enig idee waarom? :)

Maar als je toch op die toer gaat, dan kan je nog wel aanzienlijk vreemdere dingen doen, zoals deze POD_bom. Of je ook zou willen dat iemand in teamverband zoiets doet, is vraag 2 :O .
en functies hoeven niet per se een functioneel geheel te zijn maar die kun je naar eigen inzicht door elkaar rijgen totdat je een lappendeken hebt die niemand meer begrijpt? :)
Dat zijn jouw woorden, waar ik mij om begrijpelijke redenen van distantiëer.
Exceptions zijn niet voor niets exceptions genoemd. Een exceptie is volgende het woordenboek een uitzonderingssituatie. Die naamgeving is écht niet zomaar gekozen door de ontwikkelaars van de taal. Bij het lezen van een bestand wéét je dat EOF eraan komt, dus het is ook géén uitzondering wanneer dat gebeurt. Om die reden is het wat mij betreft ook erg krom om uitgerekend daarvoor een exception te gaan misbruiken.

En wat betreft degene die hierboven riep dat het gebruik van een extra "&& !EOF" in elke loop/if in een constructie minder leesbaar is dan uit de constructie springen met een exception: wat rook jij? :P Het kost geen moeite om die extra 7 karakters op te nemen, en het blijft leesbaarder dan wanneer je uit je code breekt. :)
Vier dingen.

1) Lees mijn post hierover nog eens, maar dan wat nauwkeuriger. Ik sprak niet over 7 karakters, maar over aanzienlijk meer dan dat.

2) Het besparen van 7 karakters heeft tot gevolg dat ergens anders 100+ karakters opgenomen moeten worden voor het gooien en afvangen van de door mij gesuggereerde exception. Dat is iha. zonde van de moeite. Je opmerking is dus niet logisch.

3) Ik had het dus niet primair over "&& !EOF", maar over "! bUnexpectedEOF". Daar zit een aanzienlijk verschil tussen, en wel:
unexpected EOF is in mijn scan-deel niet van belang voor het normale executie-pad
.
Dat onderscheid is er, ik ben me er van bewust, en ik houd daar rekening mee.

Merk op dat een van de dingen waar je als programmeur tijdens je loopbaan mee in aanraking komt, het spanningsveld is tussen de toenemende grootte van de projectcode, en de capaciteit van het menselijke korte- en lange-termijn geheugen. Een van de manieren waarop ik daar mee om ga, is verdeel-en-heers. Als ik besluit dat het afhandelen van een unexpected-EOF situatie in mijn scanner irrelevant is voor het normale executie-pad, dan wil ik tests daarop bij voorkeur niet in dat deel van mijn code zien dat zich bezig houdt met dat normale executie-pad. Ik wéét dat de kans op een UEOF bestaat, ik wéét dat ik die situatie correct afvang, dus ik hóef, nee ik wíl de code van het scan-deel niet vervuilen met code die daar niet noodzakelijk is. Wat is er in vredesnaam nou verwarrend aan deze aanpak?

Een van de talloze toepassing van dit principe is het Iterator Pattern, waarbij het lopen langs een container losgekoppeld is van de container-structuur. Omdat je na het bepalen van het geschikte container-type tijdens het itereren niet hoeft na te denken over de interne details van de container-structuur implementatie, houd je meer geestelijke capaciteit over voor de rest van je programma. En als je dit voorbeeld banaal vindt klinken, probeer dan nog eens goed na te denken over het principe. Dáar gaat het mij om.

4) Het is eenieders volste recht om kritiekloos af te gaan op wat anderen zeggen. Dus als je iemand hoort beweren dat 'arrays are evil because we do have containers' , 'meer dan 1 return in een functie is evel', of dat 'Exceptions niet voor niets exceptions zijn genoemd', daar zonder meer in mee te gaan. Dat is een al dan niet bewuste keuze die je maakt.

Maar ik ben glashelder van mening dat het voor je ontwikkeling als SD een goed idee is om af en toe serieus en niet dogmatisch over dit soort zaken na te denken, en bij voorschrijdend inzicht je mening bij te schaven...

Zie ook het type-3 programmeur van flowerp.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 11 mei 2007 @ 12:59:
[...]

Okee, dan even voorop het doel. Ik wil geen synchronisatie blokken in mijn client code. Dit moet door de cachemanager geregeld worden.
Dat was me al vanaf de beginpost helemaal duidelijk :). Maar hoe zou je dat implementeren met een exception, zo?
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class CacheManager
{
    public getFromCache(String key)
    {
        block();

        Objet foundObject;
        boolean found;

        // zoek in de cache

        if (!found)
            throw NotFoundException();

        unblock();
        return foundObject;
    }

    public storeInCache(String key, Ojbect o)
    {
        block();
        // store o in cache
        unblock();
    }
}


waarbij de logica van block() en unblock() voor de nodige synchronisatie zorgt (zonder nesting, dus 2x block() vanaf dezelfde thread heeft maar 1x een unblock() nodig). Of je hier er nou voor kiest om een exception te gooien of een speciale waarde te retourneren, in beide gevallen reken je erop dat storeInCache() wordt aangeroepen. Of heeft een Exception in Java tegenwoordig speciale event-code die wordt aangeroepen nadat de catch van die exception is doorlopen?

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Ah nu begrijp ik waar onze verhalen niet sluiten. Ik had het over een versimpeld voorbeeld waarbij ik misschien iets ben doorgeslagen. op de exceptie zelf kun je namelijk aangeven dat je klaar bent met updaten. Daar geef je dus de lock vrij.


Edit 1:
Mischien is de beste omschrijving dus wel: Doormiddel van een exceptie kun je de client in bepaalde state foorceren. In dit geval forceer je dus dat de client in ieder geval niet de mogelijkheid heeft om (direct) met de oude data aan de slag te gaan.

Edit 2:
Even opzoek gegaan naar de volledige code die je doorgaans gebruikt bij OsCache:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
String myKey = "myKey";
String myValue;
int myRefreshPeriod = 1000;
try {
    // Get from the cache
    myValue = (String) admin.getFromCache(myKey, myRefreshPeriod);
} catch (NeedsRefreshException nre) {
    try {
        // Get the value (probably from the database)
        myValue = "This is the content retrieved.";
        // Store in the cache
        admin.putInCache(myKey, myValue);
        updated = true;
    } finally {
        if (!updated) {
            // It is essential that cancelUpdate is called if the
            // cached content could not be rebuilt
            admin.cancelUpdate(myKey);
        }
    }
}

Het was dus niet op de exceptie maar gewoon op de manager. Opzich maakt dat voor het verhaal niet veel uit.

[ Voor 81% gewijzigd door Verwijderd op 11-05-2007 13:42 ]


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 11 mei 2007 @ 12:00:
[...]

Ik ga niet tijdens het unserializen de hele tijd testen op EOF, want die zou gewoonweg niet moeten komen.
...
Een EOF is in zo'n geval wél een uitzondering....

Testen op EOF kun je imho het beste doen daar waar je 'm verwacht (bijvoorbeeld nadat je een getline() gedaan hebt), niet daar waar je 'm niet verwacht (bijvoorbeeld als de regels die je uit het textbestand aan het lezen bent altijd in groepjes van 4 afgehandeld worden, waardoor je 4x getline() doet en dan pas een EOF test)
Bingo.

Leuke diskussie trouwens :) .

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Verwijderd schreef op vrijdag 11 mei 2007 @ 13:07:
Tuurlijk, als je dat zou willen: geen probleem, ga je gang. Sterker: je hebt kennelijk geen idee hoe vaak dat gebruikt wordt, en hoe zinvol dat kan zijn. Duik maar eens in bijvoorbeeld een Linux kernel source. Daar vind je aan de lopende band toepassing van een constructie als
C:
1
#define DO_ONCE(BLA)   do { BLA; } while (0)

En dat wordt niet voor niets gebruikt. Heb je enig idee waarom? :)
Om de code lastiger leesbaar te maken zodat je er slimmer uitziet ten overstaan van beginners? :? Ik zie de meerwaarde van een macro voor zoiets niet ten opzichte van het domweg inline opnemen; dit nog los van het feit dat een do...while loop die sowieso altijd maar één keer loopt nogal nutteloos is.
Dat zijn jouw woorden, waar ik mij om begrijpelijke redenen van distantiëer.
Het komt op hetzelfde neer als hetgeen jij zegt, namelijk dat de betekenis van het woord in onze taal niet hetzelfde hoeft te zijn als de betekenis in een programmeertaal.
1) Lees mijn post hierover nog eens, maar dan wat nauwkeuriger. Ik sprak niet over 7 karakters, maar over aanzienlijk meer dan dat.
Dat is natuurlijk afhankelijk van de taal en het aantal loops/ifs waarin je die conditie wil checken.
2) Het besparen van 7 karakters heeft tot gevolg dat ergens anders 100+ karakters opgenomen moeten worden voor het gooien en afvangen van de door mij gesuggereerde exception. Dat is iha. zonde van de moeite. Je opmerking is dus niet logisch.
Zie mijn antwoord op je derde punt hieronder.
3) Ik had het dus niet primair over "&& !EOF", maar over "! bUnexpectedEOF". Daar zit een aanzienlijk verschil tussen, en wel:
unexpected EOF is in mijn scan-deel niet van belang voor het normale executie-pad
.
Dat onderscheid is er, ik ben me er van bewust, en ik houd daar rekening mee.
Zie mijn korte discussie met .oisyn. Ik heb je al min of meer gelijk gegeven op dat punt. ;)
4) Het is eenieders volste recht om kritiekloos af te gaan op wat anderen zeggen. Dus als je iemand hoort beweren dat 'arrays are evil because we do have containers' , 'meer dan 1 return in een functie is evel', of dat 'Exceptions niet voor niets exceptions zijn genoemd', daar zonder meer in mee te gaan. Dat is een al dan niet bewuste keuze die je maakt.
Dat ben ik met je eens, maar dat neemt niet weg dat ik die mening zelf kan beargumenteren. Ik ga niet kritiekloos af op wat mensen zeggen, maar ik beredeneer of wat er gezegd wordt al dan niet zinnig is en of ik er al dan niet wat mee kan. Situaties die je op een bepaald punt in je code domweg kan verwachten, zoals een EOF op een logische plaats, zijn geen uitzonderingsgevallen en horen ook niet in je code als exception afgevangen te worden. Wanneer je een corrupt invoerbestand hebt en je komt op een bepaald punt in dat bestand onverwacht een EOF tegen, dan is dat wél een exception en die kun je gerust afvangen; daar zou ik niet tegen protesteren als jij en ik aan hetzelfde project zouden werken.
Maar ik ben glashelder van mening dat het voor je ontwikkeling als SD een goed idee is om af en toe serieus en niet dogmatisch over dit soort zaken na te denken, en bij voorschrijdend inzicht je mening bij te schaven...
Dat ben ik ook met je eens, maar voortschrijdend inzicht betekent niet dat je zomaar aan alles wat IMO duidelijk afgebakend is kunt tornen.
Zie ook het type-3 programmeur van flowerp.
Die lijst vind ik sowieso niet echt kloppen. Je hebt beginners die geen flauw idee hebben wat ze aan het doen zijn en dat van zichzelf weten en je hebt beginners die zichzelf als gevorderde typeren. Daarnaast heb je vergelijkbaar daarmee gevorderden die weten dat ze aardig kunnen programmeren maar nog niet aan de top zitten (of zelfs gevorderden die zichzelf compleet onderschatten), en je hebt gevorderden die professional denken te zijn. Ook professionals kun je nog op zo'n manier indelen. Ik wil mezelf geenszins professional noemen, maar ik denk eveneens dat er hier op GoT ook niet zoveel mensen zijn die dat wel in alle eerlijkheid kunnen. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 11 mei 2007 @ 13:20:
Ah nu begrijp ik waar onze verhalen niet sluiten. Ik had het over een versimpeld voorbeeld waarbij ik misschien iets ben doorgeslagen. op de exceptie zelf kun je namelijk aangeven dat je klaar bent met updaten. Daar geef je dus de lock vrij.
Aha dat was idd even niet duidelijk :). Dat kun je natuurlijk ook vergeten, alsmede dat je de ikBenKlaar() aanroep ook op de CacheManager kunt doen, maar ik snap je punt als je bedoelt dat dit met een exception minder snel vergeten wordt omdat je enigszins verplicht bent om de exception ook daadwerkelijk af te handelen.

Staat deterministisch finalization eigenlijk enigszins op de planning voor Java? Want daarmee zou je de unlock kunnen automatiseren, zoals dat in C++ en C++/CLI kan.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

-NMe- schreef op vrijdag 11 mei 2007 @ 13:38:
[...]

Om de code lastiger leesbaar te maken zodat je er slimmer uitziet ten overstaan van beginners? :? Ik zie de meerwaarde van een macro voor zoiets niet ten opzichte van het domweg inline opnemen;
Er is voor macro's in C en C++ weldegelijk een doel omdat de semantiek anders is dan bij inline functies. Zo zou je in een macro de __FILE__ en __LINE__ definities kunnen opnemen zodat je kunt loggen waar de call vandaan kwam. Met een inline functie kan dat niet omdat die file/line combo dan altijd wijst naar de plek in je inline functie waar je de aanroep doet, ipv waar je de inline functie aanroept. En zo zijn er nog talloze redenen om voor macro's te kiezen die ik nu niet allemaal op ga noemen :)
dit nog los van het feit dat een do...while loop die sowieso altijd maar één keer loopt nogal nutteloos is.
Om meerdere statements in een macro te kunnen gebruiken zonder de aanroepende program-flow te beinvloeden. Denk maar eens aan deze situatie:

C++:
1
2
3
4
5
6
7
8
9
#define BLA() doeIets1(); doeIets2()

void foo(bool b)
{
    if (b)
        BLA();
    else
        doeIetsAnders();
}


Ra ra wat gaat hier fout? :)
De do { ... } while (0) is hier een standaard oplossing voor, omdat het meerdere stataments in een enkele verpakt (die bovendien een sluitende accolade verwacht)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

.oisyn schreef op vrijdag 11 mei 2007 @ 14:50:
[...]

Er is voor macro's in C en C++ weldegelijk een doel omdat de semantiek anders is dan bij inline functies. Zo zou je in een macro de __FILE__ en __LINE__ definities kunnen opnemen zodat je kunt loggen waar de call vandaan kwam. Met een inline functie kan dat niet omdat die file/line combo dan altijd wijst naar de plek in je inline functie waar je de aanroep doet, ipv waar je de inline functie aanroept. En zo zijn er nog talloze redenen om voor macro's te kiezen die ik nu niet allemaal op ga noemen :)
Ik had het over die specifieke macro, niet macro's in het algemeen. :+

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 11 mei 2007 @ 14:44:
Staat deterministisch finalization eigenlijk enigszins op de planning voor Java? Want daarmee zou je de unlock kunnen automatiseren, zoals dat in C++ en C++/CLI kan.
Ik denk het haast niet, maar weten doe ik het niet. Ik vind het ook eigenlijk niet in de aard van een managed taal passen.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

RAII is een prachtig concept en het doet er eigenlijk niet toe of de taal managed is of niet. C++/CLI, wat een managed taal is, kent het tenslotte ook :). C# ook overigens, dmv using(), maar daar moet je helaas dan weer moeite voor doen. RAII zou ervoor kunnen zorgen dat die extra try..finally die je daar gebruikt helemaal niet nodig hebt - RAII garandeert namelijk dat de variabele die in die scope geintroduceerd wordt altijd wordt gedestruct -zelfs bij een exception- en in een dergelijke destructor zou je de unlock() kunnen doen.
-NMe- schreef op vrijdag 11 mei 2007 @ 14:55:
[...]

Ik had het over die specifieke macro, niet macro's in het algemeen. :+
Flauw, die specifieke macro was dan ook niet het punt, het punt was de do { ... } while(0) loop, waar hij (nickname, niet persoonlijk voornaamwoord (irritant trouwens :P)) het over had :).

Bovendien is ook díe macro nuttig.
C++:
1
2
3
4
5
6
7
8
9
10
#ifdef _DEBUG
#define DEBUGONLY(x) do { x; } while(0)
#else
#define DEBUGONLY(x)
#endif

int main(int argc, char ** argv)
{
    DEBUGONLY(std::cout << "program called with " << argc << " arguments" << std::endl);
}

[ Voor 71% gewijzigd door .oisyn op 11-05-2007 15:17 . Reden: klemtoon verkeerd :) ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

-NMe- schreef op vrijdag 11 mei 2007 @ 13:38:
Om de code lastiger leesbaar te maken zodat je er slimmer uitziet ten overstaan van beginners? :?
Pff, alleen het idee al, hoe kom je daar nou weer bij :N . Nee, omdat je dan dingen kunt doen als
C:
1
2
3
4
if (cond_1)
    DO_ONCE(do_this);
else
   do_something_else;

Voor 'do_this' kun je nu ook meerdere statements invullen, zonder dat je else-part de mist ingaat.

Daarnaast heb ik die macro niet zelf verzonnen. Maar ik vind hem in specifieke situaties wel handig, om niet te zeggen: elegant. Daarmee zeg ik niet dat je 'm altijd en overal moet gebruiken. Wel dat 'ie ontzettend vaak gebruikt wordt, vooral bij portable C/C++ code.

En waarom zou ik in vredesnaam willen proberen om 'indruk te maken op beginners'? Ik heb wel wat anders te doen, want het leven is te kort om aan zoiets tijd verspillen... De enigen op wie ik tot op zekere hoogte indruk zou willen maken (iff any), zijn mijn baas / opdrachtgevers. En vanuit een economisch standpunt gezien, lijkt me daar wel wat voor te zeggen.

Afgezien daarvan, dit is niet het 'Post hier uw cryptische code'-topic. Ben je daar in geïnteresseerd, ga dan hier maar eens een kijkje nemen.
Dat ben ik ook met je eens, maar voortschrijdend inzicht betekent niet dat je zomaar aan alles wat IMO duidelijk afgebakend is kunt tornen.
Zucht. Waarom nou weer een woord als 'alles'? Ik suggeréer niet eens om als een soort van onvolwassen puber tegen alle heilige huisjes die ik tegenkom, te willen schoppen. Ik ben wél nieuwschierig naar de achtergronden van de dingen waar ik als SD mee te maken heb. Ik probeer me te ontwikkelen, en een critische houding naar zowel de zaken waar ik mee te maken heb, als mijn eigen handelen als SD, is m.i. daarbij onmisbaar. Vergeet verder niet dat wat je 'IMO duidelijk afgebakend' vindt in deze fase van je ontwikkeling als SD, dat niet noodzakelijkerwijs ook zo vindt wanneer je je verder ontwikkeld hebt. Dat heet voortschrijdend inzicht. Klein voorbeeldje: ik gebruik de laatste tijd wat vaker 'evil' goto's. Waarom: omdat in bepaalde situaties het gebruik ervan tot een elegantere oplossing leidde. Niet gebruiken omdat ze 'evil' zijn: No Way dus.

Om dit af te sluiten: ik heb in deze diskussie wat gepost omdat ik het leuk vind om mensen een aha-erlebnis te laten krijgen, zo van: hé, zo kan het ook. Maar zo niet: even goede vrienden, hoor. :)

Oh ja, toch nog een ding mbt. dat type-3 programmeur. Een heel bekende uitspraak is:
De helft van de programmeurs vindt zich tot de top-20 behoren, en de rest vindt zich in ieder geval beter dan gemiddeld.
We zijn af en toe net autorijders :z .

Edit: ik moet sneller typen, .oisyn was me weer eens voor :)

Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 11 mei 2007 @ 15:03:
RAII is een prachtig concept en het doet er eigenlijk niet toe of de taal managed is of niet. C++/CLI, wat een managed taal is, kent het tenslotte ook :). C# ook overigens, dmv using(), maar daar moet je helaas dan weer moeite voor doen.
Ik ventileerde enkel mijn mening: Ik denk dat je het niet moet willen in een managed taal. Je bent dan immers impliciet bezig met het opruimen van je objecten, iets wat juist een managed taal (onder andere) probeert te voorkomen.

En daarbij heb ik nog wel wat andere redenen, maar ik dwaal op dit moment weer een beetje teveel af van het hoofdonderwerp.

@hij
misschien zou je in plaats van de standaard uitspraken in twijfel te trekken je beter kunnen bezig houden met de vraag waarom dergelijke uitspraken zijn ontstaan. Want van je voorbeelden krijg ik nu in de verste verte niet die 'aha-erlebnis' ;)

[ Voor 14% gewijzigd door Verwijderd op 11-05-2007 15:33 ]


Acties:
  • 0 Henk 'm!

  • D-Raven
  • Registratie: November 2001
  • Laatst online: 29-09 14:10
Verwijderd schreef op vrijdag 11 mei 2007 @ 15:18:
Klein voorbeeldje: ik gebruik de laatste tijd wat vaker 'evil' goto's. Waarom: omdat in bepaalde situaties het gebruik ervan tot een elegantere oplossing leidde. Niet gebruiken omdat ze 'evil' zijn: No Way dus.
Ik moet toch even reageren op die tenenkrommende opmerking van dat jij het GOTO: Statement gebruikt..

Ik ben namelijk zeer benieuwd naar het stukje code waarin jij het gerechtvaardigd vond om GOTO te gebruiken wegens leesbaarheid en of duidelijkheid van de code.

En om dan ontopic te zijn:
Ongeacht van de zogenaamde performance verlies van het throwen van exceptions (hoe klein dan ook). Het gebruik van Exceptions moet je gewoon op een doordachte wijze doen. Als ik dan voorbeelden zie van mensen die door een array heen itereren d.m.v een exception (om maar een voorbeeld te noemen), dan begint het spontaan te kriebelen bij mij :P
Hoe zou je in godsnaam ook maar op t idee komen. En dan interesseert het me helemaal niks wat de performance is. Zoiets is gewoon principieel fout.

[ Voor 16% gewijzigd door D-Raven op 11-05-2007 15:41 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op vrijdag 11 mei 2007 @ 15:20:
[...]
Ik ventileerde enkel mijn mening: Ik denk dat je het niet moet willen in een managed taal. Je bent dan immers impliciet bezig met het opruimen van je objecten, iets wat juist een managed taal (onder andere) probeert te voorkomen.
En daar maak je imho een denkfout. Je bent niet bezig met opruimen van objecten, maar met het opruimen van resources, en dat moet je zowel in een managed taal als in een unmanaged taal gewoon zelf doen. Het enige verschil is dat je bij een managed taal met één specifieke resource geen rekening hoeft te houden - het geheugen. Maar het gaat niet om het geheugen, en dat is ook niet waar deterministic finalization om draait. Het is natuurlijk onzin dat je zelf bijvoorbeeld files moet gaan zitten sluiten, terwijl uit de scope van je programma al duidelijk is dat je die file die je opent nooit meer kán gebruiken nadat de variabele buiten scope is gegaan. Als je echt exception-safe wilt programmeren zul je je code moeten peperen met try..finally statements om deze dingen op te vangen. RAII is echter veel simpeler, bij initialisatie acquire je een resource, en als hij buiten scope gaat wordt de resource weer vrijgegeven (file handle, netwerk connectie, een lock op de CacheManager). Het mooie is dat je dat vrijgeven op die manier ook niet kunt vergeten - het gaat immers automatisch.

Daarnaast is deterministic finalization gewoon een vorm van GC, die werkt op de objecten die op de stack staan, en die bovendien deterministisch is. Zeggen dat dat niet in een managed taal past vind ik dus een beetje raar :)

[ Voor 7% gewijzigd door .oisyn op 11-05-2007 15:55 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

D-Raven schreef op vrijdag 11 mei 2007 @ 15:38:
Ik moet toch even reageren op die tenenkrommende opmerking van dat jij het GOTO: Statement gebruikt..

Ik ben namelijk zeer benieuwd naar het stukje code waarin jij het gerechtvaardigd vond om GOTO te gebruiken wegens leesbaarheid en of duidelijkheid van de code.
Het blijft natuurlijk subjectief, maar uit een 5+ lagen geneste if of loop springen met een goto kan weldegelijk leesbaarder zijn dan het bijhouden van een enkele boolean die na elke lus gechecked wordt.

Zeggen dat zo'n structuur slecht gedesigned is en dat je dat beter in aparte functies kunt gooien (zodat je return kunt gebruiken, hoewel sommigen daar ook weer tegen argeren dus verplaats je het probleem alleen maar) is een beetje kort door de bocht. Je hebt in de aangeroepen functie namelijk niet dezelfde context als in de aanroepende functie. Dus dan moet je óf al je lokale variabelen door gaan geven, óf die gaan gieten in een structure oid (wat ook niet altijd kan omdat ze dan tegelijk geconstruct moeten worden)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Nee ik bedoelde hem echt zoals het er staat: objecten :)
Het opruimen van resources (zoals bijvoorbeeld connecties) wil ik expliciet benoemen, maar niet in een finalizer/destructor. Ik vind dat namelijk niet transparant. Ik denk dan dat je te zwaar gaat leunen op de eigenschappen van managed omgeving wat simpelweg de leercurve steiler maakt.

Overigens vind ik het zelf wel galant hoor maar mooie galante constructies zijn niet altijd de contructies die door de rest van je collega's begrepen worden. Vandaar dat ik altijd wat terughoudend ben met betrekking tot dergelijke concepten.
.oisyn schreef op vrijdag 11 mei 2007 @ 15:49:
Daarnaast is deterministic finalization gewoon een vorm van GC, die werkt op de objecten die op de stack staan, en die bovendien deterministisch is. Zeggen dat dat niet in een managed taal past vind ik dus een beetje raar :)
Nee maar nu hanteer je een iets andere context dan dat ik die opmerking in heb geplaats. Jij bekijkt hem nu vanuit een zeer technische kant die meer leunt op de technische mogelijkheid van deterministisch er een einde aan breien. En dat ga en probeer ik ook logischerwijs niet te ontkrachten. Ik vind, met nadruk op vind, het niet bij een managed taal passen. En uiteraard is die mening vooral met Java in het achterhoofd gevormd.

[ Voor 39% gewijzigd door Verwijderd op 11-05-2007 16:17 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Het opruimen van resources (zoals bijvoorbeeld connecties) wil ik expliciet benoemen, maar niet in een finalizer/destructor. Ik vind dat namelijk niet transparant. Ik denk dan dat je te zwaar gaat leunen op de eigenschappen van managed omgeving wat simpelweg de leercurve steiler maakt
Tja ik denk dat dat voornamelijk komt omdat RAII in de taal waarin jij werkt (Java) niet bestaat. Voor C++ is het juist een heel belangrijk concept, en vrijwel iedereen die in C++ programmeert maakt er dan ook gebruik van.

Dit zeg ik overigens niet omdat ik een C++ zealot ben (wat ik wel ben :P) - alle talen hebben hun voordelen en hun tekortkomingen. Maar als ik de ideale taal zou moeten definieren dan zou RAII er zeker bij horen :)

[ Voor 19% gewijzigd door .oisyn op 11-05-2007 16:15 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

.oisyn schreef op vrijdag 11 mei 2007 @ 16:13:
Tja ik denk dat dat voornamelijk komt omdat RAII in de taal waarin jij werkt (Java) niet bestaat. Voor C++ is het juist een heel belangrijk concept, en vrijwel iedereen die in C++ programmeert maakt er dan ook gebruik van.
Maar ik vind het dan ook bij C++ prima passen. Wellicht ook omdat het doorgaans een slag programmeurs betreft die vele malen meer inzicht hebben in de werking van computer/taal/programma. De gedachtegang van een dergelijke programmeur sluit dan ook veel meer aan bij de methodiek.

Acties:
  • 0 Henk 'm!

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

Confusion

Fallen from grace

Verwijderd schreef op donderdag 10 mei 2007 @ 21:53:
Exceptions zijn bedoeld voor uitzonderingen op de normale programma flow. Situaties die alleen kunnen ontstaan door onverwachte gebeurtenissen. Bijvoorbeeld: Je hebt een applicatie die een webservice call doet, als de webservice eruit valt dan dien je een exception te gebruiken. Dit is immers een onverwachte situatie.
Wat is daar onverwacht aan? Ik verwacht wel degelijk dat webservices.nl een enkele keer onbereikbaar zal zijn. Toch laat ik dan een exception gooien. Wanneer je exceptions gebruikt heeft met de uitzonderlijkheid van de situatie te maken, niet met onverwachtheid.
Verwijderd schreef op woensdag 09 mei 2007 @ 23:27:
Daar zijn ze niet voor. Exceptions zijn situaties die je niet verwacht of had kunnen voorzien.
Dan is een NumberFormatException die wordt gegooid op het moment dat ik Integer.parseInt(eenString) doe geen exception. Ik verwacht hem immers. Ik gebruik zo'n constructie bijvoorbeeld om de binnenkomende parameters te valideren in een servlet dat normaalgesproken alleen wordt aangeroepen via een link die door mijzelf geconstrueerd is. Maar ik verwacht wel degelijk dat iemand een keer gaat proberen om met de hand wat variabelen te wijzigen en daarbij n=5892 verandert in n=5892a, waarop het servlet een NumberFormatException gooit en een 403 terug zal geven.

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


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Confusion schreef op vrijdag 11 mei 2007 @ 16:46:
Dan is een NumberFormatException die wordt gegooid op het moment dat ik Integer.parseInt(eenString) doe geen exception. Ik verwacht hem immers.
Klopt, ik vind dat ook de meest belachelijke constructie in veel van de managed talen. Het riekt een beetje naar het gebruik van exceptions om het gemis van meerdere returnvalues te compenseren. Het is geen exception, het is een programming error, je geeft een functie foute invoer. Daar mag ie best op controleren en een fout rapporteren, maar laat 'm dan ook een fout rapporteren (door een Tuple<bool, int> te returnen ipv een int, of desnoods alleen een bool en de int in byref output parameter - Java heeft hier natuurlijk een beetje de trend voor gezet, wegens het gemis van value-types en byref parameter passing)

[ Voor 7% gewijzigd door .oisyn op 11-05-2007 17:13 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • brama
  • Registratie: Februari 2001
  • Niet online
.oisyn schreef op vrijdag 11 mei 2007 @ 16:13:
[...]

Tja ik denk dat dat voornamelijk komt omdat RAII in de taal waarin jij werkt (Java) niet bestaat. Voor C++ is het juist een heel belangrijk concept, en vrijwel iedereen die in C++ programmeert maakt er dan ook gebruik van.

Dit zeg ik overigens niet omdat ik een C++ zealot ben (wat ik wel ben :P) - alle talen hebben hun voordelen en hun tekortkomingen. Maar als ik de ideale taal zou moeten definieren dan zou RAII er zeker bij horen :)
In C++ ben je er zeer blij mee omdat je resources veel vaker expliciet moet opruimen (deallocatie voornl.). In Java komt dat veel minder vaak voor. Daar kom je al een heel eind met finally(). Weet iemand hier trouwens wat de reden is dat er in java geen deterministische destructors zijn? Het is namelijk wel handig. Ik heb wel een sterk vemoeden, namelijk dat het niet te voorspellen is *wanneer* een object opgeruimd wordt (dankzij garbage collection), en dat je dus zo tijden lang een hele verzameling objecten kunt hebben die bijv. een filepointer bezet houden.

I mentioned it once, but I think I got away with it.


Acties:
  • 0 Henk 'm!

  • brama
  • Registratie: Februari 2001
  • Niet online
.oisyn schreef op vrijdag 11 mei 2007 @ 17:11:
[...]

Klopt, ik vind dat ook de meest belachelijke constructie in veel van de managed talen. Het riekt een beetje naar het gebruik van exceptions om het gemis van meerdere returnvalues te compenseren. Het is geen exception, het is een programming error, je geeft een functie foute invoer. Daar mag ie best op controleren en een fout rapporteren, maar laat 'm dan ook een fout rapporteren (door een Tuple<bool, int> te returnen ipv een int, of desnoods alleen een bool en de int in byref output parameter - Java heeft hier natuurlijk een beetje de trend voor gezet, wegens het gemis van value-types en byref parameter passing)
Dat is inderdaad iets wat ik erg jammer vind. Ik programmeer voor mijn werk vrijwel uitsluitend in java, en soms moet je je in bochten wringen om een functie 2 waarden te laten retourneren. Als je 2 nummertjes wilt hebben, dan moet je bijv. een List of array retourneren, of een method object parameter waarvan de int-waarde mutable is meegeven. De 'nette' oplossing is in het algemeen dat je dan een speciale javabean class schrijft die alle te retourneren waardes bevat, maar soms is dat overkill.

I mentioned it once, but I think I got away with it.


Acties:
  • 0 Henk 'm!

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

Confusion

Fallen from grace

.oisyn schreef op vrijdag 11 mei 2007 @ 17:11:
Klopt, ik vind dat ook de meest belachelijke constructie in veel van de managed talen. Het riekt een beetje naar het gebruik van exceptions om het gemis van meerdere returnvalues te compenseren.
Je zou ook kunnen zeggen dat een exception in Java gewoon iets totaal anders kan zijn dan het ding dat met hetzelfde woord wordt aangeduidt in C++ en dat men in Java dingen exceptions noemt die eigenlijk een andere naam hadden moeten krijgen.
Het is geen exception, het is een programming error, je geeft een functie foute invoer. Daar mag ie best op controleren en een fout rapporteren, maar laat 'm dan ook een fout rapporteren (door een Tuple<bool, int> te returnen ipv een int, of desnoods alleen een bool en de int in byref output parameter - Java heeft hier natuurlijk een beetje de trend voor gezet, wegens het gemis van value-types en byref parameter passing)
Maar als het mechanisme waarmee Java een functie in zo'n geval verlaat een andere naam had gekregen en los van 'exceptions' beschouwd zou worden, zou het dan ook duidelijk inferieur zijn aan bijvoorbeeld de mogelijkheid tuples te retourneren?

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


Acties:
  • 0 Henk 'm!

  • brama
  • Registratie: Februari 2001
  • Niet online
Confusion schreef op vrijdag 11 mei 2007 @ 17:38:
Maar als het mechanisme waarmee Java een functie in zo'n geval verlaat een andere naam had gekregen en los van 'exceptions' beschouwd zou worden, zou het dan ook duidelijk inferieur zijn aan bijvoorbeeld de mogelijkheid tuples te retourneren?
Ja. Het is wel praktisch om exceptions te gooien ipv returnwaardes te gebruiken. Maar dat gaat net zo goed op voor C++, waar je liever een i/o exception gooit, dan dat je je functie -1 laat retourneren. Exceptions gooien is vaak veel beter dan de returnwaarde aanpassen, omdat je dan makkelijker op de juiste plaats de exception kan afhandelen. Altijd drama in bijv. C, als je in 4 geneste functie-aanroepen in de laatste aanroep een fout constateert, die in de 1e functie-aanroep afgehandeld moet worden.

Exceptions zijn echter geen vervanger voor het niet kunnen retourneren van meerdere waarden. Over het algemeen moet je, indien je meerdere waardes wilt retourneren (bijv. db tuple), een class schrijven (java bean) die al die waardes bevat.

I mentioned it once, but I think I got away with it.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

brama schreef op vrijdag 11 mei 2007 @ 17:15:
Weet iemand hier trouwens wat de reden is dat er in java geen deterministische destructors zijn?
Destructors zijn altijd deterministisch, net als elk computerprogramma dat is, maar dat is waarschijnlijk niet wat je bedoelt ;). Java heeft wel destructors, namelijk de finalize() method die je kunt overriden. Hierin je resources opruimen is echter erg onhandig, omdat je, zoals je zelf al zegt, niet weet wanneer ze aangeroepen worden.
Het is namelijk wel handig. Ik heb wel een sterk vemoeden, namelijk dat het niet te voorspellen is *wanneer* een object opgeruimd wordt (dankzij garbage collection), en dat je dus zo tijden lang een hele verzameling objecten kunt hebben die bijv. een filepointer bezet houden.
Tja, het kan weldegelijk determistisch. Bijvoorbeeld bij uit scope gaan, of zoiets simpels als reference counting. Maar het blijft natuurlijk een halve implementatie omdat dit lang niet voor alle objecten geldt.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 16:38

.oisyn

Moderator Devschuur®

Demotivational Speaker

Confusion schreef op vrijdag 11 mei 2007 @ 17:38:
[...]

Je zou ook kunnen zeggen dat een exception in Java gewoon iets totaal anders kan zijn dan het ding dat met hetzelfde woord wordt aangeduidt in C++ en dat men in Java dingen exceptions noemt die eigenlijk een andere naam hadden moeten krijgen.
Exceptions is een concept dat zowel in Java als in C++ hetzelfde geimplementeerd worden. Overigens had ik het over het concept, niet C++'s implementatie. Dat ze het exceptions concept ook voor andere dingen gebruiken in de implementatie maakt niet dat het ineens een ander concept is. Ik zie het zelf meer als workaround voor een aantal tekortkomingen (IllegalArgumentException is ook zoiets, een assertion is in zulke gevallen handiger - het is namelijk niet iets dat je af wilt vangen, je moet gewoon je programmacode aanpassen zodat je wél de goede parameters meegeeft).
Maar als het mechanisme waarmee Java een functie in zo'n geval verlaat een andere naam had gekregen en los van 'exceptions' beschouwd zou worden, zou het dan ook duidelijk inferieur zijn aan bijvoorbeeld de mogelijkheid tuples te retourneren?
Sorry maar ik vind de naam totaal niet belangrijk, het gaat om de semantiek van het concept. Dan kun je het wel Henks noemen, maar ik blijf het net zo fout vinden - normale program flow bypassen om een ander type te kunnen retourneren dan in je function signature staat.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

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

Confusion

Fallen from grace

.oisyn schreef op vrijdag 11 mei 2007 @ 18:40:
Dat ze het exceptions concept ook voor andere dingen gebruiken in de implementatie maakt niet dat het ineens een ander concept is.
Dat klopt, maar "ze misbruiken het exception handling mechanisme" is iets anders dan "ze gebruiken hetzelfde mechanisme voor iets anders." Aangezien ze het ook exceptions noemen, lijkt het eerste meer van toepassing, maar ik vraag me nu af of het tweede verdedigbaar zou zijn.
Ik zie het zelf meer als workaround voor een aantal tekortkomingen (IllegalArgumentException is ook zoiets, een assertion is in zulke gevallen handiger - het is namelijk niet iets dat je af wilt vangen, je moet gewoon je programmacode aanpassen zodat je wél de goede parameters meegeeft).
Op zich kan je tuples teruggeven. Als pakweg Integer.parseInt() een instantie van de klasse IntegerParseResult terug zou geven, met daarin een boolean 'succes' en een Integer 'result', dan heb je heb je dat bereikt.
Sorry maar ik vind de naam totaal niet belangrijk, het gaat om de semantiek van het concept. Dan kun je het wel Henks noemen, maar ik blijf het net zo fout vinden - normale program flow bypassen om een ander type te kunnen retourneren dan in je function signature staat.
Het gaat mij ook om de semantiek van het concept; dat is juist wat ik bedoel: het gaat niet om de naam.

De vraag is: zit er zoveel verschil tussen een try-catch block dat op een speciaal type als resultaat controleert en code overslaat als dat terugkomt en een functiecall die altijd gevolgd wordt door een if (object.succes) { } block en daarmee altijd code overslaat als de methode niet succesful was?

[ Voor 8% gewijzigd door Confusion op 12-05-2007 08:15 ]

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


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

.oisyn schreef op vrijdag 11 mei 2007 @ 18:40:
[...]
Exceptions is een concept dat zowel in Java als in C++ hetzelfde geimplementeerd worden. Overigens had ik het over het concept, niet C++'s implementatie. Dat ze het exceptions concept ook voor andere dingen gebruiken in de implementatie maakt niet dat het ineens een ander concept is. Ik zie het zelf meer als workaround voor een aantal tekortkomingen (IllegalArgumentException is ook zoiets, een assertion is in zulke gevallen handiger - het is namelijk niet iets dat je af wilt vangen, je moet gewoon je programmacode aanpassen zodat je wél de goede parameters meegeeft).
[...]
Java kent asserts, alleen niemand gebruikt ze (zover ik gezien heb) omdat ze nogal wat vervelende bijeffecten kennen in Java. Zoals dat je ze uit kunt zetten en zo.

Maar wat is nu wezenlijk het verschil tussen een IllegalArgumentException en een assert?
[...]
Sorry maar ik vind de naam totaal niet belangrijk, het gaat om de semantiek van het concept. Dan kun je het wel Henks noemen, maar ik blijf het net zo fout vinden - normale program flow bypassen om een ander type te kunnen retourneren dan in je function signature staat.
Die normale program flow zou je anders met behulp van een if ofzo aanpassen bij een foutscenario. Een exceptionmechanisme zorgt er juist voor dat je code niet bomvol paranoia error controles staat.

Exceptions horen bovendien tegenwoordig bij de function signature...

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


Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
-NMe- schreef op vrijdag 11 mei 2007 @ 11:03:
[...]
Exceptions zijn niet voor niets exceptions genoemd. Een exceptie is volgende het woordenboek een uitzonderingssituatie. Die naamgeving is écht niet zomaar gekozen door de ontwikkelaars van de taal.
Even vooropgesteld dat ik er absoluut geen voorstander van ben om Exceptions vaak als algemene programmeer constructie te gaan gebruiken, maar in Java is Exception een subtype van Throwable. De designers lijken ook een beetje de optie open gehouden te hebben; je kunt iets throwen wat kwa naamgeving geen Exception of Error is.
Verwijderd schreef op vrijdag 11 mei 2007 @ 11:41:
Ik ben tot nu toe 1 situatie tegengekomen in Java waar het Exceptie mechanisme op een vrij nette manier gebruikt wordt in de normale flow. Namelijk bij het product OsCache.
En toch is er vanuit de community wel kritiek dat opensymphony hiervoor een exception gebruikt, ik meen dat ze in een toekomstige API dit ook anders willen gaan.

Nevertheless is dit ook wel een beetje mijn punt. Jij vind dit -1- situatie waar het kan, ik heb zeggen en schrijven toevallig 1 andere situatie ooit gehad waarin ik een exception (IMHO) netjes gebruikte in de normale flow. Dat wil dus niet zeggen dat ik verkondig dat je maar overal en altijd exceptions als normaal mechanisme moet gaan gebruiken. Aan de andere kant, als ik nog eens een situatie zie waar een exception echt netter is, dan zou ik dat weer toepassen.
-NMe- schreef op vrijdag 11 mei 2007 @ 13:38:
Die lijst vind ik sowieso niet echt kloppen. Je hebt beginners die geen flauw idee hebben wat ze aan het doen zijn en dat van zichzelf weten en je hebt beginners die zichzelf als gevorderde typeren. Daarnaast [...]
Het was natuurlijk een grove indeling. Ik kon moeilijk een lijst met 100 entries maken waarin ik elke mogelijke combinatie opnoem, toch? ;) Veel mensen hier zullen wel ergens tussen die types in zitten. Voor sommige dingen volg ik zelf ook gewoon de type 2 mentaliteit, omdat ik van die sommige dingen mezelf zeker geen expert zou noemen en het dan veiliger is gewoon het algemene gedachtengoed te volgen. Maar voor dingen waar ik wel weet waar ik mee bezig ben schroom ik dan ook niet om buiten de lijntjes te denken.

[ Voor 63% gewijzigd door flowerp op 11-05-2007 23:06 ]

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
.oisyn schreef op vrijdag 11 mei 2007 @ 14:44:
[...]
Staat deterministisch finalization eigenlijk enigszins op de planning voor Java? Want daarmee zou je de unlock kunnen automatiseren, zoals dat in C++ en C++/CLI kan.
Het kan ook wel anders. In Java (EE) heb je library support voor transactions, dit heet JTA (Java Transaction Architecture). Je kunt de lock aan een transaction koppelen en aan die transaction kun je dan weer een timeout hangen. JBossCache (wat ongeveer hetzelfde doet als OSCache) gebruikt JTA precies daar voor.

(lichtelijk offtopic: ik heb zelf jaren lang OSCache gebruikt, maar aan hun mechanisme zitten ook veel nadelen. De block die ze doen heeft geen mogelijkheid voor een timeout en de refreshexception treed ook alleen op wanneer je de cache benaderd. Als je b.v. iets maar 5 minuten wilt cachen, maar pas weer een cache access doet na 20 minuten dan treed pas op dat moment de exception op. Een eviction thread zoals in JBossCache is in veel gevallen veel krachtiger)

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

  • HawVer
  • Registratie: Februari 2002
  • Laatst online: 13-09 16:51
Knappe kop die zonder exceptions handling tegen bijv. Outlook aan kan programmeren. Mijn punt? Soms ontkom je er niet aan.

[ Voor 19% gewijzigd door HawVer op 12-05-2007 18:13 ]

http://hawvie.deviantart.com/


Acties:
  • 0 Henk 'm!

Verwijderd

HawVer schreef op zaterdag 12 mei 2007 @ 18:12:
Knappe kop die zonder exceptions handling tegen bijv. Outlook aan kan programmeren. Mijn punt? Soms ontkom je er niet aan.
Done that. Is geen enkel probleem... Applicatie draait al ruim 2 jaar zonder 1 crash. De makkelijkste weg is hier om exceptions te gebruiken, maar ook hier hoeft het absoluut niet.

[ Voor 20% gewijzigd door Verwijderd op 12-05-2007 18:33 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Confusion schreef op vrijdag 11 mei 2007 @ 16:46:
Dan is een NumberFormatException die wordt gegooid op het moment dat ik Integer.parseInt(eenString) doe geen exception. Ik verwacht hem immers.
Dit blijft natuurlijk ten alle tijde zeer discutabel. Wanneer je gaat parsen naar een int verwacht je klaarblijkelijk dat de invoer een int representeert. Dus wat dat betreft is het gewoon een uitzonderlijke situatie als het geen int blijkt te zijn. Weet je niet of het een int betreft dan ben je wellicht op zoek naar een patroon. Daar zijn uiteraard andere middelen voor, zoals bijvoorbeeld regex. Dus nogmaals, zeer discutabel. Een dergelijk stellig, uit zijn context gerukt, citaat gaat dus vrijwel nooit op.

En zolang een aanpak zeer discutabel is dan laat ik het liefst de leesbaarheid het sluitende argument zijn (wat natuurlijk ook weer een discutabel argument is, maar dat maar even terzijde). Ik denk dat er weinig programmeurs zijn die de documentatie in hoeven te duiken om een try-catch met een NumberFomatException te begrijpen.

Dan is een Resultaat object (of een tupel als return waarde) simpelweg foutgevoeliger. Niet controleren op de correctheid van het resultaat betekent dat je mogelijkerwijs met malifide data werkt. Dan word je toch bij een exceptie meer gedwongen om die situatie af te handelen.

Acties:
  • 0 Henk 'm!

Verwijderd

Ik volg 't topic al even (interessant!), en wil toch nog even kijken of ik iets nuttigs te melden heb ;)
Verwijderd schreef op zondag 13 mei 2007 @ 13:50:
[...]

Dit blijft natuurlijk ten alle tijde zeer discutabel. Wanneer je gaat parsen naar een int verwacht je klaarblijkelijk dat de invoer een int representeert. Dus wat dat betreft is het gewoon een uitzonderlijke situatie als het geen int blijkt te zijn.
Puur uit puristisch oogpunt zou je dan kunnen redeneren dat je dan bijvoorbeeld een regex gebruikt om je input te controleren, en later die exception opgooit als het format toch niet juist blijkt te zijn. Ik kan me simpel gezegd hetvolgende voorstellen:

front end
textvakje voor je getal (komt dus een string uit) met een of andere validator daar op (al dan niet tijdens het intikken). Is het getal fout (met regex bepaald) dan wordt er ook niets gestart waar een int verwacht wordt.

back end
Je systeem verwacht al een string die te parsen is naar een int, zo niet is er een uitzonderlijke situatie. Exception dus.

Even in het algemeen over dit soort 'truukjes' om het zo maar te noemen:
Als je uiteindelijk gaat kijken naar echt productie werk lijkt het mij echter dat er gekozen moet worden voor de meest pragmatische oplossing. Je kan natuurlijk een heel mooi elegant geschreven programma maken, maar als daar simpelweg geen budget voor is moet je nou eenmaal compromissen sluiten. Vooraf die afweging maken. Ga ik voor leesbaarheid, wil ik performance, etc.

Acties:
  • 0 Henk 'm!

  • flowerp
  • Registratie: September 2003
  • Laatst online: 11-09 18:20
Verwijderd schreef op zondag 13 mei 2007 @ 16:12:
Je kan natuurlijk een heel mooi elegant geschreven programma maken, maar als daar simpelweg geen budget voor is moet je nou eenmaal compromissen sluiten.
offtopic:
Helaas wordt er dan 9 van de 10 keer gekozen voor ranzige code, met alle onderhoudsproblemen van dien. In vele andere engineering disciplines wordt een project dan gewoon minder ambitieus gekozen.

B.v. ik wil misschien een mooie wolkenkrabber bouwen, maar heb daar geen budget voor om het goed te doen. Ga ik dan toch die wolkenkrabber bouwen, maar met minder design erin en met slechtere materialen, of stel ik mijn plannen bij en ga maar een gewone flat neerzetten?

Ik kan de tegenargumenten al voorspellen: "ja, maar van een wolkenkrabber zijn mensenlevens afhankelijk, van een stuk software in het algemeen niet." Kan zijn, maar hetzelfde argument geldt ook voor heel veel andere zaken in onze economie. Als ik zoiets simpels als een schroevendraaier koop verwacht ik ook een zekere kwaliteit, en niet dat het ding bij een paar keer gebruik kapot gaat. Bij software geldt dat echter nooit tot zelden.

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Acties:
  • 0 Henk 'm!

  • JKVA
  • Registratie: Januari 2004
  • Niet online

JKVA

Design-by-buzzword fanatic

flowerp schreef op zondag 13 mei 2007 @ 16:51:
[...]


offtopic:
Helaas wordt er dan 9 van de 10 keer gekozen voor ranzige code, met alle onderhoudsproblemen van dien. In vele andere engineering disciplines wordt een project dan gewoon minder ambitieus gekozen.

B.v. ik wil misschien een mooie wolkenkrabber bouwen, maar heb daar geen budget voor om het goed te doen. Ga ik dan toch die wolkenkrabber bouwen, maar met minder design erin en met slechtere materialen, of stel ik mijn plannen bij en ga maar een gewone flat neerzetten?

Ik kan de tegenargumenten al voorspellen: "ja, maar van een wolkenkrabber zijn mensenlevens afhankelijk, van een stuk software in het algemeen niet." Kan zijn, maar hetzelfde argument geldt ook voor heel veel andere zaken in onze economie. Als ik zoiets simpels als een schroevendraaier koop verwacht ik ook een zekere kwaliteit, en niet dat het ding bij een paar keer gebruik kapot gaat. Bij software geldt dat echter nooit tot zelden.
offtopic:
Wat dat betreft is onze branche totaal nog niet volwassen. Als in de elektrotechniek zo onverantwoord gewerkt wordt, zou er veel misgaan... (waarschijnlijk is dat vroeger ook gebeurd en hebben ze ervan geleerd)


ik heb echter de indruk dat het topic een beetje verschuift naar waarom Exceptions zo slecht zijn. Qua constructie vind ik dat er niets mis mee is. Ik zie liever één of ander globaal (Runtime)Exception vangnet dan code bomvol met ifjes die foutgevallen controleren. Of tig niveau's diep geneste code terwijl het met een Exception eenvoudig te fixen is.

Exceptions zijn echter wel duur waardoor je ze niet overal voor kunt gebruiken. Maar aan de andere kant zijn synchronized blokken ook duur. Zijn ze daarom slecht? Nee, maar je moet wel weten hoe en wanneer je ze gebruikt.

Ik zou graag zien dat exceptions efficienter worden (in performance), in plaats van dat we eromheen gaan werken.

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

Pagina: 1 2 Laatste