A recent post by Primoz Gabrijelcic about Fluent XML has turned on interest for fluent interfaces in Delphi. What is a fluent interface or fluent programming styles? It has many sides, but one of the ideas is to let methods return the object they are applied to, so that the next method call can be chained to th first one. The only example in Delphi's native libraries is in the TStringBuilder class. With this class you can write (using a traditional approach):
sBuilder1.Append('one');
sBuilder1.Append('two');
Using the fluent interface you can write (instead):
sBuilder1.Append('one').Append('two');
Of course you might still want to have the two Append calls on two separate lines, but without having to repeat the name of the objects they are applied to. I had a long discussion (with other demos) on this topic in my post "Static Internal Dsl in Delphi", back in April 2008.
But if you want to see a really nice implementation of the idea, you can follow the link to the Fluent XML article, which applies the same principle to a situation in which alternative appraoches are not as nice. I like Primoz appraoch of combining subnodes and attributes in an XML building class, I liek it really very much. The only element I don't like is the use of navigational methods within the class. I'd rather be able to have an AddChildren method to which you can pass multiple nodes, but being in a class all day today (and tomorrow) and spedning the evening at the Delphi 2009 Productivity event in Chicago (which is going on while I'm typing this) I had no time for experiments. Primoz has made the full code available in a second post, and I'll download his code ASAP and see what I can come up with. But kudos to him for his nice fluent interface and a nice appraoch for working with XML (something I happen to use a lot).
Time to get back to hear Anders, now...




Fluent Interfaces in Delphi
Or alternatively you could write: with sBuilder1 do begin Append('one'); Append('two'); end; ;) Which has the added advantage of not building up a huge call hierarchy to be unravelled if something goes wrong in one of your calls, and the debugger dumping you back on a single statement spanning (potentially) dozens of lines of code with no indication of which /part/ of that line is directly responsible. I don't understand why this technique gets a "warm fuzzy" name ("Fluent") when "With" receives so much disdain. They achieve the same thing. (With isn't without it's problems - no argument on that score, but this so called "Fluent" API is also far from perfect, imho) It's another one of those things that I can understand why it appeals to the lazy part of all of us, but I wouldn't want to live with code written that way for any length of time. A little extra time spent creating code is insignificant (in the kinds of apps I work on) compared to the length of time that the code will spend (and have spent on it) in maintenance. For disposable code (quick, use-and-forget utilities etc), the equation balances out differently of course.Comment by Jolyon Smith on April 3, 06:58