Checking function parameters in Phobos

Jonathan M Davis jmdavisProg at gmx.com
Wed Nov 20 02:45:56 PST 2013


On Wednesday, November 20, 2013 08:51:16 Joseph Rushton Wakeling wrote:
> On 20/11/13 01:01, Andrei Alexandrescu wrote:
> > There's been recent discussion herein about what parameter validation
> > method would be best for Phobos to adhere to.
> > 
> > Currently we are using a mix of approaches:
> > 
> > 1. Some functions enforce()
> > 
> > 2. Some functions just assert()
> > 
> > 3. Some (fewer I think) functions assert(0)
> > 
> > 4. Some functions don't do explicit checking, relying instead on
> > lower-level enforcement such as null dereference and bounds checking to
> > ensure safety.
> > 
> > Each method has its place. The question is what guidelines we put forward
> > for Phobos code to follow; we're a bit loose about that right now.
> 
> Regarding enforce() vs. assert(), a good rule that I remember having
> suggested to me was that enforce() should be used for actual runtime
> checking (e.g. checking that the input to a public API function has correct
> properties), assert() should be used to test logical failures (i.e.
> checking that cases which should never arise, really don't arise).
> 
> I've always followed that as a rule of thumb ever since.

When an assertion fails, it's a bug in your code. Assertions should _never_ be 
used for validating user input. So, if your function is asserting on the state 
of its input, then it is requiring that the caller give input which follows 
that contract, and it's a bug in the caller when they violate that contract by 
passing in bad input.

When your function uses enforce to validate its input, it is _not_ considered 
a bug when bad input is given. It _could_ be a bug in the caller, but they are 
not required to give valid input. When they give invalid input, they then get 
to react to the exception that was thrown and handle the error appropriately. 
Then this works when the input came from outside the program (e.g. a user or a 
file) as well as when it doesn't make sense for the caller to have validated 
the input before calling the function (e.g. because the validator function and 
the function doing the work end up having to almost the same work, making it 
cheaper to just have the function validate its input and not have a separate 
validator function). It also makes it so that the function will _never_ have 
to operate on invalid input as invalid input will always be checked and 
rejected, which then makes it much harder to use the function incorrectly.

But ultimately, whether you use assertions or exceptions comes down to whether 
it's considered to always be a bug in the caller if the input is bad. DbC uses 
assertions and considers it a bug in the caller (since they violated their 
part of the contract), whereas defensive programming has the function protect 
itself and always check and throw on invalid input rather than assuming that 
the caller is going to provide valid input.

- Jonathan M Davis


More information about the Digitalmars-d mailing list