6 |
The LA Fox Developer Newsletter
|
May 1995
|
Candy Machine
(Con't from page 5)
usually with a corrupted database!
I don’t know if Steve was able to get the candy machines changed. But he did change Microsoft’s coding standards in a simple, easy to use way, and he eliminated that kind of bug from ever occuring again. He changed a coding style that
encouraged
bugs, to a style that
prevented
bugs.
The root cause of this kind of problem, according to Steve, is having a function mix return values and error codes. If a function usually returns character data, but will occasionally return numeric or logical error codes, it will be bug-prone. Forever.
The fix is just as simple as the problem. The error code is one output from the function, and the return value is another. The solution is to re-write your function to return the error code separately from the return value.
Think about it for a second. We’ve all been conditioned to think that functions only have one return value. Functions written in the “normal” way only have one return value, that is, they can change only one value in the calling routine.
A function that uses a variable passed by reference can change the
referenced
variable
in the calling routine,
as well as the normal return value of the function itself. A function that uses variables passed by reference can change more than one value in the calling routine. Its as though you could say RETURN(a,b) and get multiple return values from one function.
To use Steve’s technique in FoxPro, pass a variable to hold the value you want to your function by
reference
and use the return value for error codes (usually T/F).
To pass a variable by reference, use
@
like this:
It sounds complicated, but its not. Here is an example:
|
If we were to write getcsystem the normal way, just using one return value, how would we indicate that something was not in the database? We could return an empty or blank string, but that is a valid condition in this particular system. We could return a logical .F. or a valid string, but then the caller must examine the variable type of the return code, a real bother to code. We could write 2 functions, one to check if the value exists, and another to return the value, again a pretty clumsy solution.
Should you design every function using a variable passed by reference? No, many functions have no error returns possible, and it would not be worth the time and
extra
code to first initialize a variable and then pass it by reference. But, for functions that
can
have an error return, it is worth the time and bother to do it in a bug-reducing way.
Steve suggested that you design functions that “lead
programmers to write correct code
the first time.
Don’t use confusing dual-purpose return values
-
each output should represent exactly one
data
type.”
|
Page 6
|
6 |