Open UI: Property Set Methods (Why Clone?)

Open UI: New Property Set Structure
Open UI: Property Set Methods (Copy, DeepCopy, Clone)
Open UI: Property Set Methods (Fixing Copy)


Previously on Open UI: Property Set - Methods (Copy, DeepCopy, Clone), we discovered two new ways to copy a Property Set (DeepCopy and Clone).

DeepCopy is similar to Copy, except it merges two Property Sets together, while Clone performs a full copy of a PropertySet just like Copy, which raises the question around the meaning of life for Clone...until now.

To understand why Clone exists, we need to go back to the basics of ECMA script, which eScript, Browser Script and Java Script are all based upon.

Argument Passing

It is common knowledge, that there are two kinds of variables.

Primitive:
Number, Boolean, String, Undefined, Null

Complex/Composite:
Object, Array, Property Set, BusComp, Business Service, BusObject


Property Sets, BusComps, BusObject, Business Services are specific to the Siebel environment, and are considered to be complex/composite Objects, because they are derived from the base Object.


It is also "common" knowledge that complex/composite objects are passed into functions by reference. This view is supported by Bookshelf.

Passing Variables to Functions in Siebel eScript

Composite types such as objects and arrays are passed by reference.

However this is a common misconception, in fact all function arguments are actually passed in by value. Siebel professionals who work with Siebel Inputs/Outputs day in and day out, will testify to the opposite.

This is not the first time we've challenged the view of the world, so let me back this up with evidence, and what better way than to do it than with Siebel's Property Set Copy and Clone?


//Create new Property Set
var ps = SiebelApp.S_App.NewPropertySet();
//Set Type on original PS
ps.SetType("A");
console.log( ps.GetType() );
//Type stores "A"

//Perform Copy on ps
copyPS(ps);

function copyPS(ps){
     var ps2 = SiebelApp.S_App.NewPropertySet();
     //Create a new PS and set the type
     ps2.SetType("B");
     //perform a copy on ps2
     ps.Copy(ps2);
}

console.log( ps.GetType() );
//Type now stores "B"



The above test case starts off with a Property Set with a Type "A", which is passed into copyPS, which modifies the original Property Set's Type to "B". This is what we know and expect.

Watch what happens when we use Clone.

//Create new Property Set
var ps = SiebelApp.S_App.NewPropertySet();

//Set type on Original PS
ps.SetType("A");
console.log( ps.GetType() );
//Type stores "A"

//Perform Clone on ps
clonePS(ps);

function clonePS(ps){
     var ps2 = SiebelApp.S_App.NewPropertySet();
     //Create a new PS and Set the type to a different value
     ps2.SetType("B");
     //If this argument was passed in by Reference
     //it should contain the new type above.
     ps=ps2.Clone();
}

console.log( ps.GetType() );
//Type still stores "A", 
//the cloned value was lost!



With the same expectation as above, if ps were passed in as a reference, we would see that the original Property Set's type would be modified to "B", instead the original Property Set remains’ unchanged.

Here is another derivative of the above example

var ps = theApplication().NewPropertySet();
ps.SetType("A");
var ps2 = theApplication().NewPropertySet();
ps2.SetType("B");

//Perform Clone on ps
clonePS(ps, ps2);

function clonePS(ps, ps2){
     //If this argument was passed in by Reference
     //it should contain the new type above.
     ps=ps2.Clone();
}

console.log( ps.GetType() );
//Type still stores "A", 
//the cloned value was lost!



In the second example, I’ve moved both ps and ps2 declarations to global scope, and passed in the both Property Set "references". The function clonePS tries to reassign the reference but fails.



To explain this behaviour, think of ps as a reference that is being passed in by value and not as a reference passed in by reference. The reference can be used to modify the original Object, but the reference to the original object itself cannot be altered inside the function. The local copy can be changed to point to another object, however this local copy is independent from our original object.

eScript developers will be wondering, will this really apply to them? Lets fire up The Harness, and create a new test case using Server Script.



The above test case shows ps1 and ps2 being passed into a function, where the ps1 reference is set, and then reassigned to another Property Set. From our understanding above, the following statement fails

ps1=ps2

There are no surprises at this point, as the results reflect what we saw in the browser.



We can conclude that this behaviour exists in eScript/BScript and JavaScript, which are all flavours of the ECMA specification. The only exception to this rule is that with eScript, we get a special function argument modifier "&" that allows us to pass a reference by reference.

Conclusion

Siebel designed Clone to behave fundamentally different from Copy and DeepCopy, and provides it as a distinct alternative for those circumstances that the original Property Set should be preserved.

On the surface Copy, DeepCopy, and Clone look like they behave the same, but its only when we look beneath the surface, that we appreciate the subtleties of Siebel Property Sets. It brings me back to my favourite Yum cha restaurant, and being presented with Prawn & Basil dumpling, Deep fried Prawn Dumpling, and Prawn Gyoza Dumpling.

All claim to be Prawn dumplings, they have different presentations, but it’s not until you dig into it, that you begin to enjoy the subtleties of Prawn that is deep friend, pan fried, and steamed. The next time you copy that Property Set, spare a thought for the Siebel engineers who provided the different flavours of Copy, DeepCopy, and Clone, for you to enjoy.



Reactions:

0 comments:

Post a Comment

Comments are open to all, please make it constructive.