ASSERT lExpression [MESSAGE cMessageText]
If lExpression evaluates to a logical false (.F.), a debugging dialog box is displayed.
The ASSERT command is a form of In Line Error Handling. The expected and normal behavior is for the expression to be true, and the application to continue running. If the expression is not true, the program is halted and you are given the option to open the debugger.
It also documents the code. It helps show how the program should be behaving in all circumstances, including unexpected user actions.
The expression is only evaluated when
set asserts on. When asserts are off, the ASSERT command causes a minimal performance hit (less than the local command).
Neat assert trick
If you would like to to test parameters, for example, and provide default values for them to bulletprooof a routine, and also notify the developer about bad or missing parameters during testing, but continue with the defaults at runtime so the user doesn't get the messages, you can do something like this:
IF VARTYPE(pcWhatever) <> "C"
ASSERT .F. MESSAGE "Parameter 1 passed to Whatever is not 'C'"
pcWhatever = ""
In this case the IF statement will test the condition and if it fails the assert will be executed; if set asserts is ON the message will appear, otherwise it won't. In either case the parameter will be assigned the default value and the code will continue.
Nonetheless, a function should never be called with the wrong parameters. If it is, this is in fact a bug that must be fixed. The reason to provide default values is only to gain stability and secure your application against buggy code. It is called defensive programming, a technique that results in buggier applications, because it hides bugs from the developer. An assertion dialog in the above sample should be treated as a real bug, not something you simply can skip.
What if the function design is to allow optional parameters and to provide default values for them, but you want to know when they haven't been passed during development so you can decide if there is a bug and fix it if needed?
First of all, optional parameters should be treated as an exception. Too often, a default value is just created for the convenience of the developer, not because there's a design reason. Often it's better to create multiple methods or functions that deal with additional parameters. One place, for example, where they make sense is versioning. The next version of a function might offer additional possibilities, and by using optional parameters, the function can behave just like the old one, if these parameters are omitted.
To answer your question: This would entirely defeat the purpose of an assertion. An assertion is used to verify conditions that should always be true. IOW, your code assumes that they are and usually won't work, if they are not (with the exception of defensive programming, of course). If you want to support the user in ambigious case, I think it's better to use debug code here that is not compiled into the released application. This also makes clear that the purpose of this code is to determine such cases and that this is not necessarily something you expect. Consider another developer who's reading your code. The header says, parameter 2 is optional, and a few lines later there's an ASSERT telling him that it must be a string.
I have been working with someone else's code that uses optional parameters meant to benefit a developer. I assure you, that developer is not me. It makes it much harder to figure out what are expected, tolerated or invalid parameters. It is difficult to determine if a function is not correct, or the call is not correct. When things are optional, the documentation starts to get complex, and often out of sync with the true purpose of a function. -- CFK
I like the Neat Assert Trick because it effectively documents the procedure's contract. As for the parameters themselves, the arguments of a method should only include operands, no options. This is the Operand Principle .-- Steven Black
Here are some times that show how little diffenence it makes:
for lnI = 1 to 10,000,000
3.111 Baseline, nothing in loop
6.770 asserts on, Assert .t.
5.748 asserts off, Assert .t.
6.665 Local lx
This was generated by _ Assert Timer
Contributors Carl Karsten Jim Booth Christof Wollenhaupt
Category Exam 70-156 Hot Topic Category Definitions
( Topic last updated: 1999.11.10 10:48:00 AM )