When I started programming, my focus was on writing code. But I learned that when you need to perform a series of actions, it’s best to drive that using data, which is interpreted by code. The data is easier to understand, and to change. It’s easier to show to business users if that is appropriate. And it’s easier to have code that acts in a robust and resilient manner with that data.

Example One

When I worked in Shield Life, I wrote a program which allowed external users to do terminal emulation onto the Wang VS minicomputer over a dial-up connection. The program had to do a series of actions to connect to the VS:

  • Interact with the modem and dial the appropriate phone number
  • Interact with the X.25 PAD if appropriate (this used by users around the country to avoid having to make long-distance phone calls)
  • Log in to the VS (we did not want to show the login screen to these users – instead we logged them in automatically)

Rather than coding all of this, I used DATA statements in BASIC. Here are some examples:





DATA “SEND”, “ADTP <number>~”


DATA “IF”, “X.25”


This means:

  • Set the number of retries for the subsequent commands. This means that if the response which is required in a WAIT command is not received, that the preceding SEND command will be repeated up to 3 times. The statement also acts as a marker within the script. The second number indicates that the processing should return here up to 3 times if the smaller retry loops don’t get the desired result
  • Send AT followed by a carriage return to make sure that the modem is responding
  • Wait up to 6 seconds for a response of OK
  • Delay for 2 seconds
  • Send the dial command followed by the appropriate phone number and a carriage return to the modem
  • Wait up to 60 second for the modem to respond with a CONNECT message
  • The “IF” statement starts a block of commands which will only be used if the computer is configured to connect via the X.25 packet switching network

Having all of this in data, rather than code, meant that it was easier to tweak the commands to respond to changing needs.  Examples might be:

  • The data could be changed to work with different modems with different command sets.
  • Delays could be added between each character which is sent to suit systems which could not respond to data which is sent at full speed


  • The data could have been held in a file rather than in DATA statements but by putting them inside the compiled program code we made it more difficult for people to see it and potentially tamper with it. A good solution, in fact, would be to check for the existence of such a file and then use it in preference to the DATA statements if one exists. This would allow you to troubleshoot and adapt when working on a client machine
  • On-site troubleshooting would be facilitated by having a secret series of keystrokes which would bring up a window which would show the commands which are being processed along with the data which is being sent and received

Example Two

When I worked in Lotus Development, we had a Lotus Notes application which  we used to receive and manage queries from customer helpdesks around EMEA. We wanted to add some workflows to this application so that it could send notifications, reminders, escalate  cases, etc. This was an early version of Lotus Notes where this couldn’t be done in the application itself (this was before scheduled agents) and would have to be done using the C API.

I could have designed the workflow and got some C developers to code it. Instead, I designed a workflow engine where you could define the workflow using documents in a Lotus Notes database, and then that workflow could run against our tracking application. But, of course, it could also be used to create workflows for ANY Lotus Notes application (and we had a huge number of them!)

So it was a bit like Microsoft Flow (Power Automate) but about 25 years earlier!

The first document in a set would define the schedule so you could have a workflow which would run every hour, day, week, or whatever was required.

The second document would define the set of documents which would be processed. This would normally be a specific “view” in a specific Lotus Notes database.

The remaining documents in the set would define the actions. Each action could have a formula which would be run against the documents – the action would only be executed if the formula returned true (this would like an “if”). And then  the action itself could do things like:

  • Sending an email
  • Updating the document
  • Adding a new (response) document
  • Copying or moving the document
  • Deleting the document

Basically I looked at the API documentation and I created an action for anything which as if it might be useful for creating a workflow.

There was also a flag on the action so you could tell the engine to skip on to the next document in the data set without processing any more actions for this document.

So I could have got the developers to hard-code a workflow for me, but instead I got them to develop a data-driven engine which could be used to create any workflow without the need to write something as complex and error-prone as C code.