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