GDL Error Handling 1 – When Good Scripts turn Bad

2 May 2013 Andrew Watson No Comments
ArchiCAD, Tip of the Day

Apart from logical and syntax errors in the script, bugs can also arise from unexpected values. Such values can cause otherwise good scripts to turn bad.

All GDL objects rely on the end-user entering ‘sensible’ data, as defined by the programmer. For instance, if I create a library part to model a simple, rectangular bookshelf with evenly-spaced shelves, I might include parameters to define:

  • total height
  • total length
  • total depth (front to back)
  • shelf thickness
  • shelf vertical spacing

Someone using the completed product might enter values such as:

  • total height  = 1000 meters
  • shelf vertical spacing = 1 millimeter

Now the object has to place approximately 1,000,000 shelves into the bookshelf. ArchiCAD will grind to a halt and die.

Clearly these are silly values, and could be avoided by limiting the range of allowed input values. So there’s no great difficulty in avoiding this particular ‘bug’. But the example shows how even in the most simple case, a bug can naturally emerge.

Given that a simple library part such as our bookshelf can give rise to bugs so easily (actually there are many other ways the object could give an unexpected result), imagine an object that includes hundreds of parameters and dozens of ways to control them (think buttons, values lists, numeric input, dynamic hotspots). Such an object must include correspondingly large chunks of code devoted to dealing with possible unexpected user input.

But things get worse.

Let’s re-design our bookshelf. Instead of setting the shelf vertical spacing, we’ll set the number of shelves. The shelf spacing can then be calculated using a line of GDL script such as this:

shelfSpacing = totalHeight/shelfNumber

Now that will work fine if a shelfNumber is set to 1, 2, 3, … , 100. But if shelfNumber is set to 0, the fraction totalHeight/shelfNumber becomes undefined and an error message pops up to frighten the user.

As before, this error can be avoided by restricting the allowed input values. In practice however, division is often carried out on calculated (i.e. not user-entered) values, and it is not always obvious that the divisor may be zero. So each time a division is carried out, it is a good idea to check this first. For example the following code could be used:

shelfNumber = max(1, shelfNumber)

shelfSpacing = totalHeight/shelfNumber

This ensures that the divisor is never zero.

Typically a fully fledged parametric object includes hundreds or even thousands of lines of script. To ensure perfect error-handling in every one of those lines is virtually impossible, or at least time-consuming (and bear in mind that the error-handling itself might include errors). Often it is more rewarding for the programmer to focus his or her attention on making the object do smart stuff, be easy to use, look good in 3D and plan view, etc.

In many cases, the worst that can happen is that a pesky error message might pop up, or an object’s 3D model might turn inside-out. The end-user will probably tolerate this sort of behaviour, provided the solution is obvious. On the other hand, a bug that causes ArchiCAD to crash or freeze may cause the end-user to experience feelings of mild irritation, anger, or blind rage, and could lead to physical harm to the programmer responsible.

So be smart. Bugs may be generated spontaneously but this can be prevented. Avoid them generally wherever possible, and take the greatest care to avoid the nastiest bugs. More on this later …