The need for global variables often arises because of flawed implementation design. However, when used for caching purposes global variables can provide performance boosts. This article describes how you can implement a global variable with zero maintenance during upgrade.

Why use this approach?

Using the approach described below, no standard application classes are modified and consequently no conflicts with the subsequent version are introduced. This means stable code with zero upgrade maintenance and fast 3-tier performance.

About the global variable

The global variable is global to the current running session. 

The variable are identified by str owner, anytype key.
Owner is the name of the (sub-) module or application object using the global variable, as for example classStr(MyClass).
Key is the name of the variable (within the owning "scope"). It can be a (remember-to-define) constant like 'lastCustomer'.

Using this paradigm there are no compile time checking of variable existence and type.

We propose that you create an accessor method to the variable. This will give you the needed compile time checking (except from within the accessor method itself). This method can be an instance or static method declared where you use it, or - we recommend only in special situations - in one of the global places. As it is a new method it will always be upgradeable.

How to set the variable

First get the globalCache variable located on the ClassFactory class:

SysGlobalCache globalCache = classFactory.globalCache();

Then call set with three parameters:

globalCache.set(str owner, anytype key, anytype value);

Owner is the name of the (sub-) module or application object.
Key is the name of the variable.
Value is the actually value of your variable.

How to get the variable

First get the globalCache variable, also located on ClassFactory class:

SysGlobalCache globalCache = classFactory.globalCache();

Then call get with three parameters:

value = globalCache.get(str owner, anytype key, anytype returnValue = ‘’);

Owner is the name of the (sub-) module or application object.
Key is the name of the variable.
ReturnValue is the value you want if the global variable has not been set. This is useful for caching purposes. See the example.

Example

From Classes/ImageListAppl

void new() { SysGlobalCache globalCache; if (this.keepInMemory()) { globalCache = classFactory.globalCache(); imageListAppl = globalCache.get(classStr(ImageListAppl), classIdGet(this), null); } if (!imageListAppl) { imagelist = new Imagelist(Imagelist::smallIconWidth(), Imagelist::smallIconHeight()); this.build(); imageListAppl = this; if (this.keepInMemory()) { globalCache.set(classStr(ImageListAppl), classIdGet(this), this); } } }

How to initialize the variable

You might get in a situation, where you want the variable to be initialized during startup. 

The wrong solution would be set the variable in info.startup or application.startup. Since these methods are bound to change in each version, you will have to maintain your code.

A slightly better solution is to set the variable in info.startupPost or application.startupPost. These methods will not be changed from version to version. But still you put a load on the client, server and COM-Client during each startup. The best solution would be not to initialize your variable until you need it!

An elegant solution, if access your variable numerous places, is to create a construct method:

static myObject construct() { SysGlobalCache globalCache = classFactory.globalCache(); MyObject myObject = globalCache.get(classStr(myObject), 0, null); if (!myObject) { myObject = new myObject(); globalCache.set(classStr(myObject), 0, myObject); } return myObject; }

Three-tier considerations

Due to the dual nature of ClassFactory, the global variable exists either on the client or the server. The implication is that what you insert on the client side will not be retrievable from the server side. This means potentially less network traffic as it is possible to have the global variable on both sides. You just have to set it twice.

If you want to share your global variable across the network and will accept the performance penalty of a client/server call, use the infolog or appl classes instead of ClassFactory. They reside respectively on the client and on the server.