Smack me with a kipper.
fluent:
a = (NEW ValueObject.Address())
:AcornCode("something")
:Building("something")
:Country("something")
:County("something").
Normal
a = NEW ValueObject.Address().
ASSIGN a:AcornCode = "something"
a:Building = "something"
a:Country = "something"
a:County = "something".
1000 iterations, fluent is 120ms, normal is 155ms
Wow
fluent:
Is that new in 10.2B04?
And snack me because you can stack 'em with the parens ... my versions look something like (2 lines).
a = NEW ValueObject.Address().
a:AcornCode("something")
:Building("something")
:Country("something")
:County("something").
-- peter
Fluent: http://en.wikipedia.org/wiki/Fluent_interface .
Basically each method returns THIS-OBJECT (as an Interface, say) and so you can daisy-chain them along.
-- peter
Might be even faster to supply them with the constructor.
I wish
No, it's just a visual "cheat" .. this (crappy) code fragment shows
how the cheat works.
class ....
METHOD PUBLIC ValueObject.Address AcornCode(p_Data AS CHAR):
AcornCode = p_Data.
RETURN THIS-OBJECT.
END METHOD.
METHOD PUBLIC ValueObject.Address Building(p_Data AS CHAR):
Building = p_Data.
RETURN THIS-OBJECT.
END METHOD.
METHOD PUBLIC ValueObject.Address Country(p_Data AS CHAR):
Country = p_Data.
RETURN THIS-OBJECT.
END METHOD.
METHOD PUBLIC ValueObject.Address County(p_Data AS CHAR):
County = p_Data.
RETURN THIS-OBJECT.
END METHOD.
end class.
have a look at http://en.wikipedia.org/wiki/Fluent_interface
Almost looks like a new language feature in this formatting... But now it's clear.
My problem with using a constructor-based approach is that the order
of the parameters is strict. This isn't. Mind you, not sure that I
like it ...
On 29 March 2011 22:16, Thomas Mercer-Hursh
jmls wrote:
My problem with using a constructor-based approach is that the order
of the parameters is strict. This isn't. Mind you, not sure that I
like it ...
I really like it, when it's appropriate (of course). It's great for building more natural-reading constructs, as in ...
/* scopes the tenant manager's lifecycle to the security manager's */
oBindingSyntax = Bind('OpenEdge.CommonInfrastructure.Common.ITenantManager').
oBindingSyntax
:To('OpenEdge.CommonInfrastructure.Server.TenantManager')
:Using('OpenEdge.CommonInfrastructure.Common.InjectABL.ServiceProvider')
:InScope(Class:GetClass('OpenEdge.CommonInfrastructure.Common.InjectABL.ManagerScope'),
ManagerScopeEnum:SecurityManager)
:OnServerSession().
And now with Julian's parens-around-the-first-line trick, it'll be even easier to read.
-- peter
My problem with using a constructor-based approach is that the order
of the parameters is strict. This isn't. Mind you, not sure that I
like it ...
I see here two different requirements: There are cases where a constructor requires a series of parameterst o properly construct and object instance, assign some initial properties and do some initial work. In this case the constructor knows (by the sequence of code in the constructor) when those initial properties as set and when it can do the initial work.
When using an empty constructor and then either setting a hand full of properties or doing fluent method calls, the order is random, it may be easier to read, but nobody knows, when you are done setting the initial proeperies and when the initial work can start.
.NET Controls solve this using BeginInit() and EndInit() methods (support for transacted initialization). But that is a manual task and can be easily forgotten (listen, Dr. Thomas) without a code generator (like the .NET Visual Designer).
In cases when you have a constructor that requires that many parameters that you can get confused by their order, I'd rather pass a single parameter object to the constructor and take the properties of the parameter objects as the input.
I see here two different requirements: There are cases where a constructor
requires a series of parameterst o properly construct and object instance,
assign some initial properties and do some initial work. In this case the
constructor knows (by the sequence of code in the constructor) when those
initial properties as set and when it can do the initial work.
To add to this, I see constructor arguments as being mandatory arguments (or reasonably so); state added via a method/property (whether using a fluent interface or other) is not (ie it is optional data).
-- peter
I confess that I find it a bit of a cheat and obscure.
One can get around the constructor parameter order by using a parameter object with the values. There are a lot of places one would/should have one anyway.