Wondering how much effort I should go to forcing useful debugging information when creating exception messages, or should I just trust the user to supply the right info, or defer the information gathering to an exception handler?
I see a lot of people people doing their exceptions like:
throw new RuntimeException('MyObject is not an array')
or extending the default exceptions with custom exceptions that don't do much but change the name of the exception:
throw new WrongTypeException('MyObject is not an array')
But this doesn't supply much debugging info... and doesn't enforce any kind of formatting with the error message. So you could end up with exactly the same error producing two different error messages... eg "Database connection failed" vs "Could not connect to db"
Sure, if it bubbles to the top, it'll print the stack trace, which is useful, but it doesn't always tell me everything I need to know and usually I end up having to start shooting off var_dump() statements to discover what went wrong and where... though this could be somewhat offset with a decent exception handler.
I'm starting to think about something like the code below, where I require the thrower of the exception to supply necessary args to produce the correct error message. I'm thinking this might be the way to go in that:
- Minimum level of useful information must be supplied
- Produces somewhat consistent error messages
- Templates for exception messages all in the one location (exception classes), so easier to update the messages...
But I see the downside being that they are harder to use (requires you look up exception definition), and thus might discourage other programmers from using supplied exceptions...
I'd like some comment on this idea, & best practices for a consistent, flexible exception message framework.
/**
* @package MyExceptions
* MyWrongTypeException occurs when an object or
* datastructure is of the incorrect datatype.
* Program defensively!
* @param $objectName string name of object, eg "\$myObject"
* @param $object object object of the wrong type
* @param $expect string expected type of object eg 'integer'
* @param $message any additional human readable info.
* @param $code error code.
* @return Informative exception error message.
* @author secoif
*/
class MyWrongTypeException extends RuntimeException {
public function __construct($objectName, $object, $expected, $message = '', $code = 0) {
$receivedType = gettype($object)
$message = "Wrong Type: $objectName. Expected $expected, received $receivedType";
debug_dump($message, $object);
return parent::__construct($message, $code);
}
}
....
/**
* If we are in debug mode, append the var_dump of $object to $message
*/
function debug_dump(&$message, &$object) {
if (App::get_mode() == 'debug') {
ob_start();
var_dump($object);
$message = $message . "Debug Info: " . ob_get_clean();
}
}
Then used like:
// Hypothetical, supposed to return an array of user objects
$users = get_users(); // but instead returns the string 'bad'
// Ideally the $users model object would provide a validate() but for the sake
// of the example
if (is_array($users)) {
throw new MyWrongTypeException('$users', $users, 'array')
// returns
//"Wrong Type: $users. Expected array, received string
}
and we might do something like a nl2br in a custom exception handler to make things nice for html output.
Been reading: http://msdn.microsoft.com/en-us/library/cc511859.aspx#
And there is no mention of anything like this, so maybe it's a bad idea...