Wednesday, July 25, 2012

Throw your own - Nested exceptions

If you think that working with exceptions is hard to understand, exception nesting will look even harder (nested exceptions, chained exceptions, exception bubbling - it is all the same). Well, it is a step above, and it can be used if your application is structured in several layers, but at the end you'll see that it is a concept which is here to make your life easier.

The basic syntax
try
{
 // do something that can go wrong
}
catch (Exception $e)
{
 throw new Exception( 'Something really gone wrong', 0, $e);
}
Yes, you could see that kind of example at php.net, but it still does not make much sense. Why you caught it at first place, just to throw a new one? To be honest, it is a bad example (just like the examples on php.net). No wonder that you can not understand it.
But lets stick on it for one more moment.
First, you caught exception, like in any other try catch block, and than you passed it to an another one. It means that the second exception has reference to the first one, and who ever catch that second exception, will have access to the first exception too (the previous or the cause). It is hard to notice from this example, but you are probably guessing, it can be very helpful when debugging your application.

Adding useful information

function get_db_connection( )
{
 throw new Exception( 'Could not connect to database');
}

function update_email( $username, $email)
{
 try
 {
  $conn = get_db_connection();
  $conn->update( "UPDATE user SET email = '$email' WHERE username = '$username'");
 }
 catch (Exception $e)
 {
  throw new Exception( 'Failed to save email ['.$email.'] for user ['.$username.']', 0, $e);
 }
}

try
{
 update_email( 'myusername', 'newmail@foo.com');
}
catch (Exception $e)
{
 echo($e->getMessage().'
'.$e->getTraceAsString().'
'); while($e = $e->getPrevious()) echo('Caused by: '.$e->getMessage().'
'.$e->getTraceAsString().'
'); }
In this example we are outputting error information on screen, but in the real life situation, it should go to your log file. That way, when database error occurs, instead of only knowing that database connection was corrupted, you will know exactly which users encountered that problem too.

Pre Php 5.3 problem
Although passing cause exception as argument to a new one is a standard feature in languages which are supporting try/catch syntax, PHP architects included it in version 5.3. So if your application should be compatible with PHP versions before 5.3 you will have to do workaround to support nested exceptions. It can be done, it is not too hard, but I'll write about it in some other article.

Conclusion
The best motivation to use nested exceptions is when you are not satisfied with exceptions that your lower layers are throwing. During the development and debugging, when you encounter such situation, just catch it and add additional useful information. In most cases it will assume that you are using some external libraries (which original source you should not change) and that your application has multiple layers of functionality. Do not forget that your logging mechanism should be aware and capable of nested exceptions too.

Tuesday, October 4, 2011

Throw your own - Custom Exceptions

The key to understanding custom exception concept lies in knowing how to catch them. You have to know syntax, and you have to know how to use it.

First, the syntax itself
try 
{}
catch (CustomException $e)
{}
catch (OtherException $e)
{}
catch (Exception $e)
{}
Basicaly it looks like an switch/case statement. The above code could be written as the next one, and all will be valid and will work perfectly. The try catch syntax is actually automatically handled multiple if statement!
try 
{}
catch (Exception $e)
{
	if ($e instanceof CustomException)
	{}
	else if ($e instanceof OtherException)
	{}
	else
	{}
}


Throw your own
Note that by distinguishing exceptions you can decide which are the fatal errors and which exceptions are only passing you an information that something is wrong and it is a handled case. This means that you have to use Exceptions not only on critical situations. Throw them for your handled situations too.

class MyAuthException extends Exception
{}

class MyTest
{
	private $_connected;
	
	public function __construct( $connected)
	{
		$this->_connected	=	$connected;
	}
	
	
	public function printData( $auth)
	{
		try 
		{
			if ($auth != 'foo')
				throw new MyAuthException( 'Not an [foo] exception');
			if (!$this->_connected);
				throw new Exception( 'System is not connected');
				
			echo 'Authorized!';
		}
		catch (Exception $e)
		{
			die($e->getMessage().'
'.$e->getTraceAsString().'
'); } } } //$test = new MyTest( true); $test = new MyTest( false); try { $test->printData( 'foo'); // $test->printData( 'bar'); } catch (MyAuthException $e) { echo 'Not authorized'; } catch (Exception $e) { die($e->getMessage().'
'.$e->getTraceAsString().'
'); }


Be wise, work with exceptions
// BAD PRACTICE
$action->fooBar();
if ($action->isError())
{
	if ($action->getErrorCode() == 0)
	{}
	else if ($action->getErrorCode() == 1)
	{}
	else
	{}
}
else
{}
One could think that handling multiple types of exceptions can be replaced by simple if then else. The greatest disadvantage of this solution is not that you have to preserve your error state in your objects. The main problem is that you have to perform that check every time you have to handle that object. That leads you to situations where you will forget to check the error state.

Look at the same example written with exceptions. Less code and no additional error based methods you have to add to objects.
// GOOD PRACTICE
try 
{
	$action->fooBar();
}
catch (CustomException $e)
{}
catch (Exception $e)
{}
If you, in some case, forget to wrap fooBar() method in the try/catch block, your upper, application layers will catch that renegade exception and handle it.

Thursday, September 29, 2011

Throw your own - Losing the fear of Exceptions

The best way to lose the fear of exceptions is to start throwing them. Recipe is simple: whenever you come to case that something is wrong and your function or method can not accomplish its task, just throw an exception.

Example 1
My favorite case is when I'm using a configuration values in my applications. Ops, there is no value at all, not an numeric value? I'll just throw an exception and stop thinking about that. This case is especially important if your application will have several installations. This way you are ensuring that nobody (including you) can not forget to fill in configuration. Or, when such case happen anyway, problem will be immediately identified.
class MyIni
{

	private $_config;
	
	public function __construct( $config)
	{
		$this->_config	=	$config;
	}
	
	public function getProductId()
	{
		if (!isset($this->_config['productId']))
			throw new Exception( 'Required config parameter [productId] is not set');		
		if (!is_numeric( $this->_config['productId']))
			throw new Exception( 'Config parameter [productId] has not numeric value ['.$this->_config['productId'].']');		
		
		return $this->_config['productId'];
	}
}

//$test		=	new MyIni( array( 'productId' => 123)); // valid value
//$test		=	new MyIni( array( )); // not defined
$test		=	new MyIni( array( 'productId' => 'FooBar')); // not numeric

try {
	$product_id	=	$test->getProductId();
	echo 'Product Id is '.$product_id;	
} catch (Exception $e) {
	die($e->getMessage().'
'.$e->getTraceAsString().'
'); }

Example 2
Another favorite one is when switching between some predefined values. Someone passed not defined value? OK, here is an exception. This case is important when your component will be used by another developers too.
class MySwitch
{
	const GENDER_MALE		=	'MALE';
	const GENDER_FEMALE		=	'FEMALE';
	
	public static function getOpositeGender( $gender)
	{
		if (self::GENDER_FEMALE == $gender)
			return self::GENDER_MALE;
		if (self::GENDER_MALE == $gender)
			return self::GENDER_FEMALE;
		throw new Exception( 'Invalid gender value ['.$gender.']');
	}
}


try {
//	$gender	=	MySwitch::GENDER_MALE; // valid value
	$gender	=	'FooBar';	//	not defined value
	echo 'Oposite from '.$gender.' is '.MySwitch::getOpositeGender( $gender);	
} catch (Exception $e) {
	die($e->getMessage().'
'.$e->getTraceAsString().'
'); }

There is a good practice which can be applied all the time during the debug or test phase of your development project. When you encounter to an any problem, warning, notice, missing data or configuration, stop and ask your self do you know what exactly is wrong. First go to your source and add an exception which will describe what happened. Try it again and after you done that, fix what was wrong at the first place.

As the result, at the beginning you will more often see fatal error messages. But when you see it, you will exactly know what happened, where is the problem and what to do next. You will actually be glad that you wrote those throw exception statements.

Saturday, February 26, 2011

Returning the null value from a method

This example demonstrates the drawbacks of returning null from your methods. I allays preach to my colleagues that when something is wrong, your method should throw an exception instead of returning a null.
But sometimes, especially if I'm writing some tools for myself, because of the laziness, I use the return null too.

Few days ago I done that, and very soon I released that it was mistake which caused me unnecessary problems.

Story goes like this: There is an initial list of ids and result of a process is a array of fully populated objects. I use that procedure on two places in my tool: for generating RSS file and for generating a view script. The tool is written in Zend Framework, it uses a log file, when exception occurs displays a customized error page and sends a email to me.

Initially it was all flawless, but at some point, I released that I'm not able to read data for some of initial ids. So I modified a loading method in something like this:

public function loadItem( $id)
{
	$raw_data	=	$this->_getRawData( $id);
 	if ($this->_testRawData( $raw_data))
   		return $this->_parseData( $raw_data); 
 	return null;
}

Accordingly, I modified the controller part to:

public function rssAction() 
{   
	$ids	=	$this->getRssIds();   
 	$items 	= 	array();  
 	foreach ($ids as $id)   
 	{
  		$item = $this->manager->loadItem( $id);
  		if ($item)      
   			$items[] = $item;
  	}   
 	$this->view->items = $items;
}

I done it, tested the RSS feature and it was as expected, all OK. I've done few more fixes, and at last, after some time, I wanted to see the preview too.
Cold shower. PHP notices, warnings, fatal error. Undefined variable, call to a method on null object.... Why, how, what the hell ...?
Standard debugging procedure: I'm checking the log file. Nothing to find there. Next is to check the view script and associated action. Soon I found that the problem was that I had null values in array which supposed to be populated with objects. I simply forgot that I was using the same method on two places.

public function previewAction() 
{  
	$ids 	= 	$this->getPreviewIds();   
	$items 	= 	array();  
	foreach ($ids as $id)      
 		$items[] = $this->manager->loadItem( $id);
	$this->view->items = $items; 
}

At the end, as I'm experienced developer and this was my "in house" tool, I found and fixed it very quickly (still bad solution: again I put a test if the returned object is null), but it raised a really good question: When you are doing a bigger scale project, where you can not have all the things in your head, what is the right solution and what would be the consequences?

First the correct code variant:

// somewhwere in my manager class

public function loadItem( $id) 
{ 
 	$raw_data	=	$this->_getRawData( $id); 
 	if ($this->_testRawData( $raw_data))
   		return $this->_parseData( $raw_data); 
 	throw new ItemNotFoundException( 'Item ['.$id.'] could not be loaded');
} 

// somewhwere in my controller class 
public function rssAction() 
{ 
 	$ids 	= 	$this->getRssIds();  
 	$items 	= 	array();   
 	foreach ($ids as $id)   
 	{
  		try      
  		{       
   			$items[] = $this->manager->loadItem( $id);    
  		}      
  		catch (ItemNotFoundException $e)
  		{}   
  }   
  $this->view->items = $items; 
}
Let's assume that I still miss to upgrade the previewAction() method. Now, instead of bunch of warnings, I'll have Exception. This Exception is important because
1. Debugging: It will be stored to my log file, and in the development/testing process I'll quickly determine where is the problem and what I have to fix (Front controller handles it)
2. Application consistency: If I forgot to test any other part of my application which might use that manager method, and I put that code on live installation, users will encounter the customized error screen, error will be logged, and I'll receive the alarm email. The error will not be able to pass unnoticed!

Friday, November 26, 2010

Basic exception usage in php

Theory

If you have not already, check the official php documentation on exceptions at http://php.net/manual/en/language.exceptions.php. Besides some php specifics, here you can find basic example how to use try catch blocks and how to work with exceptions.

Example goes like this:
function inverse($x) {
 if (!$x) {
  throw new Exception('Division by zero.');
 }
 else return 1/$x;
}

try {
 echo inverse(5) . "\n";
 echo inverse(0) . "\n";
} catch (Exception $e) {
 echo 'Caught exception: ',  $e->getMessage(), "\n";
}

// Continue execution
echo 'Hello World';

Through this example you can see that if a process finds itself in a problematic situation, it can throw an exception. This exception can be caught, and that way we will prevent system to run into some php fatal error.

This are the theoretical basics, however, the real question is how and where to use exception handling in your  applications and scripts.



Front Controller
Front Controller is engine which runs your web application. If you are using a Zend Framework, then you are  probably using their MVC too. This MVC has in itself a front controller logic already built. On the other hand, if you have some of your engine that runs all requests through the index.php, then you probably have one class which carries the logic for including and executing different pages, or classes - that is front controller.
Theoretically, front controller is the only place where you should try to catch exceptions and probably log some info about it. In practice, you will catch them and even elsewhere, but I'll describe that issue some other time. This is quite enough for the beginning.
class Application
{
 public function init()
 {
  $page    =    $_GET['page'];
  try
  {
   require_once $page.'.php';
  }
  catch (Exception $e)
  {
   error_log( $e->getTraceAsString(), 3, 'error.log');             
   require_once 'error_page.php';              
  }
 }  
}

This is an example of a very simple application which will, depending on the passed GET parameter try to include (and execute) appropriate php script file.
It is important to note that this example shows that inside those included php scriptis, you can safely call any method that can throw the exception. You can even throw exceptions by yourself if you miss something for finishing requested process. When you have such a "rounded" application, exception will be logged and the user will be presented to an error page.
This is actually a minimum, bottom line, that your engine must comply.



Other classes
A simpler case is when you are developing "regular" classes, such as a daos for getting stored data. While building such classes, you do not have to think about what will hapen latter in other classes and processes if for example databes connection is broken, or user tries to hack the url parameters, or anything else goes wrong. You have to concentrate only on your "local" world, inside your calling method, and make it sure that the method executed well. In other words, either method will do all what is required from it, or otherwise if something is wrong, it will throw the appropriate exception.

class UserDao
{
 public $users    =    array( 1=>'Anny', 2=>'Sandra', 3=>'Monica');

 public function getUser( $userId)
 {
  if (!isset($this->users[$userId]))
   throw new Exception('User ['.$userId.'] not found in local array');

  return $this->users[$userId];
 }
}

This is a classic example where many web developers will return null and maybe try to define an error message that goes to the enduser. This is wrong because if you return null you are risking that an error passes  unnoticed. In that case your user can get the message "Hello Mrs null", and that is the better case. If you are working with the objects, you risk the fatal error after calling a method or property on the object which is null.

If, as in this example, you throw the exception, you can be sure that it will not go unnoticed. In addition, you have the opportunity to describe what happened in exception message, and help your self in latter bug tracing  sessions.
I would like to mention that in such cases it is better to throw some custom UserNotFoundExecption, but I'll explain the use of exception subclassing in another article.

Friday, November 19, 2010

Why exception handling is important in php?

    I work as a professional programmer for 10 years and in those 10 years I met a bunch of different developers. In plenty of them, especially in web / php developers, I could notice a lack of understanding of the concept of throwing and catching exceptions and what does it serves for. Of course, the first I noticed it at myself. In this blog I would like to point out a number of useful things that proper use of the exception can make, and which were slipping from my hands for a few years too.

    Exceptions are providing a standardized way to control problematic processes and they are reducing the possibility of fatal errors in the application. If process throws exception, you are forced to handle situation in your application, and it will automatically reduce the possibility that some problem sleeps out whit out being processed. When you're working with exceptions, you are handling problems at low level, so it will not make you problems with your higher layers, e.g displaying error messages to user.

    Work with exceptions make it easier to fix bugs when they happen. Errors in applications will always happen, especially in the real world of short deadlines and often requirement specification changes. However, when something goes wrong in your application, the question is when will you and will you even notice at all that something went wrong? And, also, how quickly you will know exactly what happened and what needs to be corrected? If you are working with the exceptions, this can be quite clear and painless issue that you will quickly and efficiently solve.

    PHP only since version 5 delivers the work with conventional try / catch system and it's quite a big problem for those developers who have not dealt with eg Java or C# too. In future posts I'll try to explain few simple general rules to follow that will help you to make the exceptions are not the problematic to you, but a tool which will increase your speed and quality.