Level Extreme platform
Subscription
Corporate profile
Products & Services
Support
Legal
Français
To iif or not to iif = .t.
Message
From
09/06/2001 08:26:19
James Beerbower
James Beerbower Enterprises
Hochheim Am Main, Germany
 
 
To
08/06/2001 12:10:24
Dragan Nedeljkovich (Online)
Now officially retired
Zrenjanin, Serbia
General information
Forum:
Visual FoxPro
Category:
Coding, syntax & commands
Miscellaneous
Thread ID:
00513276
Message ID:
00517365
Views:
17
The class of booby traps that I think we're talking about are those that trap "system errors that the sytem didn't catch". They are syntax errors that violate our own language rules rather than FoxPro rules.

The most notable examples of these are improper use of interfaces and failures of data integrity.

a) improper use of the interface: e.g.
if vartype(tcAction)<>"C"  
  && checks both whether a parameter was passed and has the correct type.
  then burn & crash
endif
if ! tcAction $"ADC" && Add Change Delete
	...then crash and burn
endif
In some other languages, like Java, the type of parameters is checked by the compiler; code like if vartype(...) simply compensates for a disadvantage of a weakly typed language. Cache's script -- which is weakly typed like FoxPro-- allows you to specify whether a parameter is optional or required.

The requirement that tcAction be one of ACD could be handled in another language by creating a new variable type that only has values of A or D or C. FoxPro code that relies on rules like "an Add is identified by 'A'" have to check for validity. If they did not the calling program might pass a "N" (for new :-() and a delete might be the result.

b) database integrity violations and database access problems
Here are some examples:

i) we are checking the customer's discount and the customer key in the order is not in the customer table.

ii) we have a procedure that takes three cursors and adds them to the base tables, but one of the tables is missing. This may also be an example of improper use of an interface.

iii) A function takes a foreign key as a parameter but the foreign key cannot be located. This could eithre be an incorrect use of an interface (they passed the wrong key) or it could come from bad data.

iv) Errors from SQL pass through. Again the function doing the SQL pass through knows that there is a problem. In a WAN environment this might not be regarded as an error but a normal situation. However on LANs this is almost certainly caused by improper SQL syntax being passed to the backend.

One of the great things about VFP was that we could forget a lot about these sorts of problems because the data integrity is managed by database rather than the procedural code. However if you are working in a situation where the database is not owned by you (i.e. ODBC/SQL Server/Cache etc) then you may still want to program defensively for these situations.

So what can we do about system errors the system didn't catch?
Here's what I came up with off the top of my head:
1) Let the software crash. If we don't check than it will probably die anyway.
2) Load the functionality onto whatever means we use to communicate between programs and objects
3) Call the global error handler directly
4) Handle the error ourselves
5) Call the object error handler with this.error()
6) Force an error with the ERROR() command.
7) Set booby trap by returning .f. or 0


1) Let the software crash. The problem with this approach is that the software could function but incorrectly. One might do it a little better and "make sure if crashes" by arranging your code cleverly. Someone might, alas, come around later and change the code without noticing your subtle efforts. The advantage is that one does have to think about it or test it. That's a real advantage for what may be a marginal problem in a non-critical piece of software! The wrong reason for embracing this approach would be: "It's someone elses fault anyhow."

2) Overload the messenger. The idea with this is that you may already have some sort of messenger to pass information between levels of the program. A messenger might look something like this (from our 2.6 system, our VFP one is much cooler):
"3: Are you sure that the price is correct? 
Normally Repairables cost more than 5,000 dollars."
Smarten up this messenger to accept error conditions and then have the calling program check for an error condition. This works great as long as you check. The problem is that it confuses two fundamentally different pieces of information: information that will be used by the interface and a system exception.

3) Call the global error handler directly
I used this method extensively in 2.6. The global error handler knows what to do in these circumstances-- let it do its work! The problem is that my code must know how the global error handler is supposed to work. This is not only theoretically bad because it increases code dependence, but practically bad because these day's I've been working with objects that run under both VMP and Westwind Connect: each has it's own error handler. What I have done is abstract the call and check at run time which environment the code is being run under. The approach works but I'm not satisfied: one of the keys of good error handling is simplicity=robustness.

4) Handle the error ourselves
That's just silly but I've seen it done: a messagebox is called in the program with the error and false is returned. I think this is only marginally better than setting a booby trap.

5) Call the object error handler with this.error()
This may work if you have a completely developed error hierarachy that goes up both the class and object hierarchy. I haven't tried it.

6) Force an error with the ERROR() command.
I haven't tried this but it doesn't seem like a bad idea. There are a couple error codes that are set up for use by the developer one could use those. What you would loose would be the ability to communicate more information to the error, but I don't see that as a problem since one sees the code that triggered the error.

7) Set Booby Trap: Trap Error, Return .f.
To repeat (in case anyone is reading this who missed the earlier discussion) code that only exits when it encounters one of these conditions is just evil. If user is lucky it will crash in the calling program. Locating the error may be difficult because of the distance between the true problem and the actual error. If the user has bad luck that day the program will function crashfree, leading to a real world errors.

Of course the person who set the boobytrap may not be burned. It takes two to tango!
James Beerbower
James Beerbower Enterprises
Frankfurt, Deutschland
Previous
Reply
Map
View

Click here to load this message in the networking platform