Creating an API that is free

How can you create an API that is fluent in nature?

Is this used with extension methods?

+53
c # fluent
Oct 26 '09 at 0:56
source share
9 answers

This article explains this much better than I ever could.

EDIT, can't compress this in a comment ...

There are two sides to interfaces, implementation and use. There is more work on the creation, I agree with this, but the main advantages can be found on the side of use. Indeed, for me the main advantage of smooth interfaces is more natural, easier to remember and use, and why not, more aesthetic API. And maybe trying to compress the API in free form can lead to a better thought-out API?

As Martin Fowler says in an original article on smooth interfaces :

Perhaps the most important thing to notice about this style is that the intention is to do something along the lines of internal DomainSpecificLanguage. Indeed, this is why we chose the term “free” to describe it, in many respects the terms are synonyms. The APIs are primarily intended to be read and streamed. The price of this run is more effort, both in thinking and in the design of the API itself. the simple constructor API, setter and add methods are much easier to write. Arriving with a good fluency API requires a good thought.

As in most cases, APIs are created once and used over and over again, the extra effort may be worth it.

And verbose? I am all for verbosity if it serves the readability of the program.

+44
Oct 26 '09 at 1:00 a.m.
source share

MrBlah,

Although you can write extension methods to write a free interface, it's best to use a builder pattern. I am in the same boat as you, and I am trying to figure out some additional features of the free interface.

Below you will see an example of the code that I created in another thread

public class Coffee { private bool _cream; private int _ounces; public static Coffee Make { get { return new Coffee(); } } public Coffee WithCream() { _cream = true; return this; } public Coffee WithOuncesToServe(int ounces) { _ounces = ounces; return this; } } var myMorningCoffee = Coffee.Make.WithCream().WithOuncesToServe(16); 
+36
Nov 25 '09 at 6:28
source share

While many people make reference to Martin Fowler as a prominent representative in the current discussion of the API, his early design applications actually evolve around a chain of methods . Free APIs can be further developed into actual internal domain-specific languages . Here you can see an article explaining how the notation of BNF grammar can be manually converted to a "free API":

http://blog.jooq.org/2012/01/05/the-java-fluent-api-designer-crash-course/

He converts this grammar:

enter image description here

In this Java API:

 // Initial interface, entry point of the DSL interface Start { End singleWord(); End parameterisedWord(String parameter); Intermediate1 word1(); Intermediate2 word2(); Intermediate3 word3(); } // Terminating interface, might also contain methods like execute(); interface End { void end(); } // Intermediate DSL "step" extending the interface that is returned // by optionalWord(), to make that method "optional" interface Intermediate1 extends End { End optionalWord(); } // Intermediate DSL "step" providing several choices (similar to Start) interface Intermediate2 { End wordChoiceA(); End wordChoiceB(); } // Intermediate interface returning itself on word3(), in order to allow // for repetitions. Repetitions can be ended any time because this // interface extends End interface Intermediate3 extends End { Intermediate3 word3(); } 

Java and C # are somewhat similar, the example is certainly translated into your use case. The aforementioned technique has been used to a large extent in jOOQ , a fluent API / internal domain language that simulates the SQL language in Java

+20
Sep 09 '13 at 6:12
source share

This is a very old question, and this answer should be a comment rather than an answer, but I think this is a topic worth continuing to talk about, and this answer is too long to be a comment.

The initial “fluency” thinking seemed to be mainly about adding strength and flexibility (a chain of methods, etc.) to objects, making the code more understandable.

for example

 Company a = new Company("Calamaz Holding Corp"); Person p = new Person("Clapper", 113, 24, "Frank"); Company c = new Company(a, 'Floridex', p, 1973); 

less fluent than

 Company c = new Company().Set .Name("Floridex"); .Manager( new Person().Set.FirstName("Frank").LastName("Clapper").Awards(24) ) .YearFounded(1973) .ParentCompany( new Company().Set.Name("Calamaz Holding Corp") ) ; 

But for me, the later version is actually not more powerful or flexible than

 Company c = new Company(){ Name = "Floridex", Manager = new Person(){ FirstName="Frank", LastName="Clapper", Awards=24 }, YearFounded = 1973, ParentCompany = new Company(){ Name="Calamaz Holding Corp." } }; 

..in fact, I would call this latest version easier to create, read and maintain than the previous one, and I would say that it requires significantly less luggage behind the scenes. Which is important to me for at least two reasons:

1 - The cost associated with creating and maintaining layers of objects (regardless of who does it) is as real, relevant and important as the costs associated with creating and maintaining a code that consumes them.

2 - Code overlay built into object layers creates as many (if not more) problems as code swelling in code that consumes these objects.

Using the latest version means that you can add a (potentially useful) property to a company class simply by adding one, very simple line of code.

Not to say that I do not feel that there is no place for a chain of methods. I really like being able to do things like (in JavaScript)

 var _this = this; Ajax.Call({ url: '/service/getproduct', parameters: {productId: productId}, ) .Done( function(product){ _this.showProduct(product); } ) .Fail( function(error){ _this.presentError(error); } ); 

.. where (in the hypothetical case that I present) Done and Fail were additions to the original Ajax object and were added without changing any source Ajax object code or any existing code that made use of the original Ajax object and without creating disposable things, which were exceptions to the general organization of the code.

So, I definitely found value when creating a subset of the functions of the object that returns the 'this' object. In fact, whenever I have a function that would otherwise return a void, I believe that it returns this.

But I have not yet found significant value when adding a "free interface" (.eg "Set") to the object, although theoretically it seems that there may be some kind of organization similar to the namespace, which may arise from the practice of this, which may be appropriate . ("Set" may not be particularly valuable, but "Command", "Query" and "Transfer" can, if it helps to organize things, alleviate and minimize the impact of additions and changes.) One of the potential benefits of this practice, depending on As this was done, there could be an improvement in the typical level of the encoder and attention to security levels - the lack of which undoubtedly caused a large amount of sadness.

+9
Sep 25 '13 at 22:33
source share

KISS: Keep it just stupid.

Free design is one of the principles of aesthetic design used in the API. Your methodology that you use in your API may change a little, but it’s usually best to stay consistent.

Even if you think that "everyone can use this API because it uses all the different types of methodology." In truth, the user will begin to feel lost, because you are constantly changing the structure / structure of the API data to a new design principle or naming convention.

If you want to change halfway to another design principle, for example .. Convert from error codes to exception handling, because there are some higher command powers. That would be stupid and usually the tail would hurt. It’s better to stay on course and add functionality that your customers can use and sell, rather than force them to re-write and rediscover all their problems.

Following the above, you can see that writing the Fluent API is more than eye-catching. There is a psychological and aesthetic choice that needs to be made before you start writing, and even then feeling, need and desire to meet the requirements of clients and remain consistent is the most difficult.

+6
Oct 26 '09 at 1:44
source share

What is a free API?

Wikipedia defines them here http://en.wikipedia.org/wiki/Fluent_interface

Why not use a free interface

I would suggest not introducing a traditional free interface, as it increases the amount of code you need to write, complicates your code and just adds an unnecessary template.

Another option, do nothing!

Do not implement anything. Do not provide “simple” constructors for setting properties and do not provide a smart interface to help your client. Allow the client to set properties as usual. In .Net C # or VB, this can be as simple as using object initializers .

 Car myCar = new Car { Name = "Chevrolet Corvette", Color = Color.Yellow }; 

This way you do not need to create any smart interface in your code, and it is very readable.

If you have very complex sets of properties that need to be set or set in a specific order, then use a separate configuration object and pass it to the class through a separate property.

 CarConfig conf = new CarConfig { Color = Color.Yellow, Fabric = Fabric.Leather }; Car myCar = new Car { Config = conf }; 
+5
Oct 26 '09 at 9:57
source share

With a white API:

 myCar.SetColor(Color.Blue).SetName("Aston Martin"); 

Watch this video http://www.viddler.com/explore/dcazzulino/videos/8/

+1
Feb 01 '10 at 19:01
source share

Writing a free API is difficult, so I wrote Diezel , which is a Fluent API generator for Java. It generates an API with interfaces (or a course):

  • control the calling flow
  • catch common types (e.g. guice one)

It also generates implementations.

This is the maven plugin.

+1
Dec 17 '11 at 10:16
source share

No and yes. The basics are a good interface or interfaces for the types you want to drive freely. Libraries with extension methods can extend this behavior and return an interface. Extension methods provide others with the opportunity to extend your free API with more methods.

A good smooth design can be difficult and requires a fairly long trial and error period to completely outline the main building blocks. Just a free API to configure or configure is not so difficult.

Learning how to create a free API does this by looking at existing APIs. Compare FluentNHibernate with the flowing .NET APIs or the free ICriteria interfaces. Many configuration APIs are also designed seamlessly.

0
Oct 26 '09 at 1:03
source share



All Articles