against enforce

Jonathan M Davis jmdavisProg at gmx.com
Fri Mar 25 12:21:26 PDT 2011


> >So, there really is no good answer.
> >- Jonathan M Davis
> 
> So why do you need to differentiate between assert and enforce if you can't
> choose, which of them should be used?
> 
> We can't really turn off both of them, and if we really want performance
> and no checks, we would want to turn off both of them, so they should work
> in the same way, shouldn't they?

assert and enforce serve _very_ different purposes. assert is for checking the 
logic of your code. It can go away, so you can't rely on it. It's simply for 
additional checks in your code to ensure that it's of high quality. You can't 
rely on it. It's also _not_ for error handling. When an assertion fails, there 
is a bug in your program.

Exceptions - and therefore enforce - are for error handling. They are supposed 
to _always_ be there. Performance has nothing to do with them (other than the 
fact that they can obviously harm performance, which may cause you to refactor 
your code so that they're not necessary). Typically, exceptions - and 
therefore enforce - are used when validating input. That input is often 
completely dependent on the particular run of the program, and bad input isn't 
necessarily a bug in the program at all. When enforce fails, that does _not_ 
necessarily indicate a bug in your program, and it should _not_ be used for 
finding bugs.

Input from the user is obviously always input, and you're going to have to 
check that and throw an exception on failure rather than use assertions. Input 
to a function which is completely local to your code is not in any API 
anywhere and whose input is completely controlled by your code should use 
assertions. At that point, if the function gets bad input, it's a bug in your 
code. Also, out blocks, invariants, and checks in the middle of functions 
typically have _nothing_ to do with input and should be assertions. If they 
fail it's a logic bug.

The problem is when a function could be both used internally and used on user 
input. For instance, iota is typically given hard-coded values - iota(5, 100, 
2) - but you could pass it value which was given to main - iota(5, 100, 
to!int(args[1]). With hard-coded values, assert is the correct solution. But 
with user input, enforce would be. So, which do you do? assert or enforce?

In the case of iota, since it is almost always used with hard-coded values and 
even when it isn't, it's likely used with computed values rather than user 
input, so if it's wrong, it's a bug in the code rather than bad user input. 
The application can check (with enforce or with an if and throwing an 
exception or whatever) that the input is good before passing it to iota if 
that's what it's doing.

With other functions though, it's less clear. And with every such function, a 
choice must be made. Should it treat its input as user input or as values 
local to the program? If it's user input, then it needs to use exceptions. If 
it's local to the program (at which point a bad value would be a bug in the 
program), then assert should be used. And when you're dealing with a library, 
it's not as clear what the best solution should be in. The fact that 
assertions are almost certainly going to be compiled out might make it so that 
you want to treat input to the library's API as user input rather than local 
to the program when you would choose to have those same functions be treated 
as local to the program if they weren't in another library (though of course, 
there are plenty of cases where API functions should just plain be treating 
input as user input regardless).

So, there is a clear and distinct difference between the intended uses of 
assert and exceptions (and therefore enforce). They have very different roles. 
The question then is not what their roles are but what you need a particular 
function to do - e.g. treat it's input as user input or treat it as local to 
the program (and therefore a bug if it's wrong).

- Jonathan M Davis


More information about the Digitalmars-d mailing list