Error Codes, again...
One of the tech writers in my group just asked a question about documenting error codes.
I've written about my feelings regarding documenting error codes in the past, but I've never actually written about what it means to define error codes for your component.
The critical aspect of error codes is recognition of the fact that error codes are all about diagnosibility. They're about providing enough information to someone to figure out the cause of a problem. This is true whether you use error codes or exceptions, btw - they're all mechanisms for diagnosing failures.
Error codes serve two related purposes. You need to be able to provide information to the developer of an application that allows that developer to diagnose the cause of a failure (or to let the developer of an application determine the appropriate corrective action to take in the event of a failure). And you need to be able to provide information to the user of the application that hosts your control to allow them to diagnose the cause of a failure.
The second reason above is why there are APIs like FormatMessage which allow you to determine a string version of system errors. Or waveOutGetErrorText, which does the same thing for the multimedia APIs (there's a similar mixerGetErrorText, etc). These APIs allow you to get a human readable error string for any system error.
One of the basic requirements for any interface is that you define the errors that will be returned by that interface. It's a fundamental part of the contract (and every interface defines a contract).
Now your definition of errors can be simple ("Returns an HRESULT which defines the failure") or it can be complex ("When the frobble can't be found, it returns E_FROBLE_NOT_FOUND"). But you need to define your error codes.
When you define your error codes, you essentially have three choices:
- You can choose to simply let the lower level error code bubble up to your caller.
- You can choose to define new error codes for your component.
- You can completely define the error codes that your component returns.
There are pros and cons to each of these choices.
The problem with the first choice is that often times the low level error code is meaningless. Or worse, it may be incorrect. A great example of this occurs if you mess up the AEDebug registry key for an application. The loader will attempt to access this registry key, and if there is an error (like an entry not found), it will bubble the failure up to the caller. Which can result in your getting an ERROR_FILE_NOT_FOUND error when you try to launch your application, even though the application is there - the problem is that the AEDebug registry key pointed to a debugger that wasn't found. But bubbling the failure up has killed diagnosibility - the actual problem had to do with the parsing of a registry key, but the caller has no way of knowing that. This is also yet another example of Joel's Law of Leaky Abstractions - the lower level information leaked to the higher level.
The problem with the second choice is actually that that it hides the information from the lower level abstraction. It's just the opposite - sometimes you WANT the abstraction to leak, because there is often useful information that gets lost. For instance, in the component on which I'm working, RPC_X_ENUM_VALUE_OUT_OF_RANGE, RPC_X_BYTE_COUNT_TO_SMALL, and a couple of other RPC errors are mapped to E_INVALIDARG. While E_INVALIDARG is reasonably accurate (these are all errors in argument), RPC returned specific information about the failure that hiding the error masks. So there has been a loss of specificity about the error, which once again hinders diagnosability - it's harder to debug the problem from the error. On the other hand, the errors that are returned are domain specific.
The third choice (locking down the set of error codes returned) is what was done in my linked example. The problem with this is that it locks you into those error codes forever. You will NEVER have an opportunity to change them, even if something changes underneath. So when the time comes to add offline storage to your file system, you can't add a "tape index not found" error to the CreateFile API because it wasn't one of the previously enumerated error codes.
The first is a recipe for confusion, especially when the lower level error codes apply to another domain - what do you do if CreateThread returns ERROR_PATH_NOT_FOUND? The third option is simply an unmitigated nightmare for the long term viability of your system.
My personal choice is #2, even with the error hiding potential. But you need to be very careful to ensure that your choice of error codes is appropriate - you need to ensure that you provide enough diagnostic information for a developer to determine the cause of the failure while retaining enough domain specific information to allow the user to understand the cause of the failure.
Interestingly enough CLR Exceptions handle the leaky abstraction issue neatly by defining the Exception.InnerException property which allows you to retain the original cause of the error. This allows a developer attempting to diagnose a failure to see the ACTUAL cause of the failure, while allowing the component to define a failure that's more germane to its problem domain.
Comments
- Anonymous
May 24, 2005
The comment has been removed - Anonymous
May 24, 2005
This goes blatantly off-topic but without a more proper blog to post to..
I bumped to a very interesting WinHEC powerpoint when googling around. It does not seem to be up at the WinHEC page yet though. And I can see why - it immediately raises some questions to the random viewer:
What is WASAPI and is there a better name for this?
Is the MFT "plugin" architecture the "Media Foundation" or are these separate things? One could presume MFT is abbreviation of Media Foundation.
These new slides still didn't give a good story regarding the Video story. What is the Directshow story, obviously it is going to be there in LH but are there new/easier possibilities coming regarding what is currently achieved by writing say a source filter and what's the place for first hand information.
Needless to say I'd love to see a blog from person who works with this stuff even if it only had posts only once a month. Too much hoped for? - Anonymous
May 24, 2005
The comment has been removed - Anonymous
May 24, 2005
The comment has been removed - Anonymous
May 24, 2005
Joku,
The PPT you're talking about is up there. I know :) The PM who gave it is the PM for my group. I can answer a bit of this...
MFT - Media Foundation Transform - mostly the equivilant of a DMO but with a different input/output logic.
I don't know about video because I don't work on video (although video is owned by my group).
WASAPI - Windows Audio Session API. That's the best name you're going to get for it :)
And I'm trying to get permission to start blogging about this. Certainly I'll be doing that after LH beta1 ships. - Anonymous
May 24, 2005
The comment has been removed - Anonymous
May 24, 2005
- Is [1] the ppt you mention, Joku (or Larry!)? Seems very interesting!
2) Joku: Could you please give the links to those DirectShow blogs? I've done some DS work in the past, and would like to read some "ramblings" about it :)
3) FYI: Java introduced a mechanism to keep lower layer error information in its Throwable class(which Error and Exception inherits from) in v1.4. Unfortunately this isn't the case with J2ME.
[1] http://download.microsoft.com/download/9/8/f/98f3fe47-dfc3-4e74-92a3-088782200fe7/TWEN05003_WinHEC05.ppt
Anonymous
May 24, 2005
Andreas,
1) that's the ppt
2) Better than none, but not exactly very active so far..
http://blogs.msdn.com/mikewasson/default.aspx
http://blogs.msdn.com/ccgibson/archive/2004/5/20.aspx
http://blogs.msdn.com/deanro/archive/2005/01/21/358586.aspx - Well this is like saying Larry's blog was about Video ;)Anonymous
May 24, 2005
The comment has been removedAnonymous
May 24, 2005
Renaud, what about HRESULTs? It's a error code but it contains a lot of information (see WinError.h in PSDK for the details). How to relate the error code to a message is not a hard task, if you own both. It is very neat in .NET, but you can do the same wrapping yourself.Anonymous
May 24, 2005
The comment has been removedAnonymous
May 25, 2005
The comment has been removedAnonymous
May 25, 2005
Is IErrorInfo the solution to this? The happy medium between the rich information of an exception vs the simplicity of a return value?Anonymous
May 25, 2005
The comment has been removedAnonymous
May 31, 2005
One of the comments on my philosopy of error codes post from last week indicated that all the problems...Anonymous
June 07, 2009
PingBack from http://greenteafatburner.info/story.php?id=2987Anonymous
June 08, 2009
PingBack from http://insomniacuresite.info/story.php?id=2135Anonymous
June 08, 2009
PingBack from http://quickdietsite.info/story.php?id=5495