0

I've just read some articles about exceptions and the most part of the examples do this kind of stuff:

try{
    conn.close();
} catch(SQLException ex){
    logger.error("Cannot close connection");
    throw new RuntimeException(ex);
}

While I'm used to do this:

    try
    {
        $this->pdo = new PDO($dbInfo[0], $dbInfo[1], $dbInfo[2]);
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    }
    catch(PDOException $e)
    {
        $this->exceptionHandler->displayException($e);
    }

As you can see, I use a class to handle exception instead of re-throwing it.

For instance, if a class A uses a instance B which uses a instance C which can throws an exception, I will directly handle it in the class B and not re-trowing it to the class A.

However, according to the first example, it seems that the guy just re-throws all the sub classes exceptions to a main class (like A by using my example).

Is my method bad?

gaetanm
  • 1,394
  • 1
  • 13
  • 25
  • 1
    `Is my method bad?` What are you really asking? is the practice poor? is there a performance loss? – Ohgodwhy Aug 24 '14 at 10:15
  • Primarily opinion-based. Some people think you should avoid exceptions as much as possible, while others use them frequently as control flow statements. – GolezTrol Aug 24 '14 at 10:17
  • Quite similar to, maybe duplicate of: http://stackoverflow.com/questions/9898070/the-best-practise-when-to-use-php-exception-handling?rq=1 – GolezTrol Aug 24 '14 at 10:18
  • This question appears to be off-topic because it is about code review. Ask on [codereview.SE] instead. – idmean Aug 24 '14 at 12:15

3 Answers3

1

In your displayException() example, you're not doing anything else beside displaying the exception (assuming the method does what the name implies). This might be fine if you don't have any additional code running that relies on DB activity - which might be the case for a simple PHP app/script but it's hardly ever the case for Java applications. In a more complex application, you usually want to abort the execution of any further logic and dealing with the exception on a higher level, thus you'll want to be re-throwing the exception (in Java, often as an unchecked exception instead of checked one - PHP only has the unchecked ones).

About the choice in Java to convert a checked exception to an unchecked one, I heavily recommend article Effective Java Exceptions. It explains Java exception model in depth and when you should be doing what. It is a matter of opinion I guess, but I think the arguments laid out there are solid.

In the specific case SQLException you gave, there is somewhat a consensus in java community that it a) shouldn't have been a checked exception to begin with, and b) is too general to convey anything meaningful about the actual error. This is why you often either

  • catch it, add any relevant details to the exception or the logs and re-throw it as an unchecked exception or
  • use an exception translator like the one in Spring that does this for you automatically, or in the case of exception in a finally block,
  • use an auxiliary method that closes it quietly such as closeQuietly
eis
  • 51,991
  • 13
  • 150
  • 199
  • The concept of checked vs. unchecked exceptions of Java is unknown in PHP - we only have exception. So it is misleading to point to a Java exception article when answering PHP exception questions. – Sven Aug 24 '14 at 10:53
  • @Sven yes, if this were just about PHP exception question. However as far as I understand, this was asking about the differences in exception handling between Java and PHP and what is good practice in which. – eis Aug 24 '14 at 10:55
  • "It should be noted also that java applications, unlike PHP applications, run in a container that ultimately handles the exception if nothing else will." I think this is wrong. PHP itself is "that container" and will also handle exceptions. – Sven Aug 24 '14 at 10:59
  • I agree that was misleading. Java handles them in a way that sets the content types etc for a proper response, PHP "just exists" most of the time, but that's not really very relevant to my answer so I removed that part from my answer. – eis Aug 24 '14 at 11:05
1

First to clarify: a subsystem is a self contained function/object/method which has a particular responsibility. For example, a PDO instance's responsibility is to manage a database connection and allow you to interact with the database.

Now, once a subsystem encounters exceptional circumstances in which it cannot continue with its current operation, it throws an exception. For instance, the connection to the database may suddenly drop, an event that prevents PDO from doing what it's supposed to do. Since the subsystem cannot continue doing what it's supposed to do, it abandons ship and refuses to execute any more of its code, because there's no point to it. It signals this failure of expectations to its superior/caller by throwing an exception.

This caller now needs to deal with this situation. Assuming the caller is also dependent on the subsystem to do its task, there may be no point in it catching the exception directly. Say the caller of the PDO subsystem is a data-object mapper. Since the database connection failed, what's the data-object mapper supposed to do? It cannot continue its work either. So it should either rethrow the exception or not catch it in the first place.

The only time you want to catch an exception is if you have an actual plan how to deal with the exceptional circumstance, if you are prepared for a subsystem to fail and have a contingency plan. Say, one external HTTP request fails and you have another URL you can query as fallback. But unless you have such a fallback plan, it's pointless to stop an exception. Let it bubble up as far as possible to a point where it can be contained in a useful way. Certain exceptions probably cannot be contained at all; in that case let them bubble up all the way to stop the program with an error page.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • I would oppose the idea to not catch the exception. This leads to "unknown error occurred" messages because the top level application catches all exceptions, but doesn't know how to deal with them. When using a module that internally uses PDO, I wouldn't expect to get PDO's exceptions passed - this is a very leaky abstraction. Catch the exception and deal with it. If the exception is relevant to the operation (i.e. makes it fail), throw a new exception stating just that. Include the catched exception for debugging. Or deal with the consequences and provide a result without PDO, don't throw it. – Sven Aug 24 '14 at 10:57
  • 1
    You're essentially saying that you may want to convert one type of exception to another. Sure, this can be useful for more fine grained error containment and is a useful technique. It still means that *some* exception bubbles as high up as necessary and isn't immediately stopped right where it occurs, as shown in the OPs example. – deceze Aug 24 '14 at 10:59
  • 1
    Yes. Either throw a new exception appropriate to the software layer you are in, or catch it in case the exception is accepted as one intentional outcome that simply triggers a different code path now. Try to not let exceptions from internal layers pass to the outside. – Sven Aug 24 '14 at 11:41
0

An exception should only be caught if you plan to do something with the exception, such as logging the exception in the first example. If you plan to take corrective action based on the exception, you should not re-throw the exception.

Scott Cramer
  • 304
  • 2
  • 3