1

I know they can be more natural to write, but I'm finding it conceptually hard to 'read' fluent API method chains. There's so much going on in a couple of lines.

As an example from the Nest ElasticSearch API:

 var result = Client.Search<AutoSuggestItem>(s => s
    .Source(sf => sf
        .Includes(f => f
            .Field(ff => ff.Actual)
            .Field(ff => ff.Text)
            .Field(ff => ff.TextSearch)
        )
    )
    .Suggest(su => su
        .Completion("suggestions", c => c
            .Prefix(SearchText)
            .Field(p => p.Suggest)
        )
    )

);

Any advice on this, as well as debugging it?

4

I've used both good and bad fluent APIs. I find that simple APIs that help you assemble configuration in logical chunks are very helpful. However, APIs where you have lambda callbacks, etc. are very difficult to follow because of the nested context.

My response to taming a bad fluent API is to do the following:

  • Indentation (this is a bare minimum)
  • Prepare lambdas outside the context of the larger call, or if the bit is shared between different methods, create a method to fill in the gaps.

This at least allows me to build up an understanding of the chunks used in the larger request, and then when they are incorporated I can understand how they relate to each other.

An example where an API implementer listened to their users: To the ElasticSearch team's credit, they recognized that their NEST Fluent API sometimes prevented building queries dynamically. They also provided a way to assemble queries without the fluent API. This is the best of both worlds. You can use the fluent API when it makes sense, and avoid it when you need to.

  • What sorcery is this! NEST's fluent query API is exactly what I am dealing with. I will dig around for the other implementation. – Matt Evans Sep 21 '17 at 13:58
  • The started revamping things with the 2.x line, and now that ElasticSearch is at 5.0, there are two examples of how to do queries. – Berin Loritsch Sep 21 '17 at 18:27
  • Just have looked into Roslyn's Syntax Factory. I am done with Fluent. – Christian Gollhardt Oct 22 '17 at 6:57
2

Other than indenting your code in a way that makes it easier to parse for you (like keeping one call per line), I'm afraid there's not much else you can do.

As far as debugging is concerned, if it's a third party library I don't really see the problem, as it's going to be a black box for you. With proper indentation, the debugger will highlight one line at a time (with the obvious exception of long lambdas in things like LINQ's Select()).

If it's a library that you wrote, remember what Brian Kernighan said:

Everyone knows that debugging is twice as hard as writing a program in the first place. So if you're as clever as you can be when you write it, how will you ever debug it?

If your code is simple, stepping through a fluent API is really no different than debugging any old method (which a fluent API itself is in many cases entirely made of).

Me, I love a well-designed fluent API, so much so that I would probably have to look up LINQ's query syntax, as I very much prefer the method one.

Are there specific things you're having troubles with?

Not the answer you're looking for? Browse other questions tagged or ask your own question.