The Plain Old Function Call
by vvgomes
During a design storm session one of these days, we got into a discussion on alternative approaches for an api interface. The main point in debate was basically the level of simplicity of each solution.
# first idea
choose('color', ['red', 'black', 'green'], 'ie7')
#second idea
choose('color').from('red', 'black', 'green').ignore('ie7').any
To set the context, the intention behind the hypothetical example above is to randomly select one of the options ('red' or 'black' or 'green') for a given aspect of the application ('color') in order to perform some sort of A/B testing. Besides that, we also want to prevent this thing from running in some specific browsers ('ie7' in this example).
Conceptually, the main difference between the two ideas is that the first one is based on a plain old function call with explicit ordered arguments, while the second one uses objects and method chaining (AKA Fluent Interface).
For some teammates, the first idea is the simpler one. They believe that approach describes more explicitly the api usage and is less complex to implement, since less data structures and language resources are required. It’s just a plain old function call, there is no magic in there. they say.
On the other hand, there was another group which was supporting the second idea. Their central argument was about readability: It is simpler because it just reads better. Additionally, they believe it eliminates any ambiguos interpretation on the last parameter role as well as in the statement side effect.
Well, even though both sides have their valid points, they are not really talking about the same kind of simplicity. Of course the first approach is simpler to implement because its grammar is restricted to limited set of very simple rules. And everybody pretty much knows how a function works in programming.
But turns out the second approach can be simpler on maintenance, since it gives more information about what’s going on without exposing implementation details. Also it requires less mental mapping between the computational representation and the real world thing (it’s closer to the natural language).
Conclusion
Overall, if our goal is to get something working as fast as we can using a very simple approach to create stuff, investing in old-fashioned function calls works fine. However, if the intention is to build something that would be easier and faster to understand and, consequently, maintain, the fluent approach sounds better.
Lastly, there is an important implication in that decision we should consider: the monetary cost. The Software Engineer history has shown us that maintenance is the most expensive phase of the software life-cycle. And we all know that a given piece of code is usually read several times more than it is written. So, if the maintenance is the real bottleneck, it sounds smart to adopt an attitude towards simpler maintenance.

Great Post. One thing that I like to say is: “We don’t code to ourself, we code to our code’s clients.”
That means that readbility is gold!
And adding to what Roger said: “Don’t write code for the compilers/interpreters, write it for the humans.”
So a code easier to read and to maintain is preferable.
Well.. If it is for A/B testing I believe the problem will not exist anymore once you pick A or B, right?
I would definitely go for 1 :)
Actually, the real goal of the example is not finding the winner option, but giving the clients the ability to perform A/B tests whenever they want. Imagine such API as a gem which could be used by a variety of applications. How confortable would users be with each of the approaches? How likely would they be to choose a tool that looks like each of the cases?
I’ve posted a reply:
http://qblog.aaronsw.com/post/30628091215/the-simple-function-call
> (quote) Overall, if our goal is to get something working as fast as we can using a very simple approach to create stuff, investing in old-fashioned function calls works fine. However, if the intention is to build something that would be easier and faster to understand and, consequently, MAINTAIN, the fluent approach sounds better. (quote).
I agree that it is really nice to use a more readable API in a lot of cases… but I see it being seen as “too cool” for its own good these days, it leads to overuse of a good idea, fluent interfaces and DSLs are not a silver bullet for readability. Sometimes its usage will result in exactly the opposite of what is intended.
Sometimes we go so far out of our way to implement it that the cost outweights the benefits (unless we are using it a lot and pretty much never changing it).
Even disregarding the absurd amount of complexity that can be generated by more “natural” looking interfaces, sometimes they just look outrightly awkward… your own example illustrates that. Your fluent interface is hardly “fluent” in human sense. It might be fluent from a programmers perspective as in “I’m able to chain method calls and customise the behaviour of an operation to an arbitrary extent doing it a little bit at a time”- but that’s not a very human thought model.
I don’t mean to straw man (http://en.wikipedia.org/wiki/Straw_man) your argument with your inadequate (IMHO) example.
I do think that DSLs can help tremendously in expressiveness, but I would say that the vast majority of your code will be much better off without them. They might help express domain logic and concepts, but its cost and added complexity makes it not really useful most of the time.
A function call with a good name and very few (if you have more than 2, probably your model is not good) does the job much better than a forced chain of method calls (in your example, I would much rather work with the first line of code, than with the second). I see that DSLs tend to help more when you have a HIGHLY customisable process (with a ton of optional parameters and/or default behaviours) or configuration.
I bring this argument to another example: pick your favorite html abstraction (SLIM, HAML, ???), by the end of the day, when you’re writing it, you’re thinking of tags and classes and browser quirks (we are not past that quite yet) that it is extremely harmful to force your brain to concurrently operate in a slightly higher level of abstraction.
TL/DR: I agree that writing code for human beings is nice but vastly overused, to the point it can be harmful. Sometimes a function call is actually more readable and more easily understandable than a fancy construct, it all depends on which level of abstraction you’re operating at that point.