jsr339-experts@jax-rs-spec.java.net

[jsr339-experts] Re: HEADS-UP: Decide on fluent client API atributes: simplicity vs. consistency

From: Marek Potociar <marek.potociar_at_oracle.com>
Date: Fri, 26 Aug 2011 11:53:33 +0200

On 08/25/2011 10:27 PM, Bill Burke wrote:
>
>
> On 8/25/11 3:33 PM, Marek Potociar wrote:
>> On 08/25/2011 08:25 PM, Bill Burke wrote:
>>>
>>>
>>> On 8/25/11 12:49 PM, Markus KARG wrote:
>>>> While I understand Bill's concerns as a vendor, I need to say that I more care for preventing errors than for reducing
>>>> the number of classes in this case. As the user will only get in touch the methods, but not directly get in touch with
>>>> the classes (they do not care that the methods in turn create instances of different classes) the number of classes
>>>> should not become a problems for users.
>>>>
>>>
>>> This has nothing to do about being a vendor. Its about users being able to understand the API. I don't know where you
>>> got that idea from...
>>>
>>
>> I would side Markus here - understanding of a fluent API is not expected to be conveyed as a list of class and method
>> descriptions. It's like learning English from a dictionary without understanding the proper sentence structure. Fluent
>> API's are best learned by examples. Class hierarchy plays a marginal role when it comes to learning how to use a
>> *fluent* API.
>>
>
> You make it sound like I'm against a fluent API, I'm not. I just think you can be both fluent and readable, especially
> when the inconsistencies you've outlined are both edge cases, opinion-based inconsistencies, and something the user will
> never run into. I've also pointed out a few instances where your API is quite awkward to use.
>
> In English, there's many ways to structure a sentence to say the same thing. For example:
>
> Your API is like spaghetti to me.
> Your API, to me, is like spaghetti.
> Your API is, to me, like spaghetti.
> To me, your API is like spaghetti.
>
> Its all a matter of perspective. Same could be said for how one would like to build an HTTP request. But, saying that
> "understanding a fluent API is not expected to be conveyed as a list of...descriptions" is a huge cop-out, a lame excuse
> for a bad design. Especially when we're arguing about trivial differences in opinion that nobody really cares about
> outside of this list!
>
> Anyways, good luck, it's clear I'm not getting anywhere with these arguments, so I give up.
>

I'm not saying you are against fluent API. I am saying you don't have one. Your design is simple and allows for method
chaining, but it is not a fluent API at all, because a fluent API is more than just method chaining:

1. every method invoked as part of the truly fluent API leaves the fluent context in a consistent state. If I was
designing an Invocation/HttpRequest as a typical Java bean, I would identify two core pieces of information the class
MUST have in order to be publicly instantiated:

  - target URI
  - HTTP method

I would write a public constructor that takes the two arguments. I would not let external users construct an instance
with just the URI. That would produce an internally inconsistent object. I am saying, that your design fails here as it
allows construction of Invocation instances that are internally inconsistent. Despite the clean and simple class
hierarchy, the API suffers a critical OO design flaw.

2. Another aspect that makes API fluent is the automatic shift in fluent context with each method invoked in the chain.
IOW, if you use such API with IDE code completion, the IDE will offer you only semantically meaningful options. It
basically brings us back to #1: Fluent API would not offer you invoke() after you typed in client.target(...).request()
as it would know that in this context the invoke() method is not valid at all. I guess you may point out that my version
suffers from this too to some extent. I am not denying it, neither I think we can eliminate all inconsistencies. I am
just saying that we cannot set the consistency requirement to zero, the way you did and dismiss all inconsistencies as
equally trivial and unimportant issues. At very minimum, we need to address the issue described in #1.

Marek