When use CFML code in the 'pseudo constructor' vs 'function init()' in a component - coldfusion

Given e.g. of the Pseudo Constructor in CFML:
component{
// Pseudo Constructor start
... here comes some cfml scripting code..
// Pseudo Constructor end
function init(){
return this;
}
}
I already understand that the Pseudo Constructor in a .cfc component:
Is the cfml code inbetween the component's beginning and the function init().
That the Pseudo Constructor's code runs immediately on components creation, even before the instantiating constructor "function init()" is invoked.
The variables created in the Pseudo Constructor are also available to all other components functions (Lexical Scoping)
Even code inbetween some component functions are also refered as Pseudo Constructors by some experienced cfml devs.
Please consider that I'm not refering to the use of cfproperty or property here, but to any other code in the Pseudo Constructor.
Still, I've not seen a good example or use case in CFML to help me decide. Could any experienced OOP CFML developer elaborate an example to understand it better:
When to use a code in the Pseudo Constructor and not the "function init()"?
Why NOT use the code in the instantiating constructor "function init()", so that the variables can be accessed/referenced with "this" keyword in any other components functions?
Please give an example code in such a manner that may help me and others decide when to use one over the other in the future?

After investigating a little deeper I came up with my own conclusion that I'd like to share with all interrested CFML developers. If any experienced OOP CFML developer has more precise information, I'd be really glad to know.
I've created a component named Cube.cfc that may answer the question for itself. My conclusion basically is that "pseudo constructors" allow to create some kind of "static" functions, because these fucntions can make use of these variables without instantiation of an object. Note that I didn't want to use the term "static" because these functions lacks of the naming attribute "static" (as far as I'm aware, only Lucee supports real "static" functions at the moment). Also, the example I'm showing only seems to work with createObject() and not the implicit constructors e.g. new Component(), because new Component() would instantiate the object immediately. But: using createObject and the pseudo constructor will at least allow to mimic static functions. Please note that my example component is just to be descriptive.
In the following example im using available functions that won't need any object instantiation. These functions can be used to retrieve some usefull informations that are not bound to any created/instantiated object.
Cube.cfc: a simple component to create cube objects
component displayname="Cube" accessors ="true" {
// class properties
property name="name" type="string";
property name="model" type="string";
property name="borderColor" type="string";
property name="material" type="string";
property name="dimension" type="struct";
// pseudo constructor
variables.models =[
"model-a",
"model-b",
"model-c"
];
variables.modelNameMaterialMapping ={
"model-a": "wood",
"model-b": "steel",
"model-c": "silver"
};
variables.modelNameDimensionsMapping ={
"model-a": {"height": 100, "length": 100, "width": 100 },
"model-b": {"height": 133, "length": 133, "width": 133 },
"model-c": {"height": 85, "length": 85, "width": 85 }
};
public any function init(
string name,
string borderColor,
string model
){
setName( arguments.name );
setBorderColor( arguments.borderColor );
setModel( arguments.model );
setMaterial( getMaterialByModelName( arguments.model ) );
setDimension( getDimensionByModelName( arguments.model ) );
return this;
}
//this function won't need any instantiating of an object because it uses variables of the pseudo constructor
public string function getMaterialByModelName( string modelName ){
return modelNameMaterialMapping[ arguments.modelName ];
}
//this function won't need any instantiating of an object because it uses variables of the pseudo constructor
public struct function getDimensionByModelName( string modelName ){
return modelNameDimensionsMapping[ arguments.modelName ];
}
//this function won't need any instantiating of an object
public string function isValidModel( string model ){
return variables.models.contains( arguments.model );
}
}
index.cfm:
<cfscript>
CubeService = CreateObject("component","Cube");
writeDump( CubeService );
writeDump( GetMetaData( CubeService ) );
modelsForChecking=[
"model-a",
"model-k",
"model-c",
"model-z"
];
// loop through model information without having any object instantiated
for( model in modelsForChecking){
if( CubeService.isValidModel( model )){
writeOutput("Cube ""#model#"" is valid.<br>");
writeOutput( "Cube models ""#model#"" are made of ""#CubeService.getMaterialByModelName( model )#"" and a dimension of ""#CubeService.getDimensionByModelName( model ).width#x#CubeService.getDimensionByModelName( model ).length#x#CubeService.getDimensionByModelName( model ).height#""<br>");
}else{
writeOutput("Cube ""#model#"" is NOT a valid model.<br>");
}
}
//intantiate a specific cube object with the name "CubeOne";
writeOutput( "Instantiate an object with the component:<br>");
CubeOne=CubeService.init("CubeOne", "white", "model-c" );
// dump properties of the specific cube "CubeOne"
writeDump( CubeOne );
// get width with the accessor getter for property "dimension" for the cube named "CubeOne"
writeOutput("""CubeOne"" has a width of #CubeOne.getDimension().width# <br>");
</cfscript>
If you run the above files you'll note that the functions:
getMaterialByModelName( "model-a" ),
getDimensionByModelName( "model-b"),
isValidModel( "model-z" )
don't need any instantiated object. They just retrieve some usefull information about the cube models without running any init() function.
That causes me to assume the following thumb rules:
Use variables that are bound to a property of an instantiated object within the "init()" functions.
Use variables in the 'Pseudo Constructor' whenever you need to use functions with those variables before having used the init() function.
Note that my component is just to be an descriptive example. If somebody comes up with more detailed information about the topic or I need to be corrected in my assumptions, I'd be glad to know.
IMPORTANT UPDATE: As #SOS thankfully commented, Adobe Coldfusion supports static functions since Coldfusion 2021. These "non-instantiated-object-related" functions can now be directly invoked with Component::staticFunctionName( args ) without using any preceeding CreateObject() nor the implicit constructor new Component()! As #SOS also commented, looks like "using static is probably the best approach for 2021+" in CFML because now both CFML engines Lucee and Coldfusion fully supports them.
For completeness I'm placing an adapted/rewritten version of my example code as a reference for 2021+:
Cube.cfc
component displayname="Cube" accessors ="true" {
// class properties
property name="name" type="string";
property name="model" type="string";
property name="borderColor" type="string";
property name="material" type="string";
property name="dimension" type="struct";
// set static varibales
static {
private models =[ "model-a", "model-b", "model-c" ];
private modelNameMaterialMapping ={
"model-a": "wood",
"model-b": "steel",
"model-c": "silver"
};
private modelNameDimensionsMapping ={
"model-a": {"height": 100, "length": 100, "width": 100 },
"model-b": {"height": 133, "length": 133, "width": 133 },
"model-c": {"height": 85, "length": 85, "width": 85 }
};
};
public any function init(
string name,
string borderColor,
string model
){
setName( arguments.name );
setBorderColor( arguments.borderColor );
setModel( arguments.model );
setMaterial( static.getMaterialByModelName( arguments.model ) );
setDimension( static.getDimensionByModelName( arguments.model ) );
return this;
}
public static string function getMaterialByModelName( string modelName ){
return static.modelNameMaterialMapping[ arguments.modelName ];
}
public static struct function getDimensionByModelName( string modelName ){
return static.modelNameDimensionsMapping[ arguments.modelName ];
}
public static string function isValidModel( string model ){
return static.models.contains( arguments.model );
}
}
index.cfm
<cfscript>
modelsForChecking=[
"model-a",
"model-k",
"model-c",
"model-z"
];
// loop through model information without having any object instantiated by calling static functions
for( model in modelsForChecking){
if( Cube::isValidModel( model )){
writeOutput("Cube ""#model#"" is valid.<br>");
writeOutput( "Cube models ""#model#"" are made of ""#Cube::getMaterialByModelName( model )#"" and a dimension of ""#Cube::getDimensionByModelName( model ).width#x#Cube::getDimensionByModelName( model ).length#x#Cube::getDimensionByModelName( model ).height#""<br>");
}else{
writeOutput("Cube ""#model#"" is NOT a valid model.<br>");
}
}
//intantiate a specific cube object with the name "CubeOne";
writeOutput( "Instantiate an object with the component:<br>");
CubeOne=new Cube("CubeOne", "white", "model-c" );
// dump properties of the specific cube "CubeOne"
writeDump( CubeOne );
// get width with the accesso getter for property dimension for the cube named "CubeOne"
writeOutput("""CubeOne"" has a width of #CubeOne.getDimension().width# <br>");
</cfscript>
For further reference, see:
Static functions for CFC in Lucee
Static functions for CFC in Adobe
CFML: static methods and properties - by Adam Camaron

Related

Spock - How to work with repeated interactions

For few test cases I'm trying to follow a DRY principle, where only the interactions are different with same test case conditions. I'm not able to find a way to implement multiple methods in the interaction { } block.
As mentioned in http://spockframework.org/spock/docs/1.3/interaction_based_testing.html#_explicit_interaction_blocks, I'm using interaction { } in the then: block like below:
Java Code:
// legacy code (still running on EJB 1.0 framework, and no dependency injection involved)
// can't alter java code base
public voidGetData() {
DataService ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset() // happy path scenario; missing a null check
// other code
}
// other varieties of same code:
public voidGetData2() {
ItemEJB tmpItem = new ItemEJB();
ItemEJB item = tmpItem.findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
public voidGetData3() {
ItemEJB item = new ItemEJB().findByOffset(5);
if(null != item) {
Long len = item.getOffset();
// other code
}
}
Spock Test:
def "test scene1"() {
given: "a task"
// other code ommitted
DataService mockObj = Mock(DataService)
when: "take action"
// code omitted
then: "action response"
interaction {
verifyNoDataScenario() // How to add verifyErrorScenario() interaction to the list?
}
}
private verifyDataScenario() {
1 * mockObj.findByOffset(5) >> mockObj // the findByOffset() returns an object, so mapped to same mock instance
1 * mockObj.getOffset() >> 200
}
private verifyErrorScenario() {
1 * mockObj.findByOffset(5) >> null // the findByOffset() returns null
0 * mockObj.getOffset() >> 200 // this won't be executed, and should ie expected to throw NPE
}
The interaction closure doesn't accept more than one method call. I'm not sure if it's design limitation. I believe more can be done in the closure than just mentioning the method name. I also tried interpolating the mockObj as a variable and use data pipe / data table, but since it's referring the same mock instance, it's not working. I'll post that as a separate question.
I ended up repeating the test case twice just to invoke different interaction methods. Down the line I see more scenarios, and wanted to avoid copy & paste approach. Appreciate any pointers to achieve this.
Update:
Modified shared java code as the earlier DataService name was confusing.
As there's no DI involved, and I didn't find a way to mock method variables, so I mock them using PowerMockito, e.g. PowerMockito.whenNew(DataService.class).withNoArguments().thenReturn(mockObj)
Your application code looks very strange. Is the programming style in your legacy application really that bad? First a DataService object is created with a no-arguments constructor, just to be overwritten in the next step by calling a method on that instance which again returns a DataService object. What kind of programmer creates code like that? Or did you just make up some pseudo code which does not have much in common with your real application? Please explain.
As for your test code, it also does not make sense because you instantiate DataService mockObj as a local variable in your feature method (test method), which means that in your helper method mockObj cannot be accessed. So either you need to pass the object as a parameter to the helper methods or you need to make it a field in your test class.
Last, but not least, your local mock object is never injected into the class under test because, as I said in the first paragraph, the DataService object in getData() is also a local variable. Unless your application code is compeletely fake, there is no way to inject the mock because getData() does not have any method parameter and the DataService object is not a field which could be set via setter method or constructor. Thus, you can create as many mocks as you want, the application will never have any knowledge of them. So your stubbing findByOffset(long offset) (why don't you show the code of that method?) has no effect whatsoever.
Bottom line: Please provide an example reflecting the structure of your real code, both application and test code. The snippets you provide do not make any sense, unfortunately. I am trying to help, but like this I cannot.
Update:
In my comments I mentioned refactoring your legacy code for testability by adding a constructor, setter method or an overloaded getData method with an additional parameter. Here is an example of what I mean:
Dummy helper class:
package de.scrum_master.stackoverflow.q58470315;
public class DataService {
private long offset;
public DataService(long offset) {
this.offset = offset;
}
public DataService() {}
public DataService findByOffset(long offset) {
return new DataService(offset);
}
public long getOffset() {
return offset;
}
#Override
public String toString() {
return "DataService{" +
"offset=" + offset +
'}';
}
}
Subject under test:
Let me add a private DataService member with a setter in order to make the object injectable. I am also adding a check if the ds member has been injected or not. If not, the code will behave like before in production and create a new object by itself.
package de.scrum_master.stackoverflow.q58470315;
public class ToBeTestedWithInteractions {
private DataService ds;
public void setDataService(DataService ds) {
this.ds = ds;
}
// legacy code; can't alter
public void getData() {
if (ds == null)
ds = new DataService();
ds = ds.findByOffset(5);
Long len = ds.getOffset();
}
}
Spock test:
Now let us test both the normal and the error scenario. Actually I think you should break it down into two smaller feature methods, but as you seem to wish to test everything (IMO too much) in one method, you can also do that via two distinct pairs of when-then blocks. You do not need to explicitly declare any interaction blocks in order to do so.
package de.scrum_master.stackoverflow.q58470315
import spock.lang.Specification
class RepeatedInteractionsTest extends Specification {
def "test scene1"() {
given: "subject under test with injected mock"
ToBeTestedWithInteractions subjectUnderTest = new ToBeTestedWithInteractions()
DataService dataService = Mock()
subjectUnderTest.dataService = dataService
when: "getting data"
subjectUnderTest.getData()
then: "no error, normal return values"
noExceptionThrown()
1 * dataService.findByOffset(5) >> dataService
1 * dataService.getOffset() >> 200
when: "getting data"
subjectUnderTest.getData()
then: "NPE, only first method called"
thrown NullPointerException
1 * dataService.findByOffset(5) >> null
0 * dataService.getOffset()
}
}
Please also note that testing for exceptions thrown or not thrown adds value to the test, the interaction testing just checks internal legacy code behaviour, which has little to no value.

Getting values from THIS scope after init function (persistency inside CFC)

I'm initiating a CFC like this.
<cfscript>
lock scope="application" timeout="5" {
application.mycfc = new mycfc();
}
writeOutput(application.mycfc.readVars());
</cfscript>
In the CFC, I'm setting some properties.
component output="false" accessors="true" {
property name="title";
property name="foo";
this.title = "mycfc";
function init() {
this.foo = "bar";
// I can now properly read this.title, or this.foo.
return this;
}
function readVars() {
// Here, I can read this.title, from the constructor space, but I can't
// read this.foo. It's just blank (because the default value of the
// `default` attribute of `property` is "")
}
}
Because of the implementation (caching in Application), I can instead use application.mycfc.foo in readVars().
Because of this name, it's hard to Google for details. I thought it would be persistent throughout the CFC's life, but apparently it is not?
I surely could do something like
var self = application[this.title]; // or application.mycfc
Or perhaps even
this = application[this.title];
In functions where I want to get/set without typing application.mycfc each time.
Just trying to make sure I'm not doing something wrong, or reinventing the wheel.
In my real implementation, I'm pulling from rows from a database to populate a struct.
Scopes in ColdFusion components (.cfc):
this
is the public scope, read/write from anywhere
properties
is a magical scope, read/write only via accessors (a.k.a. getters/setters) from anywhere
variables
is the private scope, read/write only within your component
All of these scopes can coexist, but this.x is NOT the same field as property name="x"!
Since you are using a component with accessors="true", all your property fields can only be read via getter and written via setter. So if you want to write your title property, use setTitle("mycfc"); instead of this.title = "mycfc";. Same goes for the foo property. Use setFoo("bar"); instead of this.foo = "bar";. If you want to read the properties, use application.mycfc.getTitle() and application.mycfc.getFoo(). If you want to set properties at runtime, use application.mycfc.setTitle("something"). Note that writing to a shared scope such as application should happen in a cflock to avoid race conditions (thread-safety).
If you don't need accessors at all, you can simply use public fields instead (accessors is missing here, i.e. set to false):
component output="false" {
this.title = "mycfc";
this.foo = "";
function init() {
this.foo = "bar";
return this;
}
function readVars() {
return this;
}
}
application.mycfc = new mycfc();
writeOutput(application.mycfc.title); // mycfc
writeOutput(application.mycfc.foo); // bar
application.mycfc.title = "something";
writeOutput(application.mycfc.title); // something
writeOutput(application.mycfc.foo); // bar
Public fields are usually not recommended though as they break encapsulation.

UnityEngine.Object instances have no name property in test

Assigning names to my objects (like the ones returned from the global Instantiate method) is breaking my tests. Anyone have any ideas for how to get around such things in test?
using System;
using NUnit.Framework;
using UnityEngine;
[TestFixture()]
public class BoardSpec{
[Test()]
public void NamePropertyWorks(){
var obj = new UnityEngine.Object();
obj.name = "object name";
}
}
The error I'm receiving: System.MissingMethodException : Cannot find the requested method.
The first line of the stack trace gives: at (wrapper managed-to-native) UnityEngine.Object:set_name (string)
Unity 5.2.0f3, running tests in MonoDevelop-Unity 4.0.1 on osx
_____update 9/20______
It sounds like creating new Objects is not recommended, but this code fails with the same error:
[Test()]
public void ScriptableObjectNamePropertyWorks(){
var obj = new ScriptableObject();
obj.name = "object name";
}
Short answer: Never create nor inherit directly form UnityEngine.Object, use ScriptableObject instead
Doing something like (new UnityEngine.Object()).name = "text" will always throw a null reference exception, as I'll explain below. From there to the System.MissingMethodException you are getting, it depends on the inner workings of NUnit.
Unity uses UnityEngine.Object in a very special way, keeping track of objects, and considering some "not alive" despite existing. The Equals comparison for UnityEngine.Object is overriden to reflect this, and an existing Object might equal null:
// Both Mesh and MyObject inherit directly from UnityEngine.Object
Object plainObject = new UnityEngine.Object();
Mesh meshObject = new UnityEngine.Mesh();
MyNumber myNumber = new MyNumber(123456f);
// using the overriden Unity.Object.Equals()
print(plainObject != null); // false
print(meshObject != null); // true
print(myNumber != null); // false
// With traditional null checking, everything exists of course, as we just created them
print(plainObject as System.Object != null); // true
print(meshObject as System.Object != null); // true
print(myNumber as System.Object != null); // true
print(myNumber.number); // prints 123456, the object is there and perfectly operational
print(myNumber.name); // the program ends with a null reference exception thrown by the name set accessor, because myNumber is not "alive"
Every native Unity class that inherits from UnityEngine.Object makes any needed internal call to register the object as "alive", but this is not done in the base class itself. Basically, any attempt to create a vanilla Object, or something directly inherited from it, will be considered stillborn by the engine, and you won't get it to work as usual. If you need to create or inherit from Objects, use ScriptableObject instead, that has an explicitly special behaviour in the inner workings.

QML: How to use a dynamically created component with a customized internal object?

I'm looking for a way to dynamically create a component and object, and use the component. It seems like most of the examples available, such as those in the Qt documentation or other StackOverflow posts, are related to using the object returned from createObject(), whereas I want to use the component which contains the (customized) object.
I've stripped out a lot of extraneous detail (e.g. the CustomContainer gets pushed onto/popped off of StackViews), but the following code hopefully illustrates what I'm trying to do... Basically, I would like to have the CustomControl rectangle with foo = 10 and bar = 10, but it seems to load with the defaults instead. There will be multiple "custom control" types and multiple "custom container" objects so I need to be able to support this generically.
The Qt documentation talks about creation contexts, which I assume is my problem, but I'm not sure how to fix this. I'd prefer a purely QML solution, but C++ is fine if that's where the solution lies.
Main.qml:
CustomContainer {
id: myCustomContainer
}
CustomContainer {
id: myOtherCustomContainer
}
function addCustomControl( control, args ) {
var newComponent = Qt.createComponent( control )
var newObj = newComponent.createObject( myCustomContainer, args )
return newComponent
}
myCustomContainer.loaderSource = addCustomControl( "CustomControl.qml", { "foo": 10, "bar": 10 } )
myOtherCustomContainer.loaderSource = addCustomControl( "CustomControl.qml", { "foo": 20, "bar": 20 } )
CustomControl.qml:
Rectangle {
property int foo: 5
property int bar: 5
}
CustomContainer.qml:
Item {
property Component loaderSource
onLoaderSourceChanged: {
myLoader.sourceComponent = loaderSource
}
Loader {
id: myLoader
onSourceComponentChanged: {
doStuff()
}
}
}
The component does not "contain the object". The component is a prototype for objects to be instantiated. Think of it like a "type" or a class or struct in C++ vs an instance of that type.
Your code creates the component, and then creates an object from it with modified values for the properties, but the component still has its default properties, so using it as a source component will produce objects with default properties.
Furthermore, a Loader will do automatic dynamic instantiation for you. So you don't need to combine both manual and automatic, either do it manually, or leave the loader to do it.
Last, but not least, when components are instantiated by a StackView they will automatically fill it and their size will be bound to it, so it will automatically change as the StackView size changes. So just use an Item and put your content in there and layout it. Only the root item's size will be bound to the StackView size, its children items will have their own sizes.

Integrating Lua to build my GameEntities in my Game Engine?

I really want to add Lua Scripting to my Game Engine. I am working with Lua and bound it to C++ using luabind, but I need help to design the way I will construct my Game Entities using Lua.
Engine Information:
Component Oriented, basically each GameEntity is a list of components that are updated in a delta T interval. Basically Game Scenes are composed by collections of Game Entities.
So, here's the dilemma:
Let's say I have this Lua file to define a GameEntity and it's components:
GameEntity =
{
-- Entity Name
"ZombieFighter",
-- All the components that make the entity.
Components =
{
-- Component to define the health of the entity
health =
{
"compHealth", -- Component In-Engine Name
100, -- total health
0.1, -- regeneration rate
},
-- Component to define the Animations of the entity
compAnimation =
{
"compAnimatedSprite",
spritesheet =
{
"spritesheet.gif", -- Spritesheet file name.
80, -- Spritesheet frame width.
80, -- Spritesheet frame height.
},
animations =
{
-- Animation name, Animation spritesheet coords, Animation frame duration.
{"stand", {0,0,1,0,2,0,3,0}, 0.10},
{"walk", {4,0,5,0,6,0,7,0}, 0.10},
{"attack",{8,0,9,0,10,0}, 0.08},
},
},
},
}
As you can see, this GameEntity is defined by 2 components, "compHealth" and "compAnimatedSprite". Those two totally different components require totally different initialization parameters. Health requiring an integer and a float ( total and regeneration ), and on the other side, animations requiring a sprite sheet name , and to define all of the animations ( the frames, durations, etc ).
I would love to make some kind of abstract class with some virtual initializer method that could be used by all my components that require Lua binding in order to facilitate initialization from Lua, but it seems difficult, because the virtual class is not going to have one virtual init method. This is because all of the component initializers (or most of them) require different init parameters (health component requires different init than Animated Sprite component, or AI component).
What do you suggest to make the Lua bindings to the constructors of this components easier ? or how would you do it ?
PS: I must use C++ for this project.
I'd suggest using a composite structure instead for your game entities. Add objects inheriting from a common game entity component to each game entity as you encounter them while parsing the Lua configuration table. This task is a perfect candidate for the factory method. Note that composing your entities in this way still requires all methods to be implemented in the GameEntity class unless you use an alternate dispatch method like message passing (see the visitor pattern)
On the Lua side, I find it is more convenient to use callback function with a single table argument instead of traversing a complex table structure in C/C++. Here is a pure Lua example of what I mean using your data.
-- factory functions
function Health(t) return { total = t[1], regeneration = t[2] } end
function Animation(t) return { spritesheet = t[1], animations = t[2] } end
function Spritesheet(t)
return { filename = t[1], width = t[2], height = t[3] }
end
function Animations(t)
return { name = t[1], coords = t[2], duration = t[3] }
end
-- game entity class prototype and constructor
GameEntity = {}
setmetatable(GameEntity, {
__call = function(self, t)
setmetatable(t, self)
self.__index = self
return t
end,
})
-- example game entity definition
entity = GameEntity{
"ZombieFighter",
Components = {
Health{ 100, 0.1, },
Animation{
Spritesheet{ "spritesheet.gif", 80, 80 },
Animations{
{"stand", {0,0,1,0,2,0,3,0}, 0.10},
{"walk", {4,0,5,0,6,0,7,0}, 0.10},
{"attack", {8,0,9,0,10,0}, 0.08},
},
},
}
}
-- recursively walk the resulting table and print all key-value pairs
function print_table(t, prefix)
prefix = prefix or ''
for k, v in pairs(t) do
print(prefix, k, v)
if 'table' == type(v) then
print_table(v, prefix..'\t')
end
end
end
print_table(entity)