Partager via


An analogy: Good UIs and Fluent APIs

Background

A while back I was writing a web app to try the Entity Framework and MVC together.

I knew the pain points would probably be around Foreign Keys, or at least the lack of them in .NET 3.5 SP1 (FKs are now available by default in .NET 4.0).

So I started looking for opportunities to edit entities and their FKs, to investigate the expected pain.

The interesting thing is while I did this it all felt somewhat forced, and it started to dawn on me that in a good UI there are very few times that you want to select something from a drop down.

Usually good UIs are designed so that most things including FKs are established from Context. A good UI only asks you to provide the information it can't infer.

Take StackOverflow as an example. When you "Answer a question" you simply type your answer and submit.

But an Answer is more than just a long string, it has an author, a created time, and a Question.

The Question is probably modeled as an FK in the database, but you aren't asked to pick a question, you've already done that when you clicked on the Question to read the details.

Essentially you establish the parameters to the "CreateAnswer(...)" method as you browse.

Then I started to realize that Fluent APIs are all about the same thing. There are lots of interesting Fluent APIs in the .NET world now. Something like StructureMap is a good example. But in the interests of brevity here is a silly example of a Fluent style API just for context:

Query.Where("Age").LessThan(30).And("Salary").GreaterThan(50000);

As you see rather than forcing you to provide all the parameters in one go, Fluent APIs allow you build them slowly as you chain method calls with intellisense guiding you.

Insight?!

If you squint hard enough Intellisense is similar to a hyperlink, and the parameters to the function are similar to whatever a web form needs you to enter.

To illustrate this analogy we could describe the process of creating an Answer on StackOverflow like this:

StackOverflow.Logon("User","Password")
.ViewQuestion(2312)
.Answer("here is my answer");

Rather than like this:

StackOverflow.CreateAnswer("User",
"Password",
2312,
"here is my answer");

What do you think? Is this an interesting analogy?

All this is a little random I know, but hey, I wanted a change from writing EF tips!

Comments

  • Anonymous
    April 16, 2009
    PingBack from http://microsoft-sharepoint.simplynetdev.com/an-analogy-good-uis-and-fluent-apis/
  • Anonymous
    April 18, 2009
    Like you said, the thing they have in common is context.A good UI lets you navigate the data. Then when you are in context, it presents you with just the things you might like to do there.A fluent API returns an object from each method. That object presents only the methods that you might like to perform from that context.This would suggest that application-level menus are not a good UI, since they are not context sensitive. But the ribbon is.Perhaps this should encourage us to look at APIs differently. We shouldn't consider an object as a packet of data encapsulated behind all of the operations that can be performed on it. Instead, we should consider it as a point of view: a context from which the developer can branch off into a few different directions.Favor parameters over properties. Never return "void"; return "this" instead. Never return "null".
  • Anonymous
    April 19, 2009
    Fluent API is usually built on builder pattern in my experience. I do not have sufficient expertise to mention my thoughts about the UI portion of analogy.
  • Anonymous
    January 03, 2010
    Nice Insight. We see some of the best APIs using this approach, that we may not think of at first as fluent.  Linq is fluent. Moreover, we use DateTime daily, which is also fluent.var q2 = db.Employees   .Where(emp => emp.IsActive)   .Select(emp => new { emp.FirstName,emp.LastName});// DateTime is Fluent.DateTime dt = DateTime.Parse("1/1/10")   .AddDays(1)   .AddHours(1);Very powerful concepts. The ideas of "context", state, and workflow is evident. Linq is also composable, which gives it the real power.However, if we did deeper, does the power really come from it being Functional?  Each function (method), takes an input, does something with that input, and returns an output. In some cases, using stateful monad. State is passed down the pipeline.Another thing I have been wondering is this the answer to the shared state problem and concurrency we have all been looking for.  In the abstract, a program could start with Root object, and then be threading down a pipeline changing state locally (or not) at each function and only returning copies.In a distributed environment, we can Declare the pipeline:customer => "http://webservice".Add => Output1) Take a new customer created locally.2) Pass it a web service to add customer (locally or remotely).3) After web service returns new customer, display it.So we pass objects to functions and functions return new objects - locally or remotely. Async issues are just "hidden" in the pipeline processing so things like callbacks don't exist (also has a nice fit with Reactive programming (Rx)).  And because no shared state, we can go parallel (same manner as sql pipelines).  Question is, can we arch applications like this in general and what would that look like?  How to morph Haskel and Erlang into a nice .net language to do just this. Erik and others work on this as we speak.
  • Anonymous
    September 19, 2011
    Thanks.Here you find a fluent API for the SharePoint. FluentSP implements a modern fluent interface around the classic SharePoint 2010 API:www.parago.de/.../fluentsp-the-fluent-sharepoint-api