views:

553

answers:

7

I am developing a wrapper for a third party function library that is interfacing with some special hardware. So basically, I want to encapsulate the dll functions (bool Connect(), void Disconnect() etc) in a MyHardwareObject with connect- and disconnect methods.

The Connect function from the dll can throw some specific exceptions, for example when the hardware is not present. For the application, the information on why the connect method failed is considered unimportant, so the additional information contained in the exception is not needed.

What is the best way of handling those exceptions, returning false, or leaving the exception unhandled here and catch it on the level that would otherwise handle the fact that the connect method returnded false?

 bool MyHardwareObject.Connect()
{
    try
    {
        ThirdPartyLibrary.Connect();
    }
    catch (SomeException)
    {
        return false;
    }
    return true;
}

As opposed to

 bool MyHardwareObject.Connect() 
{
    ThirdPartyLibrary.Connect();
    return true;
}

(or in the second case better void MyHardwareObject.Connect(), since we either return true, or throw an exception?)

Or what else would you do? And most important: Why?

+5  A: 
MadKeithV
+2  A: 

It's really difficult to choose wisely between exceptions and return codes. It depends on a lot of things, and how errors are handled in the rest of your codebase would be the most important one - stay consistent.

Lately, I'm leaning more towards the "don't throw an exception if it's not worth it". Our exceptions do a lot of work: they log stuff, they create stack traces, etc. If I just want to convert a string to an integer, throwing an exception if the input string has the wrong format is probably not worth it. On the other hand, I have objects that I simply don't want in my system if they can't be constructed from proper data, and in that case their constructors throw exceptions.

If the rest of the codebase does not give you any hint on how to do it, I like this rule of thumb: imagine that throwing an exception makes your computer emit a loud beep. As long as you can put up with it, throwing is fine.

Carl Seleborg
+1  A: 

I would pass on the exceptions. If you don't you are masking potentially important information that could be useful later. I know that you aren't using it now, but what if you decide in the future to handle recovery differently based on the type of error. At that point you will have to undo all the code that you've written to mask out the exception. While I disagree with @MadKeithV on making it true/false, I think he has a point on wrapping the exception in your own exception that has, possibly, better semantics for your applicaiton.

tvanfosson
Well I wasn't suggesting masking important information - but seriously considering which information is important to pass on, and which information should be safely handled by Connect either failing or succeeding, instead of blindly passing on all exceptions. So I think we mostly agree.
MadKeithV
A: 

I believe the principle behind the exception mechanism is the "fail fast" theory.

Do you want your client's application to "fail fast" is the connection is unsuccessful ?
If yes, just throw back the exception or encapsulate the exception in an applicative exception of your own.

If the client ignore that exception, his application will stop.

Return false means the client might ignore the problem, his application might still crash, but "later"...

VonC
A: 

Is this third-party library required for your program to run, or does it just add a little extra functionality, which, while nice, is not required? Also, is it likely that the hardware will fail. Finally, how many types of exceptions can the hardware throw at you?

If the library is not actually needed for your program to run, you certainly need to catch the exception at some point, but you may want to do it higher up.

If the hardware can throw multiple types of exceptions, it is more likely that you would want to rethrow the exception since simply returning a value will cause you to lose some of the information. However, you did say that the client doesn't care why it failed, just that it did, so this shouldn't be an issue.

Finally, if the hardware failure is commonplace, you might be more likely to want to return an error code (or false in this case) than if failure is commonplace.

I think in your case it really comes down to the first question. If you don't really need this library, return false and make sure that it is very clearly documented that the operation may fail for completely arbitrary reasons and that they need to check the return value. If you need it to work, rethrow the exception and let it propogate to wherever you can gracefully exit.

James
It is required - interfacing with this hardware is the main task of the application. Do I understand you correctly: You would not use a return value, because someone could use by just calling `MyObject.Connect()`, without checking the return value, as in `if (!MyObject.Connect())...`?
Treb
+1  A: 

I would suggest the second one. It will be the caller responsibility to handle the exception and take the right action according to the exception. Suppose Connect throws AccountExpiredException, NetworkUnavailableException, InvalidCredentialsException, etc (these are just examples) I can prompt the user to "fix" the exception (Contact the Administrator, Check you network cable, Check Username/Password). I would even suggest to remove the return value(indicator) and just make it void. Take a look at SqlConnection Open method - it's like you Connect - it doesn't return a value instead it throws an exception. To swallow the exception like this

 bool MyHardwareObject.Connect()
{
    try
    {
        ThirdPartyLibrary.Connect();
    }
    catch (SomeException)
    {
        return false;
    }
    return true;
}

isn't a good idea IMHO. I would recommend you to implement IDisposable pattern. Just my 2 cents.

Petar Petrov
+2  A: 

Read this: http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

In short:

Does the caller have any use for the return value? Can it recover or is an error the end of the world? If it's just a minor issue, use a return code. If the various states happen equally often (50% of the time it fails, 50% it works), use a return code because the caller must handle the situation anyway and an exception doesn't help.

Do you want to pass up additional information (like the setup of the third party thingy so someone has a chance to debug what happened later)? Use an exception.

Aaron Digulla