multipart-mixed

Mini-Pattern: Error Function

I have a bunch of "mini-patterns" that I've been collecting, small nuts-n-bolts level patterns I've either created myself or found elsewhere over my past 10 years as a software engineer. I'm going to start posting them here in case others find them useful. So, without further ado, first mini-pattern:

Instead of returning an error code directly, use a function that can provide logging or other necessary functionality in addition to returning the error code.

Problem Description

Many times error codes are highly generic -- e.g. "IO error" in a network driver could mean anything -- so it's often useful to provide more detail in some form of trace. Exceptions can be a great tool for this, of course, because they can contain any amount of data required to fully describe the error condition.

For situations where exceptions are not feasible, e.g. lack of language support or an executive decision not to use them, you can use this pattern to provide some of the same benefits regarding data collection about the error.

Solution

Use a function to return errors. This function will take parameters for the error code to return, plus additional debugging information. The function can then print diagnostic information to the console or a dedicated error log.

This example prints diagnostic information to stderr:

#include <stdarg.h>
#include <stdio.h>
#include <string.h>
typedef unsigned long err_t;

err_t error(err_t code, char* message = 0, ...)
{
    if (message != 0)
    {
        fprintf(stderr, "Error %d: ", code);

        va_list argp;
        va_start(argp, message);
        vfprintf(stderr, message, argp);
        va_end(argp);

        fprintf(stderr, "\n");
    }
    else
    {
        fprintf(stderr, "Error %d\n", code);
    }

    return code;
}

An example of this function in use:

err_t foo()
{
    // ... do some work ...

    if (requiredSpace < availableSpace)
    {
        return error(ENOSPC, "not enough space on disk; "
                             "%d required, %d available",
                             requiredSpace, availableSpace);
    }
}