Patterns: Fluent Interface - make your code easier to read

27. September 2007

I never heard of the Fluent Interface pattern until I saw Randy Patterson's blog post titled "How to design a Fluent Interface". When I first saw the title of the post I thought he was talking about design a user interface, but upon further inspection I found out that using the Fluent Interface pattern in your code will make it easier to read.

Randy posts an example of how to use the Fluent Interface pattern, but I thought I would also write up a short example. My example below shows how to implement a small class to generate Sql scripts using the Fluent Interface pattern.

Example Usage:

SQLQuery sql = new SQLQuery();
sql.Select(
"Id").Select("FirstName").Select("LastName").From("Person").Where("Id = 1").Where("FirstName = 'Chris'").OrderBy("LastName").OrderBy("FirstName");

/// Get the string representation of our Sql query
string strSqlString = sql.ToString();

Console.WriteLine(strSqlString);

Code for the SQLQuery class:

public class SQLQuery
{
private ArrayList _SelectItems = new ArrayList();
private ArrayList _WhereItems = new ArrayList();
private ArrayList _OrderByItems = new ArrayList();
private string _FromTable = null;

public SQLQuery Select(string select)
{
_SelectItems.Add(select);
return this;
}

public SQLQuery From(string from)
{
_FromTable = from;
return this;
}

public SQLQuery Where(string where)
{
_WhereItems.Add(where);
return this;
}

public SQLQuery OrderBy(string orderby)
{
_OrderByItems.Add(orderby);
return this;
}

public override string ToString()
{
StringBuilder sb = new StringBuilder();

sb.Append(
"SELECT ");
for(int i = 0; i < _SelectItems.Count; i++)
sb.Append(_SelectItems[i] + ((i == _SelectItems.Count - 1) ?
" " : ", "));

sb.Append(
"FROM ");
sb.Append(_FromTable);

sb.Append(
" WHERE ");
for(int i = 0; i < _WhereItems.Count; i++)
sb.Append(_WhereItems[i] + ((i == _WhereItems.Count - 1) ?
" " : " AND "));

sb.Append(
"ORDER BY ");
for(int i = 0; i < _OrderByItems.Count; i++)
sb.Append(_OrderByItems[i] + ((i == _OrderByItems.Count - 1) ?
" " : ", "));

return sb.ToString();
}
}

Conclusion

As you can see the Fluent Interface pattern is rather simple to implement and it can really make your code easier to read. 

 

General



Comments

New C# 3.0 and VB9 Language Feature: Object Initia
New C# 3.0 and VB9 Language Feature: Object Initia
9/28/2007 9:17:00 PM #
instead of:
   Person person = new Person();
   person.FirstName = "Scott";
   person.LastName = "Guthrie";
   person.Age = 32;
..a new feature called "object Initializers" will allow you re-write the above code like so:


  Person person = new Person { FirstName="Scott", LastName="Guthrie", Age=32 };


This making the Fluent Interface pattern obsolete.  In fact, some argue design patterns are merely missing language features:  c2.com/.../wiki
Anonymous
Anonymous
9/29/2007 7:39:00 AM #
"really make your code easier to read"
Really? Looks ugly to me. Almost like Hibernate.  
9/29/2007 3:40:00 PM #
I assume that you've used C# for your demonstration (pretty looks like Java at first sight ;o)). I'm not sure if C# supports something that's called 'varargs'  in Java, that is declaring a variable number of arguments that can be refered to like a simple array. With that 'tool' at your hand, you could make your interface more consice by allowing more than one argument (an arbitrary number) i.e. for your where clause:

sql.Select("Id","FirstName","LastName")...

using

public SQLQuery Select(string...selects)
{
  for( String select : selects )
    _SelectItems.Add(select);
  return this;
}

As said, i'm not sure if C# supports a concept like varargs. But if support is given, it would make your interface a little bit more compact and consice.

Greetings

Mario
Comments are closed