How Superbase NG Differs
When SIMPOL was designed, one of the strongest factors in the design of the language was to make the code easy to learn, easy to use, and easy to maintain later. An unfortunately common scenario that has played out far too often in many places using tools like legacy Superbase, is where an island solution built by an inspired layman programmer achieves a degree of success. Then as its star rises, it requires additional professional assistance to make it to the next level of usability. At that point, the professionals investigate the software and discover that it is written in a way that is non-standard, complicated to understand, and possibly built using a tool that they personally have no experience using. At which point they decide to discard the original and start over again. The problem is the original solution probably took one dedicated person 1-3 years of work to build using a very powerful tool. The new version usually is estimated to require 3-5 people several years to produce, and would cost a fortune to achieve it. At which point the whole project might be scrapped as too expensive.
To prevent the solutions that were built by non-expert programmers from being discarded as unmaintainable or unsupportable once they reached this level, every effort was made to avoid this result. All the factors that were bars to entry for quickly learning the language were discarded. As much as possible, redundancy was removed from the design. The keyword set was reduced to the bare minimum and everything was turned into a type or a function. There is also no way to jump out of any block statement, so it is always clear how the code flows, and there are no global variables.
Not having global variables is one place where SIMPOL strongly differs from many languages. The choice to not allow them went back to the problems that are commonly associated with them:
Random unexplained changes in one module as a result of calling code in some other module
Assignment to apparent local variables changing the value of global variables
The constant search for a new and valid name for a global variable
The inability to distinguish in the code between a local variable and a global one
So what was the gain for SIMPOL by not having them, and how does it cope with certain situations that appear to require them? By not having global variables, all variable changes are specific to the function in which they are created. If a value is need in a function from outside the function, it must be passed into the function as a parameter. It is always clear where the values are coming from.
But what about event handlers? How do we get the data we need into an event handler if we don't call it directly?
That is handled by every event having an additional property called reference. This property
is declared to be of type (*)
, which is a special placeholder that allows a variable to hold a
reference to any data type. This is the mechanism used to pass quasi-global data to an event handling function. With
that, the loop is closed and there is no other need for global variables.
Every SIMPOL program starts in the function main()
and ends when that function is exited
(unless the program is multi-threaded and one or more threads are still executing at that time).
That all sounds like loads of work, if there is a lot of legacy Superbase code to change. The reality is a little different. As it turns out, much of what people code is about working around how their environment works. Legacy Superbase is no different. The easy route is to move the data and the forms, migrate the menus, and then see what works and what is missing. Then add the code as event handlers for the various event types.
One important difference to note is that Superbase database files allow the definition of calculations, constants, and validations as part of the field definition. The initial Superbase NG database engine is a pure storage engine, and it does not cater for these field-level operations. This may seem to be a significant drawback, but in fact, most of the more advanced legacy Superbase developers had stopped using these in their projects quite some time ago, since in any complex project these sorts of things could get in the way and cause as much trouble as they provided help.
To resolve this in SIMPOL, it is necessary to migrate those settings into a function or set of functions. In an earlier chapter, Chapter 6, GUI-Style Database Programs, a special function was built to create the serial number when a new record is created in a table on a form. A similar function would be needed for each time a record is created in any table that needs constants to be generated at that time. A similar function would be needed for calculations, which could be called every time a record is saved (it could also be called during the onlostfocus event of certain controls).