exceptions... daar gaan we weer

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Pagina: « vorige 1 2 3 volgende »

Ozzie PHP

Ozzie PHP

05/12/2013 16:18:11
Quote Anchor link
Jup, het was even zoeken maar ik heb 'm gevonden.

http://anvilstudios.co.za/blog/2010/09/02/error-vs-exception-part-2/

(er is ook een deel 1, 3 en 4)
 
PHP hulp

PHP hulp

20/04/2024 12:10:51
 
Mark Hogeveen

Mark Hogeveen

05/12/2013 16:36:01
Quote Anchor link
Ik zou exceptions gebruiken als de uitzondering ervoor zorgt dat je überhaupt een melding op het scherm zet.
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.
 
Chris -

Chris -

05/12/2013 16:38:43
Quote Anchor link
Ward van der Put op 05/12/2013 14:56:25:
Ozzie PHP op 05/12/2013 14:08:54:
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!
Het is maar hoe je het ontwerpt. In jouw ontwerp kan dit een uitzonderlijke situatie zijn, in een ander ontwerp eerder regel dan 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.
 
Ward van der Put
Moderator

Ward van der Put

05/12/2013 16:44:58
Quote Anchor link
@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.
 
Wouter J

Wouter J

05/12/2013 16:46:45
Quote Anchor link
Geen zin om alles terug te lezen, ik reageer even op een oude reactie, om Chris een plezier te doen

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.
 
Chris -

Chris -

05/12/2013 17:07:30
Quote Anchor link
@Ward; aah oke, 'ff checken' gevalletje ;-)
@Wouter; ging inderdaad niet om de isset waar ik het over had, puur om het verwijderen van de cache wat mislukte :-)
 
- Raoul -

- Raoul -

05/12/2013 17:07:33
Quote Anchor link
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 :-)
 
Wouter J

Wouter J

05/12/2013 17:10:53
Quote Anchor link
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
 
Chris -

Chris -

05/12/2013 17:27:44
Quote Anchor link
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?
 
Wouter J

Wouter J

05/12/2013 17:36:05
Quote Anchor link
Je hebt veel verschillende cache use-cases en bijna allemaal hebben ze een andere cache handler nodig. Bijv. het cachen van routes, dan zou ik een PHP bestand cachen, zoals:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
$collection = new RouteCollection();
$collection->add(new Route(...));
$collection->add(new Route(...));
// ...

return $collection;


Heb ik een template, dan zou ik de template compilen en dat cachen:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
<?php
class Template_13545 extends BaseTemplate
{
    // ...
}
?>


etc.
 
Chris -

Chris -

05/12/2013 19:22:32
Quote Anchor link
maar dat komt dan toch uiteindelijk neer op één principe: opslaan/ophalen/verwijderen van specifieke data uit een voorgedefinieerde map en een bijhorende 'identifier'?

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!
 
Ozzie PHP

Ozzie PHP

07/12/2013 01:06:22
Quote Anchor link
Nog even een vraagje... als je een exception niet opvangt en je hebt een exception handler functie ingesteld, gaat de code dan verder na het gooien van die exception die niet wordt opgevangen (maar dus wel in de exception handler functie terecht komt)? Ik kan het zelf even niet testen nu, vandaar mijn vraag.

Stel:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
<?php

public function foo() {
  throw new UncaughtException('ik word niet opgevangen');
  echo 'hallo allemaal';
}


?>

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?
 
Ward van der Put
Moderator

Ward van der Put

07/12/2013 07:51:46
Quote Anchor link
Nee, dan zou je die echo in de exception handler moeten opnemen, want: “Execution will stop after the exception_handler is called.”
 
Wouter J

Wouter J

07/12/2013 12:54:06
Quote Anchor link
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.
 
Ozzie PHP

Ozzie PHP

07/12/2013 16:08:12
Quote Anchor link
Oei... dan had ik het verkeerd geinterpreteerd. Mijn idee was om sommige onschuldige exceptions op een hoger niveau te vangen en te loggen. Stel bijv. het cachen lukt niet en de cacher gooit een CacherException. Ik zat dan te denken, als ik die niet opvang en gewoon naar boven laat opborrelen naar de exception handler function, dan kan ie daar mooi gelogd worden. Maar dat werkt dus niet, want dan zou de applicatie direct stoppen.

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)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
<?php
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
 
Wouter J

Wouter J

07/12/2013 16:18:13
Quote Anchor link
Over het algemeen laat je die exceptions juist wel opborrelen. Deze exceptions kom je al tegen in de dev. omgeving en ga je dan oplossen.

En ja, zodra je niet wilt dat je applicatie stopt moet je hem van te voren opvangen.
 
Ozzie PHP

Ozzie PHP

07/12/2013 16:26:01
Quote Anchor link
>> Over het algemeen laat je die exceptions juist wel opborrelen. Deze exceptions kom je al tegen in de dev. omgeving en ga je dan oplossen.

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...)
 
Wouter J

Wouter J

07/12/2013 16:32:31
Quote Anchor link
Het 2x locken van een object is een zogenaamde LogicException. Het is een exception die je bij het testen van je applicatie al door kan hebben en die als het ware door de compiler (als PHP er eentje had) gevonden wordt.

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.
 
Ozzie PHP

Ozzie PHP

11/12/2013 22:43:05
Quote Anchor link
Even nog een exception vraagje... ik ben even e.e.a. aan het ombouwen waardoor ik het nu niet zelf kan uittesten.

Als ik dit doe:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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!';
}

?>

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
 
Wouter J

Wouter J

11/12/2013 22:47:34
Quote Anchor link
Zou ik jou eens een paar hele handige site's geven?

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
 

Pagina: « vorige 1 2 3 volgende »



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.