tags:

views:

106

answers:

4

In the process of creating a module I am facing a dilemma: should each class internally define its own error codes, or should there be a module-wide error codes defined?

So far pros and cons go hand-in-hand, but I am inclined to define per-class errors:

1:

class MyClass
{
public:       
   typedef enum _TResult {
       EOk = 0,
       EErrNoMemory,
       EErrBadParam,
       <...>
   } TResult;

   TResult DoSomething();
};

As opposed to something like:

2-1:

#define OK              (0)
#define ERR_NO_MEMORY   (1)
#define ERR_BAD_PARAM   (2)

Or:

2-2:

typedef enum _TResult
{
    EOk,
    EErrNoMemory,
    EErrBadParam,
    <...>
    EErrTimeOut,
    EErrFeedThePenguin
} TResult;

From your experience what would be the gotcha's for any of the approaches?

A: 

I think it depends on how you want your users to use the system. If you have error codes that make sense for multiple classes, it makes sense to put them at a "global" level, in some well-organized format (e.g. error codes grouped by concept). If your classes all return their own custom error codes, I would define them more at the class level.

Andy White
A: 

If you are going to need the same error codes from other classes, then define them separately. You need to do a little ahead planning. You may not need them now, but it is possible that you create a class in the future that needs similar or the same error codes.

Otherwise, it is better to have them in the same class. This will help the maintenance of the source and the error codes. It will make reading and understanding the code easier too.

kgiannakakis
+3  A: 

The one thing that I'd comment about with per-class error codes is that you then aren't able to write a single error logger (or at least not easily) due to the fact that the same code will mean different things depending on the class.

That said, you can always use both. Have a global enum with common errors:

enum GlobalErrors {
   EOk = 0,
   EErrOutOfMemory,
   // etc.
   EFreeErrorCodeBase
};

and then in classes you can have:

class Something {
    enum ClassErrors {
       EErrCantInitialize = EFreeErrorCodeBase,
       EErrCorruptedData,
       // etc.
    };
...
};

Which gives you a place for global error codes and ensures your class error codes won't overlap the globals (and this is maintained by the compiler).

workmad3
That's a mighty good idea, thanks! Upvote!
Ignas Limanauskas
A: 

I think meaningfully named status code enumerations that exist external to your classes is a good choice. This way they speak to the context of their status and not the implementation of a class that will undoubtedly change or whose responsibilities may grow to span more than one class.

typedef enum _DatabaseErrorCodes {
   ConnectionFailure = 0,
   Timeout,
   InvalidParameters
} DatabaseErrorCodes;

typedef enum _CommonErrorCodes {
   NullArgument = 0,
   SystemOutOfMemory,
   FeedThePenguin
} CommonErrorCodes;

Classes are too liquid and susceptible to change. Tying error codes to a specific class seems like a coupling without any clear advantage. I think (ideally) the status codes should be able to stand on their own and have meaning.

Nick Swarr