Ola peepz,

Nog even een vraagje over eigen exception classes.

Mij werd dus aangeraden om eigen exception classes te gebruiken. Nu zien die classes er allemaal ongeveer zo uit:

<?php

namespace Foo;

use Bar\MyException;

class Exception extends MyException {

public function __construct($message, $code, $previous = null) {
parent::__construct($message, $code, $previous);
}

}
?>
Nu is het zo dat de MyException class een constructor heeft die identiek is aan de constructor van de Foo Exception class. De constructor in de Foo Exception class levert op dit moment dus geen meerwaarde en zou ik dus compleet achterwege kunnen laten. (Hierbij ga ik er nu even vanuit dat ik de $message niet wil aanpassen met een of andere standaardtekst.)

Als ik de constructor zou weglaten, krijg ik als het ware een lege class. Is dat niet vreemd? Of is dit gewoon oké?

<?php

namespace Foo;

use Bar\MyException;

class Exception extends MyException {}

?>
>> Dus mijn opzet zoals ik die nu heb die klopt dan gewoon?

jupperdejuppie
>> Nee, geen algemene exceptions. De Class A zal echter alleen een Cacher exception willen ontvangen (met als previous exception de FileSystemException). Het zal me een worst wezen wat die cacher heeft gedaan waardoor het niet lukte, dat heb ik alleen nodig bij het debuggen. Voor de code wil ik alleen weten dat die Cacher het niet is gelukt.

Oké... dan klopt het dus hoe ik het nu doe :)

Toevoeging op 17/11/2013 15:47:56:

>> jupperdejuppie

Jeee!! :-)))

Toevoeging op 17/11/2013 17:05:30:

Wouter, nog even een vraagje over wat jij eerder zei. Jij zei dat het nuttig is om een exception hiërarchie op te bouwen.

>> En dat is juist het mooie van het gebruik van hierarchy. In sommige gevallen wil je gewoon alle database problemen, of zelfs alle problemen, op vangen, terwijl je in andere gevallen alleen de connectie problemen wil opvangen. Het gebruik van hierarchy is juist het mooie van exceptions, gooi je dat weg kan je lekker alleen met een base klasse gaan werken...

Kun je een praktijk-voorbeeld geven wanneer zo'n hiërarchie een meerwaarde kan zijn?

Wat ik namelijk niet helemaal begrijp... stel we hebben een FooException, en we hebben 5 andere Exceptions die de FooException extenden. Wat is dan precies daar de meerwaarde van? Blijkbaar kunnen we dit doen om in 1x alle FooExceptions te catchen? Oké, prima... maar als dat de reden is, en we blijkbaar alle FooExceptions op dezelfde manier willen behandelen, waarom gebruiken we dan niet slechts 1 FooException?

In de praktijk... waarom zouden we bijv. een DirectoryException maken en een FileException, die beiden de FileSystemException extenden? Ik kan toch gewoon 1 FileSystemException gebruiken en via $message aangeven wat er fout gaat ("Er kan geen directory worden aangemaakt" of "De file kan niet worden opgeslagen".) Waarom zou je hier meerdere Exceptions voor willen gebruiken?
Ozzie PHP op 17/11/2013 15:47:34

In de praktijk... waarom zouden we bijv. een DirectoryException maken en een FileException, die beiden de FileSystemException extenden? Ik kan toch gewoon 1 FileSystemException gebruiken en via $message aangeven wat er fout gaat ("Er kan geen directory worden aangemaakt" of "De file kan niet worden opgeslagen".) Waarom zou je hier meerdere Exceptions voor willen gebruiken?

Zou je daarvoor dan niet op zijn minst $code gebruiken met een unieke integer/constante? Als het toch één exception is, kan je daarmee in elk geval nog varianten van dezelfde exception onderscheiden.

Een file system is sowieso een klasse apart (hint-hint) omdat een directory technisch weinig meer is dan een bestand dat andere bestanden bevat. Hetzelfde geldt voor een zip-bestand of ander type archive. En hetzelfde geldt voor constructies zoals een station en een partitie. Je hebt hier een iterator nodig en daarmee een speciale exception.
>> Zou je daarvoor dan niet op zijn minst $code gebruiken met een unieke integer/constante? Als het toch één exception is, kan je daarmee in elk geval nog varianten van dezelfde exception onderscheiden.

Waarvoor zou je dan precies een code gebruiken? Ik kan toch ook een message gebruiken om te zeggen wat er mis is? Als ik bijv. zou zeggen, foutcode is 20, dan weet ik niet wat er wordt bedoeld. Als ik echter een message hebt die zegt "Ik kan geen directory aanmaken" dan snap ik wel wat er wordt bedoeld. Wat is de meerwaarde van een code?

Kan iemand dan een praktijk-voorbeeld geven wanneer het extenden van Exceptions nuttig is, want dat begrijp ik nog steeds niet.
http://www.php.net/manual/en/spl.exceptions.php

<?php

try
{
...
}
catch (InvalidArgumentException $e) {}
catch (BadMethodCallException $e) {}
catch (OutOfRangeException $e) {}

if (isset($e))
{
// doe iets (DRY, maar hacky)
}

// Versus

try
{
...
}
catch (LogicException $e)
{
// doe iets
}

?>
Dos, thanks... maar wat heeft dit precies met mijn vraag te maken?? :)
Het eerste kun je zonder hiërarchie ook.
Het tweede niet. (Ik reken \Exception even niet als hiërarchie.)
Een hele groep van exceptions af kunnen vangen is als programmeur fijner dan elke exception individueel afvangen.
Dos, dat kan ik in zeker zin wel volgen... maar ik snap niet wanneer je het in de praktijk zou moeten gebruiken. Wat jij nu laat zien is (als ik je goed begrijp) dat je een heleboel Exception classes de LogicException class laat extenden, en uiteindelijk vang je dan de LogicException op. Maar dan weet je aan het eind van de rit toch helemaal niet welke Exception je opvangt, en hoe je die moet afvangen?

Ik snap technisch gezien wel wat je doen, maar ik zie het nut tot op heden nog niet. Jouw voorbeeld zou je ook iedere exception de standaard exception kunnen laten extenden en dan in het catch-blok kunnen controleren op Exception.

Ik vind het nog een beetje vaag, en ik zie tot nu toe eerlijk gezegd ook nog geen enkel praktijk-voorbeeld.
Oké, we blijven bij onze DatabaseExceptions. Stel we hebben een database cacher. Het zal die cacher een worst wezen of het een CouldNotConnectException is of een InvalidQueryException. Het gaat die cacher erom dat de database niet werkt.

Daarom zal die cacher gaan catchen op de algemene DatabaseException. Dat terwijl de database klasse alleen maar CouldNotConnectException of InvalidQueryException gooit.

Dan hebben we nu een UserMapper. Zodra we daar een user by id opvragen zal hij ook die database klasse willen gebruiken. Voor hem is het echter wel belangrijk wat het type exception is. De CouldNotConnectException zal hij namelijk lekker moeten laten opborrelen, maar een InvalidQueryException is een exception die aangeeft dat hij iets fout doet. Dat moet hij dus zelf zien op te lossen.

Daarom is het gebruik van hierarchy belangrijk.

En een code is inderdaad onduidelijk, behalve als je er een constante aan hangt. Bijv. CouldNotConnectException::ERR_INVALID_CREDENTIALS. Je gebruikt codes omdat je weet dat je deze verschillende typen exceptions niet apart wilt catchen, maar je wilt toch onderscheid ertussen maken.
Dankjewel Wouter, nu wordt het al wat duidelijker.

Dat van die codes snap ik nog niet helemaal. Ten eerste, gebruik jij echt een code (een nummertje)? En ten tweede, wat is het verschil of ik dan die code meegeef, of in mijn $message "Invalid credentials" zet. Dat komt toch op hetzelfde neer?

Reageren