[
Lists Home |
Date Index |
Thread Index
]
Elliotte Rusty Harold <elharo@metalab.unc.edu> wrote:
| To some extent, this design choice [ie. method chaining] has been heavily
| influenced by my work with JavaBeans, where a method that doesn't return
| void isn't recognized as a setter method.
As I understand it, that's part of JavaBeans' "introspection" conventions
for black boxes. It's a good robustness principle when you're just
setting fields in objects, and need to know that's what you're doing.
| I'm not sure if that has any true relevance here, but it's definitely
| influenced me as to what feels right and what doesn't.
Perhaps some, but not much I think, because "setting fields in objects"
isn't what's really going on, except maybe as an implementation detail.
We're actually dealing with a tree by composition: most of the time we're
adding to or subtracting from collections - canonically, a hash for
attributes and an array for content - and thematically, operations on
collections are usually subject to repetition. That is, often you'll be
wanting to do the "same thing" a number of times, so it makes sense to get
mere language clutter out of the way for this. This is no big deal in
languages that support variable arglists - just pass the lot into one
function/method call, but Java doesn't even have that. It's in that
context that method chaining is often a good way to record the intent of
repetition where you'd like to have done it all at once but couldn't.
That's the stylistic difference between
foo.add( bar ) ;
foo.add( quux ) ;
and
foo.add( bar ).add( quux ) ;
That said, method-chaining should not be used routinely in places where
conventions to support it (such as returning "this") are not more or less
strictly observed. (At a minimum, the API docs should explain why the
return value is an object of the same class.)
| The other problem I have with the method chaining approach is that it
| too often leaves you without references to the objects you need. I
| don't find it actually hold together too well in practice.
There's no substitute for good planning! I dislike one shot locals - to
me they add cognitive clutter. So I want to defer setting the title and
filling in the body? No problem, I go
Etitle myTitle = hf.makeTitle( ) ; // save ref for reuse
Ebody myBody = hf.makeBody( ) ; // ditto
// I need to do something with the toplevel immediately, so make it now
Ehtml myHtml = // get the boiler plate out of the way
hf.makeHtml(
hf.makeHead( myTitle ) .add(
hf.makeLink( )
.withRel( "Stylesheet" )
.withHref( "/ss/style.css" ) // Uri made internally
.withType( "text/css" ))) .add(
myBody ) ;
// do the urgent thing ...
// do stuff with myBody, update myTitle, and finally pass myHtml ...
Also, the API should support xpath-like functionality to retrieve
references when needed
Elink myLink = (Elink) myHtml.select( "head/link" ) ;
or
Element[] myLinks = myHtml.match( "head/link" ) ;
which I think addresses the other issue worrying you.
| And my third problem is that I just think it looks too damn ugly! I
| can't read it. I can't follow it, even with good indenting.
Well, beauty in the eyes of and all that.
|