We all know that Remedy’s developing paradigm is very different from traditional programming. We have no code, no loops, no functions nor any other classical element. But, classical programming has a long way and a lot of minds thinking about it. So there are some very useful concepts that, if propagated to Remedy, can provide a great advantage. One of this missing things in Remedy is the function concept. There is no function concept in Remedy apart of built in functions. But, using workflow elements we can emulate the function concept and create our own library.
In this post I will review the function concept and how can it be implemented in BMC Remedy Action Request System developments.
The concept of function
Strictly a function is some entity that from a number of inputs provides an output. It can be particularized as a reusable piece of code that needs some predefined input and computes an output. In that sense a function is a sequence of commands.
The most important fact of a function, and the main reason for it existence is its reusability. Once you programmed a function, you can use it everywhere you want in your code.
A function in traditional assembly
Typically, an assembly function expects some data (the input) to be placed in a particular memory location (like the stack or registers). It processes the information from this input using a set of temporally reusable memory locations (typically registers or the stack), and once the output is obtained it is placed at a predefined location (yes, again a register or the stack). So there exists a convention about where the data is expected to be and which type of data will be at these places. Also exists a convention of what resources the function can use and where is expected to write the output.
When you code a function in classical C, the assembler translates the function into an assembly that follows this convention.
Applying the concept to Remedy
So, to create a function we need:
- A convention about where the input is to be placed and of which type of data.
- A convention about what resources the function can freely use without disturbing other code.
- A convention about where to write the output and of which data type.
- A set of code to be executed.
Now it is straightforward, just follow these rules and you’ll get it! Well, I’ll give you a hand. Three points are about creating a convention of where and which type. We do not have access to memory in Remedy, but we have access to fields. So we need to create a convention about fields.
The field convention
The convention must be reusable everywhere at your application, so you must create a set of fields defining for each:
- A field ID number.
- A name (not really required but it is advisable to have a unique name).
- A data type.
Imagine you are planning to create a sum function (completely useless but for demonstration purposes it’s OK). You need two integers as the input and one integer as the output. So you will need something like:
- FunctionSumInput1 (900000001) Integer
- FunctionSumInput2 (900000002) Integer
- FunctionSumOutput3 (900000003) Integer
You’ve a convention. Your function will expect to read the values form the input fields and place the output at the output field. Thus, if you create these fields at any form you’ll be able to use the function.
But as the number of functions you create increases, it will also increase the number of fields you need to adapt your forms to these functions. Also, following this design is very difficult. The best practice is to share these fields among all your functions. So you need to create a set of input fields of a variety of types (enough to fit any of your functions). It can be something like:
- FunInChar1 (900000001) Character
- FunInChar2 (900000002) Character
- FunInInt1 (900000101) Integer
- FunInInt2 (900000102) Integer
- FunInDT (900000201) Date/Time
- FunInDT (900000202) Date/Time
- FunOutChar1 (900010001) Character
- FunOutInt1 (900010101) Integer
- FunOutDT1 (900010201) Date/Time
Using this list of fields your form can hold any functions with a maximum of two character, numeric or date/time fields at the input and one character, numeric, date/time field at output.
Also you need to make place to function variables, that is values that the function can use for its own purpose. The function can use any input value that is not used as an actual input to store temporally values. So, in your convention you must create enough input fields of each type to hold the input and function variables.
Adapting a form to hold a function
In order to allow a form to call your functions you need to create the set of fields defined in the previous step. Create these fields as display only, since they are only temporally values. If you need to store the output of a function, you must create a workflow that copies the output from the function field to your stored one.
Creating the function
You can have two types of functions, to be executed by the client or to be executed by the server. The same logic applies to both, but functions to be executed at the client are composed by active links, and active link guides; and functions to be executed at the server are composed of filters and filter guides.
The function will be a guide that stores all the elements that compute the result, to be placed at one of the output fields. For instance our sum function will be a guide containing only one active link with a set action that computes FnOutInt1 = FnInInt1 + FnInInt2. And that’s all.
You must follow a set of rules:
- Your function can execute actions or retrieve information for other forms.
- Your function can only use the function fields of the calling form.
- Document your function.
- Beware of the rights you are giving to the function for the client side case.
- Share the elements (guides, active links, filters) with the form that will use them.
Making the test bed
I recommend to create a display only form containing all the function fields. Create a button for each client side function, that fires it. Also create an option field with all your server side functions. And create a button that calls a service, that calls the desired function and shows the results. This form will able you to test the function development. Also you will be able to copy all the function fields to a form to quickly adapt the form to your functions library.
Document, document and document
Document each of your functions describing the inputs outputs and behavior. Do it the best as you can. Every minute spent on this documentation task will be returned in the future.
How functions are used in BMC out-of-the-box applications
BMC uses a similar concept to share its workflow between forms and applications. If you take a look at the fields of any BMC form you will surely find the z1D_Char fields. These are the function fields for BMC. But BMC uses these fields for any temporally activity (a use i do not recommend), and when adding a workflow element you are not always sure that these fields can be utilized and don’t store critical data.
So I recommend you to create your own set of function fields and think building your reusable code library.