views:

126

answers:

8

Hello, 3 days ago I started rewriting one of my scripts in OOP using classes as a practice after reading a lot about the advantages of using OOP.

Now I'm confused weather I should use exceptions or not. They seem to make my work harder and longer.

My application check if the data was sent through an Ajax request or not then uses that info through the script.

Check this example :

 /*
 * The older way
 */

if($ajaxEnabled) {
    $error = errorWrap('Ajax error');
} else {
    $error = errorWithBackLinkWrap('NoAjax error');
}

function doSomething() {
    if(empty($POST['name'])) {
            die($error);
    }
}

/* 
 * OOP way
 */

class someClass {
    private $_ajaxEnabled;

    public function doSomething() {
        try {
            if(!$this->_isDateValid()) {
                if($this->$_ajaxEnabled) {
                    throw new ajaxException('Ajax error');
                } else {
                    throw new noAjaxException('NOAjaxError');
                }
            }
        } catch(ajaxException $e) {
            echo $e->getErrorMessage();
        } catch(noAjaxException $e) {
            echo $e->getErrorMessage();
        }
    }
}

This code is only for demonstrating the problem, so I know there are some undefined functions in it :).

So before going oop, error handling was easier for me because I only had to echo the appropriate error.

Now using exceptions, in every function I have to check the type of connection first then write 2 catch functions for each thrown exception, which lead to a much larger code.

I'm really new to OOP in php so maybe there is a cleaner and a better way to do this, is there ?

+2  A: 

You shouldn't use exceptions when your code can handle the error gracefully using an if statement (like you did there on your example).

Exceptions are for situation that are well, exceptional. Unfortunately this is not very straightforward, so it's up to you, the programmer, to decide what is exceptional or not. I think a good rule of thumb is:

Avoid using exceptions to indicate conditions that can reasonably be expected as part of the typical functioning of the method.

From: http://www.codeproject.com/KB/dotnet/When_to_use_exceptions.aspx

NullUserException
CodeProject is a favorite resource of mine but the article link posted above has one of the lowest scores and harshest reviews I've ever seen on CP. Please consider finding a better resource for this topic.
Paul Sasik
@Paul I posted the link because of the quote
NullUserException
+2  A: 

Exceptions' usefullness is not in printing error codes. It's in catching error so you can try to solve them instead of crashing with fireworks.

klez
A: 

If all you need is to display error message, why don't you use

catch (Exception $e)
{ print ($e->getMessage()); }
a1ex07
What's the point of this? This would be like saying "I don't know what went wrong, and don't care. I'll just let the user know what went wrong and then continue on with the request". What happens if the `Exception` was that the database went away. And then you keep going trying to query, and get a new exception each time... Personally, I think that's bad practice unless you're specifically debugging a particular block of code...
ircmaxell
This is a perfect example of how *not* to (mis)use Exceptions. See ircmaxell.
delnan
The point of this is not to list all exceptions (as it was in original code). Also, I didn't see any exception handling but displaying a message.
a1ex07
I know, but I still really feel that any time I see `catch (Exception $e)` outside of the top-most scope that you're really just saying, `"I don't care what went wrong, I'll just keep going or try to guess..."`. It defeats the point of Exceptions. In other languages what would happen if the exception was an `OutOfMemoryException` and you tried to ignore it? I really just don't like seeing that kind of thing... It has its uses, but IMHO I feel more often than not it's a sign of code-rot...
ircmaxell
I agree, `catch (Exception $e)` is not a good idea. I just wanted to show that writing a number of `catch`es that just print error messages is also not a good solution. I should have written something like `catch (MyExceptionBaseClass $e)` to illustrate that.
a1ex07
A: 

I personally hate exceptions. I don't work with them in my applications. I prefer functions returning (and expecting) defined status codes, and dealing with recoverable errors on that level.

In truly exceptional situations (like an unreachable database server, a file I/O error etc.) that are an immediate emergency, I tend to trigger and handle a fatal error. (Object shutdown will still take place, so any connections that need closing etc. will still be handled as long as they are placed in destructor functions.)

Third party libraries' exceptions I strive to catch as quickly as possible, and deal with them in my own way.

Joel Spolsky puts the reasons much better than I could in his notorious Exceptions essay.

Note that this is one view and one school of thought. There is a lot of brilliant software whose error handling is based entirely on exceptions, and that is perfectly fine. The key is consistence - either you make the design decision to use them, or you don't.

Pekka
A: 

If I understand how you're doing it, I think you're doing it wrong. Exceptions for not for errors. They are for exceptional circumstances. Errors can mean any number of things (for example, a user didn't enter a long enough user name on a registration form). That itself shouldn't be an exception. You could however use an exception to show that registration itself failed (Depending on the situation)...

And you don't need to have a try/catch block at every level. In fact, that's bad practice. Only catch exceptions if you either can handle the exception, or need to do something else before letting the exception continue. So, for example: If you are connecting to a remote set of websites, and the first one fails. You can catch the exception for that one, and retry with a second website. And keep going until you have no more left (at which point you'd throw another exception to indicate that no websites could be fetched). Another example would be if you're generating images. You have a method that does some computation while generating the image that throws an exception. You'll want to catch that exception so that you can "clean up" from the image process (to save memory, etc) and then re-throw it once you're done: catch (ImageSomethingException $e) { /* Clean up here */ throw $e; }...

The true power of exceptions is that it lets you handle the situations however you want (since the exception can just bubble up to the top of the program). But only catch exceptions where you know you can deal with them (or at least need to clean up). You should almost never do print $e->getMessage() inside of production code.

Personally, I have a default exception handler that I always install. Basically, if an exception is not caught, it will log that exception and then generate a 500 error page. That lets me focus on what exceptions I can deal with in code instead of trying to catch everything (which isn't usually a great idea)...

Good luck...

ircmaxell
+1  A: 

Exceptions as an error handling mechanism are VERY different in concept and implementation than function return codes. You cannot/should not simply map one to the other. You should read and digest this article (and then a few more including this one*) before proceeding further.

If you're going to favor exceptions instead of return codes for error reporting/handling then the structure of your code should change significantly.

(*The CodeProject link is .NET-specific but there's little code ti digest. It's mostly a best-practices article easily applicable to any language.)

Paul Sasik
Wow, that link on the `.NET` exceptions is quite worth the read... +1
ircmaxell
+1  A: 

There is a finite capacity to most development processes - i.e. even where its possible to predict all possible circumstances that the code might run in (i.e. all possible combinations of inputs, all possible states for supporting systems like database, DNS, existing data etc) then its just not practical to deal with every scenario. Using exceptions allows you:

  1. to bundle a series of operations into one entity for the purposes of determining success/ failure as a whole

  2. handle multiple different modes of failures with a single bit of code

So yes - I'd say that exception handling is a useful practice - but not a substitute for handling the common failure modes specifically, intelligently and informatively (and typed exceptions are IMHO a complete oxymoron).

symcbean
+1  A: 

Your question is not uncommon, whether/when to use exception is sometimes a philosophical decision and many experienced developers can't wrap their heads around it.

That being said, I've found that listing out the distinct properties of each way of handling error makes it easy to choose your preferred way:

Return code

  • The caller can ignore it or forget to check it
  • The caller usually needs more documentation reading before he can use it (does 0 mean success or failure?)
  • Object destruction is not guaranteed -- it all depends on the caller to clean up properly

When to use: It's pretty obvious. Use return codes when you trust the caller (internal code or trivial errors which can be safely ignored).

Exceptions

  • The caller cannot ignore it
  • The caller can still suppress it if he wants (with an empty try/catch)
  • Object destruction takes places properly -- most of the time

When to use: When you don't trust your caller as much (third party) or you really need to make sure your error code doesn't go ignored.

Die

  • Cannot be ignored and cannot be suppressed

When to use: It's usually obvious enough. You need everything to stop immediately.

(In a PHP context, I don't think it makes much difference. The above suggestions should still apply.)


(Aside)

Usually it's tempting to just write out an error message when something bad happens (especially when the first programming language you learned is PHP :P). But if you really want to grok OOP, it's not a proper way to handle errors.

Every object or every function should ideally only perform one function. If one function writes error to the screen and does its own thing, it's difficult to later switch to a DatabaseErrorLogger or TextFileErrorLogger or etc. One approach would be to supply a logger to use (this is called Dependency Injection). Another way to do it is to use exception -- this way, the caller gets to choose which ErrorLogger to use.

kizzx2
I can't thank you enough, I never thought it can be explained with this level of clarity. Though I appreciate every one who answered my question, some of the answers made me more confused and I thought I should stop with OOP. I will try to read even more (I've been learning opp php the whole past month :( ) about opp php and error handling.
Maher4Ever