开发者

What should I consider when choosing between chainability and language constructs?

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.


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.


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.


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


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

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

etc.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜