SitePoint Sponsor

User Tag List

Results 1 to 11 of 11
  1. #1
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,816
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)

    Whats the point of 'throwing' exceptions

    For the longest time I've thought that exception weer 'thrown' automatically when (after) some sort of error in the script occurred ( maybe they are and I am doing something wrong). and that I could THEN 'catch' that exception to run some code.

    for example if I had called an nonexistent method in a class within a TRY block, an exception would AUTOMATICALLY be thrown which, if uncaught , would stop the script but if I had a CATCH block then I could execute some other code/ gather information about the error, etc.

    Thinking about it, maybe this explanation of what an exception is will clarify what/why am asking my question

    Code:
    <?
    function inverse($x) {
        if (!$x) {
            throw new Exception('Division by zero.');
        }
        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\n";
    ?>



    in the above code no actually error occurs, it's merely ANTICIPATED ... as such one wonders why not just ( if we even concerned about reusability) use a regular function to report the error... what would be the ADVANTAGE, GENERALLY SPEAKING, over say using this :

    Code:
    <? 
     function errFoo($mess){
      echo '"faux  exception": ',$mess, "\n";
     }
     function inverse($x) {
        if (!$x) {
            errFoo('Division by zero.');
            return false; 
        }
        return 1/$x;
    }
    
        echo inverse(5) . "\n";
        echo inverse(0) . "\n";
    echo "Hello World\n";
    ?>

    Thanks in advance for your answers !!

  2. #2
    Programming Team silver trophybronze trophy
    Mittineague's Avatar
    Join Date
    Jul 2005
    Location
    West Springfield, Massachusetts
    Posts
    17,238
    Mentioned
    194 Post(s)
    Tagged
    2 Thread(s)
    For your example I see little difference.

    I think where throwing comes in useful is when there is also an set_exception_handler

    Not always useful, but if for example you are running a bunch of database queries it might be a good thing to not proceed with them (eg. do a rollback) and still have some kind of page show instead of a nasty error message or blank screen.

  3. #3
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by dresden_phoenix View Post
    what would be the ADVANTAGE, GENERALLY SPEAKING, over say using this :

    Code:
    <? 
     function errFoo($mess){
      echo '"faux  exception": ',$mess, "\n";
     }
     function inverse($x) {
        if (!$x) {
            errFoo('Division by zero.');
            return false; 
        }
        return 1/$x;
    }
    
        echo inverse(5) . "\n";
        echo inverse(0) . "\n";
    echo "Hello World\n";
    ?>
    The biggest difference I see is that in this code, your inverse function decides how to respond to an error. Whereas in the former example, the code that uses inverse decides how to respond. Depending on the application, you may want to report errors in a variety of ways, maybe with an HTTP response, or by logging to a file, or by sending an email, etc. But if the error reporting is baked into inverse, then you lose an awful lot of flexibility.
    "First make it work. Then make it better."

  4. #4
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,184
    Mentioned
    17 Post(s)
    Tagged
    4 Thread(s)
    Well for one it is nice to adhere to the same interface for throwing exceptions. An exception isn't really an error per say. Second exceptions bubble up through the current code exception path. Which means the class/function/etc. throwing the exception doesn't need to know anything about what to do with it. This promotes a well structured, loosely coupled architecture. Not to mention when all else fails the application language can be responsible for handling the exception if it bubbles up the entire code execution path without being handled. Third using classes instead functions makes inheritance, polymorphism, and encapsulation possible. This makes it easy to define custom exceptions and add more information perhaps for a logger or something. Having different variations of exceptions that can be used in the same way is a very powerful basic concept of oop and programming to an interface rather than an implementation.

    Tough the primary difference between standard exception handling pattern and the code snippet provided is that using your own function the application is now tightly coupled to that error function. Imagine if you were creating a library for others to use via composer like Swiftmailer. It would be like pulling teeth to override your one off error handling mechanism. Where as with exceptions one could merely wrap code that interacts with Swift mailer in a try catch block and handle any exceptions thrown by the dependent library anyway which they wanted.

    I guess from a procedural (spaghetti code) and small application/site standpoint what you provided might make some sense. However, from a OOP perspective there is absolutely no advantage over the standard exception handling. If anything there are several disadvantages almost taking use back to the way you would need to handle errors and exceptions in straight c.
    The only code I hate more than my own is everyone else's.

  5. #5
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,816
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    @Jeff...

    Thats sort of what I am talking about. ( my code comes from php.net, btw) , inverse() decides based on programmer code when rot throw the exception, in my alternative version I call a suction instead. you may want to report errors in a variety of ways, maybe with an HTTP response, or by logging to a file, or by sending an email, etc. with the errFoo() ( in essence errFoo() is the 'interface')

    I guess what I am asking is why exceptions are thrown 'manually' . If i HAVE TO throw the exception for division by zero; I have to expect that SPECIFIC type of error, which doesn't seem to allow for 'loosely coupled architecture'. I want to be clear, I LOVE the idea of exceptions.. it's the fact that you have to THROW them yourself that is confusing me.


    Consider a method that 'fails' if one of several specific data types are sent to it. for example a function which echoes a variable
    Code:
    function outp($word='nada'){ echo $word ;}
    ... of course , objects can't be converted to strings so that will give an error.

    I can't simply do

    Code:
    $wrong= new OBJ();
    try {
      outp($wrong);
    }
    catch($e){
    echo "oops!", $e->getMessage(), "\n";
    }

    it seems i MUST have some line in the code to check the type of $wrong and throw the exception. which really means that could just as employ a different handling mechanism, since I already know the error and why ( otherwise how could I have know to throw the exception?). How could you 'uncouple' something which you need know so specifically , in order to throw?


    As exceptions are an integral part of OOP ,am obviously off in my thinking... I just don't know how.

  6. #6
    Always A Novice bronze trophy
    K. Wolfe's Avatar
    Join Date
    Nov 2003
    Location
    Columbus, OH
    Posts
    2,182
    Mentioned
    67 Post(s)
    Tagged
    2 Thread(s)
    It's mandatory for me to drop this here: https://github.com/KyleWolfe/PHPErrorNet

    I'm ready for a fire fight again, it's usually how this conversation goes... Errors and notices in PHP are awful. Flip them all to exceptions, halt execution ALL THE TIME.

    Nice side affect, now you don't have to throw those exceptions for division by 0, that error is now an ErrorException (which is built in btw, its just not how they are handled by default.)

  7. #7
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by dresden_phoenix View Post
    you may want to report errors in a variety of ways, maybe with an HTTP response, or by logging to a file, or by sending an email, etc. with the errFoo() ( in essence errFoo() is the 'interface')
    When you call errFoo, you're calling a particular implementation. So you've hindered your ability to respond to different errors in particular ways. Also, since errFoo doesn't "bubble" like exceptions do, it doesn't give the rest of your application code a chance to handle the error.

    Quote Originally Posted by dresden_phoenix View Post
    I guess what I am asking is why exceptions are thrown 'manually' .
    In the division by zero case, you can blame PHP for that one. In Java, for example, I think it would automatically throw an ArithmeticException. But PHP originated from a procedural programming style, so it still uses error handling functions for a lot of things.

    I vaguely recall reading somewhere that PHP was working toward converting its errors and warnings into actual exceptions. But in the mean time, you can use the workaround shown in this example.

    Code PHP:
    <?php
     
    // Use set_error_handler() to change error messages into ErrorException
    function exception_error_handler($errno, $errstr, $errfile, $errline ) {
        throw new ErrorException($errstr, 0, $errno, $errfile, $errline);
    }
    set_error_handler("exception_error_handler");
     
     
    function inverse($x) {
        /*
        No more manual throwing
        if (!$x) {
            throw new Exception('Division by zero.');
        }
        */
        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\n";
    "First make it work. Then make it better."

  8. #8
    SitePoint Wizard bronze trophy
    Join Date
    Jul 2006
    Location
    Augusta, Georgia, United States
    Posts
    4,184
    Mentioned
    17 Post(s)
    Tagged
    4 Thread(s)
    Throwing exceptions manually provides a level of granularity that the application language itself can't resolve. For example, rather than simply throwing an exception that a query failed an exception could be thrown that provides increasingly more information for a debugger or global exception handler. This promotes an application/framework that is easier to debug and resolve issues when they occur rather than relying on the less contextual default exceptions within php. In many cases some functions error rather than throwing exceptions like they should which is also a good candidate for manual exception handling instead of what would possibly be errors instead.
    The only code I hate more than my own is everyone else's.

  9. #9
    Programming Team silver trophybronze trophy
    Mittineague's Avatar
    Join Date
    Jul 2005
    Location
    West Springfield, Massachusetts
    Posts
    17,238
    Mentioned
    194 Post(s)
    Tagged
    2 Thread(s)
    A bit off-topic, but I found this from the This Week in JavaScript - 28 April 2014 thread interesting

  10. #10
    Community Advisor silver trophybronze trophy
    dresden_phoenix's Avatar
    Join Date
    Jun 2008
    Location
    Madison, WI
    Posts
    2,816
    Mentioned
    34 Post(s)
    Tagged
    2 Thread(s)
    @Jeff: exception_error_handler() that makes sense now!!!


    @oddz:
    Throwing exceptions manually provides a level of granularity that the application language itself can't resolve. For example, rather than simply throwing an exception that a query failed an exception could be thrown that provides increasingly more information for a debugger or global exception handler.
    hmmmm, yes. But ONLY in the cases of error types you already expect, which is kinda like saying " I know this MIGHT occur , but I just don't feel I have the time to actually solve the issue now".

    for example if PHP didn't allow negative numerators , we would need to ANTICIPATE that bug, and add a line of code that threw a DIFFERENT exception for that particular case. If, on top of that PHP didn't allow division by decimals, but we didn't know this fact , the script would still crash, as no exception would be thrown since we didn't anticipate this particular limitation.

    Don't get me wrong, I can see the use of being ABLE TO trigger custom errors (throw exceptions manually) on occasion it's just that it seemed pretty limited if that was the only time PHP threw exceptions.

  11. #11
    SitePoint Wizard bronze trophy Jeff Mott's Avatar
    Join Date
    Jul 2009
    Posts
    1,313
    Mentioned
    19 Post(s)
    Tagged
    1 Thread(s)
    Quote Originally Posted by dresden_phoenix View Post
    hmmmm, yes. But ONLY in the cases of error types you already expect
    I would say this is about half right. The crucial bit of missing information is that, thanks to inheritance, we have the option to catch any generic exception. catch (Exception $e) will catch everything, no matter how specific of an exception we may have created. That means, for example, that lower level code might catch (SomeSpecificException $e) and say, "I know how to fix that! Let me handle that for you." Then at a high level in your code, you would catch (Exception $e) in order to catch all the exceptions that couldn't be handled in a better way, at which point your catch code might send an email to the site admin, log the error, then send the user a friendly message, "Oops. Something went wrong."

    EDIT: After writing all that, I realized that I may have misinterpreted your last post.
    "First make it work. Then make it better."


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •