Anonymous functions in Siebel

I was on a Project, that was performing an upgrade from Siebel 7 to Siebel 8, and discovered  parts of their Application was implemented using undocumented eScript features. The code was written by graduate web developers, who used their trade to write ECMA compliant code, but unfortunately some of these features were unsupported by Siebel 8.

One such feature was the usage of anonymous functions, which has the following benefits.

* Provides locally scoped variables
* Can be used as a call back function
* Allows better code readability
* Avoids extra named reference on the current scope

Unfortunately anonymous functions, or even function expressions cause a reference error in Siebel 8.


> ReferenceError:':-$753' is not defined

Siebel customers who need a viable substitute have the option of using the Function constructor, which is appropriately documented by Oracle here.
http://docs.oracle.com/cd/B40099_02/books/eScript/eScript_JSReference189.html

Let’s look at a real world scenario to see where this can come in handy.

During development, a Siebel developer might come across the need to enumerate a PropertySet. The following code shows a basic implementation of the enumerator function.


var propName = oPS.GetFirstProperty(), 
propValue ="";
while (propName != "")  {
                propValue = oPS.GetProperty(propName);

                //###  Do something with propName and propValue ###

                propName = oPS.GetNextProperty();
}

I propose that we create a utility for Siebel developers to easily loop over the properties of a single PropertySet level, without the above verbosity, using the following syntax.

1. [<PropertySet> ].psEach( <Callback> )
or
2. util.psEach( <PropertySet>, <Callback> )

The implementation of option 1 is outside the scope of this article, but it can be easily built by customers who already have a familiar construct in their Library.

However option 2 should be a little more familiar to customers who use script libraries in Siebel. util is the name space, or the local reference to a name space from an eScript library. psEach is the logical method that performs the enumeration.

The following diagram shows, how we should use the Function object in this context.


1.       ‘Class_Util_PSNodeEach’ is the literal name for util.psEach.
2.       The PropertySet that we wish to enumerate
3.       A function object that will receive the Name, Value pair.
4.       This function will receive two inputs n, v. This is optional, as the arguments object can be used just as easily.

The following screenshot of The Harness shows the definition of ‘Class_Util_PSNodeEach’, the code that was used to set up the test case, and the expected results.


Line 15. above shows where the magic happens, this API essentially replaces 9 lines 
of code (x the number of times this construct is used in your Application) with 1 line.

Just a friendly reminder that this code has been simplified for illustration purposes, it is not is not production ready or is it 
optimized to be used in the real world.

> new Function("n,v", "log.info(n+' = ' +v " );

The syntax above creates a new function on the fly, which expects an input of "n" and "v". It is invoked by line 5 in the screenshot above, and prints it out using a library method that outputs the result back to the UI. 


This allows us to hide the clunky looping construct that is normally required to enumerate a PropertySet in eScript, and expose a much better API through psEach.

Are there any side effects?

* Code written inside the Function constructor is supplied as a string, which has to be properly escaped

* The function constructor will run in the scope of its instantiated instance. This is normally the current Siebel event handler or Business Service, or the code library where psEach lives, but it could also be the instance of any object created by the new Operator. What this all means is that, the callback function won’t inherit the local scope of your object, and will not have access to your local function’s variables unless they are passed in

* These functions won’t appear in your Siebel eScript object explorer. This could also be an advantage.

In context of the problem that we are trying to solve, the above list doesn't apply, but it should still be taken into consideration if you want to utilize this elsewhere in your Application, and please check with your local eScript architect if you are unsure of the impacts.

Are there any speed difference with either option? Once the function is parsed, it will perform just as well as the function declaration. The following test case shows that with our set up above, there are no discernible speed advantage of using either method.



The Function constructor is possibly one of the most underused features of eScript, but when used in the right way, it can provide your project with the capability to organize, and reduce the amount of code that your developers have to write, test, and maintain. 

Further Reading Topics

Function Constructor JavaScript
Immediately Invoked Function Expressions (IIFE) or
Self Executing Anonymous Functions (SEAF).


The Test

Every once in a while, a developer decides to make a fix without unit testing and breaks the application. There are a variety of reasons why it occurs, it could be that the developer got too confident, maybe it hard to setup the test case, it could be due to inexperience, or it could be due to pressure to turn around the defect, and check it in.

It could also be less sinister, maybe unit testing was performed, but the fix had other unintended impacts, or the unit test was not creative enough to produce errors, or worse still, the defect goes unnoticed until it is released into the wild.

Unfortunately it happens, but can it be prevented?

Imagine your Siebel developers could run a suite of automated test cases, to verify the sanity of the core application just before check in. This would provide your project with a good measure of quality assurance that the application isn't broken. How good the measure is, depends on your test coverage.

Testing can be exhaustive, and take hours to regression test the Application. To make things more manageable, we can split it into two categories.

1. Core application
2. Business functionality

2, can be covered by more comprehensive regression test methods, and are done post check in. Sometimes this is too late. The concept of ‘The Test’ is to focus on 1. Testing the core application, to verify that what’s being checked in, doesn't cause widespread damage to the application in the next migration.

In the past, I've covered this topic in the following articles

SiebUnit - an xUnit implementation
http://www.impossiblesiebel.com/2012/02/siebunit-xunit-implementation.html

SiebUnit - Build Inventory
http://www.impossiblesiebel.com/2012/02/siebunit-build-inventory.html

I've had a lot contact from various Siebel customers over the above articles, confirming that the tool meets a real world need.

“The Test” is not as ambitious, its purpose is to be simple, effective and a lot easier to implement, but it’s not declarative. Writing code to test code, and maintain that extra code, isn't a deal breaker, what’s more important is that your developers have the confidence to make core changes, and your application is protected from serious defects.

Like SiebUnit, the main requirement of ‘The Test’ is to have testable interfaces. Testable interfaces are API’s that can accept an input, produce an output, without any reliance on Siebel’s application context, and are predictable. Ideally it should also have as few dependencies as possible.

In Siebel, these API’s take the following forms.

Business Service
Workflow
Script Library
eScript
Browser/OUI Script

To test the above interfaces, I propose we create a Test library using eScript (for testing server side APIs), it could sit inside your existing Script library if you have one.

There should be an external method called “The Test”, this method could instantiate a new Test class, with a main entry point called “run”, that would run groups of test cases, each of these groups would contain 1 or more test cases. To facilitate the writing of clean test cases, I suggest we enforce a formal structure.

The following code snippet shows an implementation of the above concept in Siebel.


1. Calls a script library function called parseINI that will be tested. The util namespace is used, and invokes parseINI, to return object representation of a configuration file
2. assert is defined as a class function.
3. The purpose of ‘assert ‘, is to determine if a test case has passed or not. The first argument passes the evaluated the condition to assert. 
4. The Output PropertySet is passed to assert for logging the result
5. A description is provided to identify the test case.
6. Test case helpers to minimize coding.

Examples of helpers

* Create a common complex hierarchy for PS manipulation
* Invoke Siebel APIs without using setting up PropertySets
* Invoke WF without the normal setup
* Create a data randomizer to facilitate more creative test cases.


The good news is that with a bit of organization, we can reduce the amount code that a developer has to write to test your APIs. I claim that these test cases are readable, are easily maintained, and require no effort to pick up, other than the inertia to change ones habits.

Now that we have a proposed test case construct, we need to have an ability to report on the test results. Step 4 states this from a high level, but the report can be as simple as name value pairs on an Output PropertySet, or as complex as you need. The report should at the very least, display the number test cases that have passed and failed. This will allow the developer identify where the problem is, fix the issue, and re run The Test again to ensure that all expected test cases pass.

Establishing your Test library a great first step, but acquiring it alone is not is actually not enough, the project has to foster the culture of writing test cases into developers, and factor the effort into the build estimates. The project also has to identify what is testable, and augment what is not testable. A script library is a good example of a testable interface, members of the audience who have the ABS framework on their projects, should be familiar with "The Test".

It takes effort to write the test cases, as well as to maintain them going forward. To be conservative, your current unit testing estimates should be doubled when implementing automated test cases. This may sound a little daunting, so lets take a look a little example that demonstrates the ROI.

Testing an email address validator

You have a written a library function to test the validity of emails. The manual method of test this might be to launch the UI, and navigate to a view, where you repeated enter a series of bad, and good emails, to test the string. Lets say that takes you 5 minutes to perform, and writing automated test cases for the same scenario takes 10 minutes. Now imagine a defect was raised against your code, you would need to fix the defect, and spend another five minutes to re-validate the function to ensure you haven't broken something else. On the other hand, your automated test cases can be re run in an instant.

The initial effort to write the test case, will be paid back in spades. Your application will require less re-development, and suffer less downtime as a result, your developers will have the confidence to make core changes, automated unit tests can be your unit test documentation, your application will be more robust, and my personal favorite, is that developers can write the unit test once, and run it multiple times.

Once you have the right framework in place, and given enough experience (1-2 weeks), writing test cases actually saves more time than not writing them.

The Test is simple to build, and can be taken as a quick win towards a larger goal, for ensuring a better quality product. However be warned that once you start writing automated test cases, you won't want to look back to manual testing.