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