tags:

views:

57

answers:

4

I have tough time making this design decision.

I could go with traditional new language construct to initialize objects, and use them through variables, such as:

$o = new Object('arg');
$o->method();
$o->property = 'value';
$o->save();

Or I can choose factory pattern and aggressive chainability like as

Object::new('arg')->method()->setProperty('value')->save();

which would result in

  • less LOC to
    • read,
    • maintain,
    • refactor,
  • no need to name variables.

However, I'm not sure if this is an acceptable approach, and if I forgot to take something into account.

Please express your worries or agreement, and guidance as how I could make my decision.

A: 

why not have multiple constructors that take values for initialization. So you would have:

Object::new()
Object::new('arg1')
Object::new('arg1','arg2')

etc.

ennuikiller
This is not related.
pestaa
+1  A: 

I am a big fan of your 'chainable' design. This sort of design is sometimes called a Fluent Interface.

David Seiler
I'm glad you like it. Although, is there anything that could be mentioned beyond fanatism, please?
pestaa
I thought you summed up its benefits quite well: easier to read/maintain/refactor due to the lack of explicit local state and general shortness.
David Seiler
+2  A: 

I have mixed feelings on the recent Fluent Interface fad.

For me, fluent interfaces make sense when the overall method chain expresses a single concept from start to finish. For example:

var SuperLate = (new Coffee()).AddMocha().AddCream().Invert().Blend();

Each step needs the context of the chain to make sense and the order in which the methods in the chain are executed matters. If Blend() were called before Invert(), chaos would ensue.

In your example, there is little temporal coupling between the methods of your interface. Setting properties and executing methods should not be order dependent. I believe that introducing a fluent interface for routine method invocation and property manipulation only increases the complexity of the interface while giving the perception of temporal coupling.

In addition, adding a fluent interface increases the coupling between each method because they are now dependent on each other's return value. This coupling makes sense when each method expresses only part of an overall concept (like a step in making coffee), but can hinder future refactoring when each method stands alone.

While it may be more verbose, I would not recommend introducing a fluent interface for routine method invocation and property setting.

Ryan Michela
I may have not chosen the best routine names for this example, but I'd prefer configuration objects over multiple setter calls for instance. As you can see, the example also leads the object from initialization to saving. Is the order-independency that only bothers you?
pestaa
I'm more bothered by the scale of the construct. Most fluent interfaces I've seen make large constructs (an nHibernate mapping) out of small components. The small components don't really stand on their own. Configuring and saving an object is not a single construct. It is a series of discreet steps. That is why I don't feel a fluent interface is appropriate. This is however, just my opinion.
Ryan Michela
Too bad newer "OO" languages don't support the interactions that the original (Smalltalk) did. In Smalltalk it was a simple matter to send multiple messages to one object byt separating them with a semicolon. (Rectangle new) color: Red; addToCanvas: mainCanvas.
Joe Koberg
I agree that large constructs make code difficult to maintain in some edge cases, but I'm mainly planning to implement fluent interface in ORM and other basic set of objects, so it might speed up development. Thank you for your opposite opinion, though! +1
pestaa
+1  A: 

What's nice about the fluent interface is that the meat of the code isn't lost among extra syntactical plumbing making it easier to read. However it is a less familiar idiom than the line-by-line procedural approach, and not as general; not all code structures will be a good fit for this style, for example

if (something) $o->method();

won't translate as cleanly. So if such things are typical, it may not be a good fit.

Also consider the context of the other code that will surround it. If the code is going to mostly be these sort of boilerplate looking segments like

$o = new Object('arg');
$o->method();
$o->property = 'value';
$o->save();

then making them more succinct would surely be an improvement. But if such code will be lost among much other code in a different style, maybe not.

If it seem like it's probably a good idea, I'd say go for it. If it doesn't play out well, the small effort of switching back will be worth the learning experience.

Grumdrig
Trial and possibly a revertible error -- I like it.
pestaa