exceptions... daar gaan we weer
Pagina: « vorige 1 2 3 volgende »
Jup, het was even zoeken maar ik heb 'm gevonden.Of het systeem daardoor moet stoppen of niet, een error op het scherm wil je sowieso niet.
En dan heb ik het niet over errors die je aan gebruikers laat zien als je geen geldige input geven, of omdat ze niet ingelogd zijn, of dat een pagina niet kan worden gevonden.
Beter gezegd misschien: een exception gooi je als er door het systeem of door de programmeur iets fout gaat, dat normaal niet elke dag zou gebeuren.
Als je kijkt naar professionele codes, zoals sommige frameworks. Kom je meestal maar een aantal verschillende exceptions tegen. Die exceptions zijn dan heel vaak InvalidArgument-exceptions (fout van programmeur dus)
Maar als een bestand niet kan worden gevonden, zou ik geen exception gooien. Ik zou dan eerst controleren of het bestand bestaat met een method die een boolean terugstuurt.
Ward van der Put op 05/12/2013 14:56:25:
Je kunt bijvoorbeeld ook eenvoudig stellen: dat wat jij nu wilt verwijderen, is al verwijderd. Oh mooi, dan hoeven we dat niet nog een keer te proberen.
Dat is een ander ontwerp, maar je moet er vooral geen waardeoordeel aan verbinden en meteen "Error!" gaan schreeuwen.
Daarom kan het Filesystem hier een exception gooien (cachebestand bestaat niet) en FileCache daaraan zelf een conclusie verbinden (maakt mij niet uit). Voor een andere klasse of applicatie kan dezelfde exception geheel andere gevolgen hebben: "Chips, dat is niet pluis, laten we Ozzie een sms sturen."
Ozzie PHP op 05/12/2013 14:08:54:
Het is maar hoe je het ontwerpt. In jouw ontwerp kan dit een uitzonderlijke situatie zijn, in een ander ontwerp eerder regel dan uitzondering.Op het moment dat je cache data (uit de database of uit een bestand) wilt verwijderen en het lukt niet, of omdat de data niet bestaat, of omdat de data wegens technische redenen niet verwijderd kan worden... is er dan sprake van een uitzonderingssituatie? Ja, ik zou denken van wel. Ik wil iets verwijderen. Normaal lukt dat altijd, maar nu ineens niet! * ping * Uitzondering!
Je kunt bijvoorbeeld ook eenvoudig stellen: dat wat jij nu wilt verwijderen, is al verwijderd. Oh mooi, dan hoeven we dat niet nog een keer te proberen.
Dat is een ander ontwerp, maar je moet er vooral geen waardeoordeel aan verbinden en meteen "Error!" gaan schreeuwen.
Daarom kan het Filesystem hier een exception gooien (cachebestand bestaat niet) en FileCache daaraan zelf een conclusie verbinden (maakt mij niet uit). Voor een andere klasse of applicatie kan dezelfde exception geheel andere gevolgen hebben: "Chips, dat is niet pluis, laten we Ozzie een sms sturen."
Eeh, hier gaat iets mis. Althans, mis, er mist een stuk. Dat een bestand niet te verwijderen is geeft niet aan dat het bestand niet bestaat; daar zou dus nog een check vóór zitten. Als het bestand wél bestaat maar niet kan worden verwijderd, waardoor de cacheclass denkt dat de huidige cache de juiste is terwijl het oude data is, lijkt mij dat een uitzondering die je wilt melden.
Als het bestand niet bestaat is een boolean voldoende uiteraard, dan levert het geen oude/corrupte data op.
@Chris, correct, het voorbeeld was kort door de bocht. Ik vergeleek eigenlijk ook twee extremen om te illustreren dat het een ontwerpbeslissing is, geen wetmatigheid.
Quote:
Maar... jij gebruikt nu dan dus unlink om een bestand te verwijderen. Stel nu dat dat niet lukt, omdat de maprechten van de bovenliggende directory dit niet toestaan, dan zou je toch een exception willen gooien? Dat is dan toch (zoals Wouter het zegt) een uitzondering?
Ward en ik hebben allebei een andere werkwijze, zo zie je maar dat dit onderwerp gewoon veel kan verschillen.
De Filesystem#remove functie, zodra een bestand niet verwijderd kan worden is dat een uitzondering. Als je die method namelijk aanroept ga je er vanuit dat het bestand wel verwijderd kan worden, anders roep je hem niet aan. Zodra de remove functie dus niet succesvol verloopt return je geen waarden, je gooit een exception.
Een isser daarintegen, aangezien jij die in het begin van je topic toonde, heeft als doel het terug geven of iets aan staat of uit. Als de optie uitstaat is dit geen uitzondering van die method, dus geeft ie gewoon false terug, als iets aanstaat is dit ook geen uitzondering, dus true teruggeven.
Merk op dat hier ook weer uitzonderingen in zijn. Denk bijv. aan een authorization klasse: $authorization->isGranted('ROLE_ADMIN', $user). Deze geeft een boolean terug of de user dit mag of niet. Maar zodra de token die we meegeven helemaal niet bestaat geeft ie natuurlijk een exception. Of wanneer de user helemaal geen UserInterface object is.
@Wouter; ging inderdaad niet om de isset waar ik het over had, puur om het verwijderen van de cache wat mislukte :-)
Wouter J op 05/12/2013 16:46:45:
Maar zodra de token die we meegeven helemaal niet bestaat geeft ie natuurlijk een exception. Of wanneer de user helemaal geen UserInterface object is.
Gelukkig kunnen we instellen in de method declaratie dat enkel een UserInterface welkom is :-)
Quote:
puur om het verwijderen van de cache wat mislukte :-)
Oh je bedoelt mijn mening dat de cacher de directory niet moet verwijderen? Mijn punt is dat de cacher zelf ook niet weet dat hij de bestanden in een directory plaatst. Hij krijgt gewoon te horen dat ie al zijn cache bestanden daar moet opslaan, dat het een directory is weet hij strict genomen niet.
Bij het leeghalen van de cache is het enige wat hij kan en mag doen de bestanden weghalen die hij ooit gemaakt heeft.
Stel bijv. dat we 2 cacher hebben die allebei met de /app/cache directory werken, dan wil je niet dat als je de clearAll() method van de één aanroept, hij de hele /app/cache directory weghaalt, dan ben je namelijk ook de cache bestanden van die andere cacher kwijt.
>> Gelukkig kunnen we instellen in de method declaratie dat enkel een UserInterface welkom is :-)
Ja, maar niet of de Role werkt of niet (zou leuk zijn om guards in PHP te hebben...)
Gewijzigd op 05/12/2013 17:11:36 door Wouter J
2 cache handlers? ik maak zelf gebruik van 1 cachehandler die werkt op basis van keys; kun je een voorbeeld noemen waarin je 2 cachehandlers zou willen gebruiken?
Code (php)
1
2
3
4
5
6
2
3
4
5
6
$collection = new RouteCollection();
$collection->add(new Route(...));
$collection->add(new Route(...));
// ...
return $collection;
$collection->add(new Route(...));
$collection->add(new Route(...));
// ...
return $collection;
Heb ik een template, dan zou ik de template compilen en dat cachen:
etc.
ik werk zelf vrij vaak met caches (omdat het gewoon nutteloze SQL-queries voorkomt die de bottleneck zijn voor de meeste applicaties) maar werk vanuit één class. die regelt voor mij het ophalen, opslaan en verwijderen (alles, specifieke reeksen op basis van de key of één enkele key) en werkt razendsnel.
Offtopic:
ik krijg zelf altijd het gevoel dat op het moment dat je overal alles wilt gaan extenden/inheriten/implementeren de applicatie niet alleen bizar groot wordt (groter dan nodig zou moeten zijn) maar dat het ook qua snelheid z'n nadelen heeft. maar nou betrap ik mezelf erop dat dit onwijs offtopic gaat en dat een andere discussie is... excuus!
Stel:
Code (php)
Als we nu de functie foo aanroepen dan wordt de UncaughtException dus doorgestuurd naar de exception handler functie, maar wordt dan wel nog 'hallo allemaal' ge-echoot?
Nee, dan zou je die echo in de exception handler moeten opnemen, want: “Execution will stop after the exception_handler is called.”
nee, bij het gooien van een exception stopt je script tot het moment dat je de exception opvangt. Aangezien de exception handler helemaal aan het eind van je script staat stopt dus gewoon je hele script.
Mijn gedachte was dus om onschuldige exceptions bewust te negeren en door de exception handler functie te laten loggen.
Stel nu, ik heb een object en ik wil dat object locken zodat de class properties niet kunnen worden gewijzigd. Stel ik lock het object, maar het object blijkt al gelockt te zijn. Het resultaat is natuurlijk hetzelfde. Het object is en blijft gelockt. Alleen het feit dat jij iets op slot wil zetten wat al op slot zit, klopt niet. Dus ik dacht, hé dat is een uitzondering, dus dan gooien we een exception. Het idee was om die exception dan ergens bovenin te loggen, maar de rest van de code gewoon door te laten gaan (er gebeurt immers niets ernstigs). Maar als ik jullie goed begrijp werkt dat niet. En dus zal ik de exception direct moeten opvangen. Maar overal waar je dan iets wil locken, krijg je dan dus zoiets:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
<?php
try {
$object->lock();
catch (Exception $e) {
$this->logger->log('could not lock object');
}
?>
try {
$object->lock();
catch (Exception $e) {
$this->logger->log('could not lock object');
}
?>
Is dat niet vreemd dat je dan een try/catch-blok gebruikt alleen om even iets te locken?
Gewijzigd op 07/12/2013 16:10:09 door Ozzie PHP
En ja, zodra je niet wilt dat je applicatie stopt moet je hem van te voren opvangen.
Hmmm, oké. Dus jij zou dan gewoon $object->lock(); doen en dit niet in een try/catch zetten?
Maar ik bedenk me... in het geval van lock zou dat inderdaad kunnen, dat je de exception laat opborrelen. Maar in het geval van een cacher die niet werkt moet je dat dus niet doen, want dan klapt je applicatie eruit. Correct?
(p.s. Blij dat jullie even antwoord geven, want ik was dus bijna de mist in gegaan...)
Het mislukken van een cacher is een RunTimeException. Zoiets is afhankelijk van dingen buiten de code om, namelijk het filesysteem of de database. Hierdoor kun je deze niet bij het compilen al vinden en deze moet je dus wel opvangen als je niet wilt dat de applicatie erdoor stopt.
Als ik dit doe:
Code (php)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
<?php
try {
throw new FooException('foo');
} catch (FooException $e) {
throw new BarException('bar');
} catch (BarException $e) {
echo 'hallo!';
}
?>
try {
throw new FooException('foo');
} catch (FooException $e) {
throw new BarException('bar');
} catch (BarException $e) {
echo 'hallo!';
}
?>
Verschijnt er nu 'hallo!' op het scherm? Anders gezegd, wordt de BarException die in de 1e catch wordt gegooid opgevangen door de 2e catch?
Gewijzigd op 11/12/2013 22:43:38 door Ozzie PHP
http://writecodeonline.com/
http://sandbox.onlinephpfunctions.com/
http://3v4l.org/
In dit geval: http://3v4l.org/ttjZJ (wat ook vrij logisch is, aangezien we alleen dingen in tries opvangen)
Gewijzigd op 11/12/2013 22:47:57 door Wouter J