On 03/29/2011 12:40 PM, Mike Linford wrote:
Hello,

So I'm writing a function for a library. It takes a struct as an
argument. The struct's fields can't just be any old values, though. The
function won't work if some of the fields are weird. It could return an
erroneous value, or even crash.

The thing is, though, that I can't tell whether the best approach is to
use an in-contract or throw an exception if it doesn't pass my test. What
would you guys recommend?




I was given two words of advice on exceptions:
"Use exceptions for the exceptional"
"Use exceptions only for the exceptional"

Meaning, if you expect something to fail frequently, using a try/catch is much more expensive than an if/else. "The exceptional" is something that should rarely ever occur, like running out of memory.

For contracts, they are usually meant as a developer tool to warn them when that they will be in no-man's land if they attempt to proceed any further. They are, therefore, not compiled in when you pass the D compiler the -release flag.

I don't think that contracts and exceptions are mutually exclusive. They provide two different safeguards. One is a tool to aid in the development process, one is a tool to safeguard against exceptional run-time scenarios.

However, I think if I rephrase your question a little bit, it might provide you what I think you're after. I'm making an assumption here, so I may be way off the mark.

"Who's responsibility is it to check whether or not the data passed into the function is valid? Should I accept whatever the user wants to pass in, and let them know when it's invalid, or should I trust that the user is sending in good data?"

I think that's a choice for you to make. Contract programming is often used to put the burden of validation on the user of the library (meaning programmer writing software taht uses your library). Exceptions could be used to indicate that the library writer is accepting responsibility for validating the data before using it.

But validating data is not the only reason to use exceptions, and it's not unusual for a library to skip all validations and force the user to do all the checking before hand. Arrays are a good example. When not in -release mode, array boundaries are checked upon every access to the array, and an exception is thrown if access goes out of bounds. In -release mode, if you go out of bounds you get a segfault. This is one example of giving the user (programmer) of arrays the responsibility to check boundaries so that the library can focus on being fast.

I think the choice comes down to a balance between performance, responsibility, and maintainability. (Oh, and you'll usually get it wrong the first time, so don't be sad.)

Reply via email to