What are the pros and cons in using fluent interfaces in Delphi?
Fluent interfaces are supposed to increase the readability, but I\'m a bit skeptical to have one
Everybody is just writing about negative issues so let's stress some positive issues. Errr, the only positive issue - less (in some cases much less) typing.
I wrote GpFluentXMLBuilder just because I hate typing tons of code while creating XML documents. Nothing more and nothing less.
The good point with fluent interfaces is that you don't have to use them in the fluent manner if you hate the idiom. They are completely usable in a traditional way.
EDIT: A point for the "shortness and readability" view.
I was debugging some old code and stumbled across this:
fdsUnreportedMessages.Add(CreateFluentXml
.UTF8
.AddChild('LogEntry')
.AddChild('Time', Now)
.AddSibling('Severity', msg.MsgID)
.AddSibling('Message', msg.MsgData.AsString)
.AsString);
I knew immediately what the code does. If, however, the code would look like this (and I'm not claiming that this even compiles, I just threw it together for demo):
var
xmlData: IXMLNode;
xmlDoc : IXMLDocument;
xmlKey : IXMLNode;
xmlRoot: IXMLNode;
xmlDoc := CreateXMLDoc;
xmlDoc.AppendChild(xmlDoc.CreateProcessingInstruction('xml',
'version="1.0" encoding="UTF-8"'));
xmlRoot := xmlDoc.CreateElement('LogEntry');
xmlDoc.AppendChild(xmlRoot);
xmlKey := xmlDoc.CreateElement('Time');
xmlDoc.AppendChild(xmlKey);
xmlData := xmlDoc.CreateTextNode(FormatDateTime(
'yyyy-mm-dd"T"hh":"mm":"ss.zzz', Now));
xmlKey.AppendChild(xmlData);
xmlKey := xmlDoc.CreateElement('Severity');
xmlDoc.AppendChild(xmlKey);
xmlData := xmlDoc.CreateTextNode(IntToStr(msg.MsgID));
xmlKey.AppendChild(xmlData);
xmlKey := xmlDoc.CreateElement('Message');
xmlDoc.AppendChild(xmlKey);
xmlData := xmlDoc.CreateTextNode(msg.MsgData.AsString);
xmlKey.AppendChild(xmlData);
fdsUnreportedMessages.Add(xmlKey.XML);
I would need quite some time (and a cup of coffee) to understand what it does.
EDIT2:
Eric Grange made a perfectly valid point in comments. In reality, one would use some XML wrapper and not DOM directly. For example, using OmniXMLUtils from the OmniXML package, the code would look like that:
var
xmlDoc: IXMLDocument;
xmlLog: IXMLNode;
xmlDoc := CreateXMLDoc;
xmlDoc.AppendChild(xmlDoc.CreateProcessingInstruction(
'xml', 'version="1.0" encoding="UTF-8"'));
xmlLog := EnsureNode(xmlDoc, 'LogEntry');
SetNodeTextDateTime(xmlLog, 'Time', Now);
SetNodeTextInt(xmlLog, 'Severity', msg.MsgID);
SetNodeText(xmlLog, 'Message', msg.MsgData.AsString);
fdsUnreportedMessages.Add(XMLSaveToString(xmlDoc));
Still, I prefer the fluent version. [And I never ever use code formatters.]