web developer & system programmer

coder . cl

ramblings and rants on software development...


Print Article R -a +A

exceptions on the run

by Daniel Molina Wegener on 2008.12.14
posted in: programming

The language implementation limit the right behavior of exception handling code. There are a lot of well known anti patterns and best practices around exception handling techniques. Navigating through practices we can found common patterns to apply in our software, and depending on the programming instance these patterns have a few deterministic usage.

exception design

Exception logging is a useful tool for debugging purposes and critical error condition handling. It’s clear after articles such as Exception-Handling Antipatterns from Tim McCune that we must restrict the exception logging to certain conditions in our software. Java offers some tools to make our logging a feasible task around logging facilities and class constructors.

public class Exception implements Throwable {
    public Exception(String msg, Throwable cause) {
        // implementation...
    }
}

IMO, this is the best constructor that fits the delayed exception logging. You can add the source exception, and throw your own with the right message to upper layers, where is used the logging facility. In other languages, like dynamic languages, where isn’t possible to create overloaded methods, you must design your own exception that fits this constructor.

class ExceptionNest extends Exception {

    protected $message;
    protected $cause = false;

    public function __construct($msg, $cause) {
        parent::__construct($msg);
        $this->message = $msg;
        $this->cause = $cause;
    }

    public function getCause() {
        return $this->cause;
    }

    public function getFullStackTrace() {
        $stk = array();
        $cause = $this->cause;
        if (is_a($this->cause, "ExceptionNest")) {
            $level = 0;
            do {
                $stk[] = array($level, $cause->getMessage(),
                                $cause->getStackTrace());
                $level++;
            } while (is_a($cause, "ExceptionNest")
                        && $cause = $cause->getCause());
        }
        $stk[] = array($level, $cause->getMessage(),
                        $cause->getStackTrace());
        return $stk;
    }
}

In PHP5, we should use a similar class to create a nested exception behavior for our code. And then we can the exception logging as we should do in regard with the known anti patterns and exception logging techniques, implementing the right __toString() method in this class.

Python has a similar behavior. We should implement our class as follows.

class ExceptionNest(Exception):

    message = None

    def __init__(self, cause, message):
        self.message = message
        self.value = cause

    def getCause(self):
        return self.value

    def getFullStackTrace(self):
        stk = []

        level = 0
        cause = self.value
        if isinstance(self.value, ExceptionNest):
            while True:
                stk_item = [level, cause.message, str(cause.value)]
                stk.append(stk_item)
                if isinstance(cause.value, ExceptionNest):
                    cause = cause.value
                else:
                    break
        stk_item = [level, cause.message, str(cause.value)]
        stk.append(stk_item)
        return stk

The traceback should be handled directly from the parent exception, and also, on how are implemented nested exceptions is the way that the logging interface should handle the complete backtrace of the given exception. In any case, you must not double logging the nested exceptions, but you can think some particular cases, such as EJB, CORBA or RMI implemented classes, where you really need to implement a double logging with consistent messages.

In dynamic languages, we require the proper __str__() or __toString(), whatever you like to call it, to get the right representation on the logging interface side.

cut off on flow control

Exceptions are a good tool on stopping the execution of some task, if we really need to terminate it. In some languages is difficult to handle exception as flow control stopping method, specially if the language doesn’t implement a garbage collector, such as C++.

ProcessingObject obj1 = new ProcessingObject();

while (!globalProcessingSpinLock->isLocked()) {
    if (obj1->isRaceConditionDetected()) {
        /* we should be specially carefull
        with object deletion... */
        delete obj1;
        throw new MyApplication::ExceptionNest("my message", NULL);
    }
    obj1->continueProcessing();
}

As we see, we can’t be careless with our memory allocations, and some other conditions in complex environments. Language complexity don’t come with the language semantics itself, instead comes with the language design and implemented facilities. Parallel and distributed environment should have complex behavior on these kind of tasks, managing threads, resources and similar objects should be a hard tasks, and we can’t use exceptions as flow control facility if we can’t take a global overview of what we are trying to stop. Flow control by exception usage is hard in languages without a garbage collector.

On the other side, languages with a garbage collector can throw exception on any time, without care on the memory leaks and similar problems, but not with certain allocated resources, such as file descriptors, network connections or shared memory blocks.

Connection myConn = ConnectionFactory.getConnection();

while (ThreadImplementation.isRunning()) {
    myConn.processMessage(this.getResponseMessage());
    if (ThreadImplementation.getCurrent().hasRaceCondition()) {
        // the connection needs to be closed...
        myConn.close();
        throw new Exception("Race condition");
    }
    // some tasks...
}

handling exceptions

Software designers should think on the software destination, if I’m trying to create a friendly software if I’m working on layers different from the user interface, I must think that the software that I’m developing should handle the exceptions in the proper way, or throw the exception to upper layers, but masked or nested inside a custom exception.

Which exception must I log and which exceptions must I throw, IMO, isn’t a personal criteria, it must go shoulder to shoulder with the software design. In example, if we are creating a network client, we should notify the user if the connection fails. If the software is well organized in the proper layers, the design must be considering to throw a custom exception, but with the original exception nested in it, notifying upper layers of the real cause.

Regarding patterns and anti patterns, good practices and whatever, we can reach the logging point. In the example above, we must do the exception logging where is finally handled the upper exception.

There is a really good article about exception handling on Java: Best Practices for Exception Handling. If you take a smart look on that, you can find that most recommendations can be implemented on other languages.


No coments yet.

post a comment

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>