Fluent interface in Delphi

后端 未结 5 930
既然无缘
既然无缘 2021-01-30 17:25

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

5条回答
  •  鱼传尺愫
    2021-01-30 17:50

    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.]

提交回复
热议问题