One style of programming we generally try to avoid is placing executable code statements (*) in a “$insert” record (i.e. an STPROCINS entity) and using that in another program because it usually suffers from the following problems:
- Inserted code cannot be traced properly with the debugger, making it hard to step through a procedure and possibly obscuring variable initialization and manipulation.
- Changes to the inserted code will force all the hosting stored procedures to need recompilation.
- The BLint() process that the compiler uses to check for suspected unassigned variables will not follow the $insert statement and process the insert record, making compile time errors more difficult to detect.
However, whilst working on the new Form Designer we found there was quite a bit of common code that was shared between the various modules used by the form parser and compiler, and we obviously didn’t want to duplicate this in each one. Normally we would just move the code into a separate stored procedure and call that from each module, but that just adds extra overhead in a process that we really wanted to keep as fast as possible, and so we looked at another option: moving it into an insert record instead. Sharing the code this way means that it runs “inline”, thereby removing the need to create another call-frame, move variables on and off the stack, and so on.
The shared code involved was fairly straightforward, well-tested, and limited to a few small subroutines, so the only real issue to overcome was: how can we easily update any “host” stored procedures in the event of the insert record being changed?
Well, one of the nice things about the OpenInsight repository is that it tracks the various relationships between entities in an application, and some types support a method called TCOMPILE (Tree-Compile) that allows an entity to compile any other entities they are using during the compilation process as well. However, in this case we needed to do the opposite and compile those entities that were using the insert record instead, and so we created a TCOMPILE method for the STPROCINS type that processes this list of “used-by” entities and executes their normal COMPILE method after the insert record has been saved. This results in a simple way to ensure that changes are implemented across any affected programs.
Whilst we wouldn’t say we exactly endorse embedding programs in this way, it does remain a useful technique for sharing code in some limited cases, and with the new TCOMPILE method it is now much easier to manage too.
(* e.g. code statements such as “x = y + z; call msg( @window, txt );” etc, as opposed to simple constant declarations like equate statements).
(Disclaimer: This article is based on preliminary information and may be subject to change in the final release version of OpenInsight 10).