Home
About
Contact
Tuesday, September 02, 2008

As mentioned before, I created a small tool for sending out emails to our members in NNUG. When implementing tools like these I always make sure to experiment with new language features, patterns or similar. This time it was the fluent interface to be tested.

Recently there has been a lot of focus on Domain Specific Languages (DSL's). A Fluent Interface is a specific type of DSL. Martin Fowler and Eric Evans gave this DSL type its name in 2005 which you can read more about here.

To jump right into the usage of my interface here's how to send an email to one person from code:

EmailComponent email = Email
    .To("somebody@torresdal.net")
    .From("anybody@torresdal.net")
    .WithSubject("Anybody out there?")
    .Using.Body("Guess not...");
email.Send();

The above code is nice, but you can't really do anything useful with it. You can send emails from code, but I would rather use an email client for that :-) So lets make it a bit more interesting:

EmailComponent email = Email
    .ToAllIn("recipients.txt")
    .From("anybody@torresdal.net")
    .WithSubject("Anybody out there?")
    .Using.TxtBodyFromFile("someTxtFile.txt")
    .Using.HtmlBodyFromFile("someHtmlFile.html");
email.Send();

Now instead of specifying one single to address we point to a file where all the recipients are found. Also instead of the body text we use a text file and a html file to be used as the email body. In this way, when you send emails, people that can only receive plain text emails will get that, and the others will get the html version. This is done using the AlternateView class in .Net.

But there is more interesting stuff you can do:

EmailComponent email = Email
    .ToAllIn("recipients.txt")
    .From("anybody@torresdal.net")
    .WithSubject("Anybody out there?")
    .Using.TxtBodyFromFile("someTxtFile.txt")
    .Using.HtmlBodyFromFile("someHtmlFile.html")
    .PauseAfter.Every(30).EmailSent.For(20).Minutes;
email.Send();

In the last line we say: Pause after every 30 email sent for 20 minutes. So what would you use that for? If you send out 500 emails, your smtp server might not like you very much, so he/she just reject your request thinking you're a spammer. By splitting it up you still might be a spammer, but the smtp server won't know it.

There are many variants of the above line. Here's a few other examples:

.PauseAfter.Every(10).Minutes.For(1).Hour;
.PauseAfter.Every().Hour.For(2).Hours

How is this done you might ask? First of I read Anders Norås excellent article about fluent interfaces (Behind the scenes of the planning DSL) and Martin Fowler's articles from his coming book about DSL's to get a deeper understanding.

So in essence I've basically picked the right words (hopefully) for the method names and properties to build up an understandable sentence implemented by using Method Chaining. Here's what Martin Fowler says about method chaining:

Method Chaining is an idiom that acheives this through a sequence of modifier calls where each call returns the host object for further modification.

Implementing method chaining is quite simple illustrated by the code below:

public Email To(string emailAddress)
{
    _to = emailAddress;
    return this;
}

This is from my Email class of the fluent interface. See how it returns itself? This is so that you can do subsequent calls to the same class.

If you've been very observant you've seen that the To method returns an Email object, but the object type returned after the "sentence" is finished is an EmailComponent. As Anders accurately describe in his post this is done using an implicit user-defined type conversion operator in C#. It's actually not as difficult as it might sound :-) Check out Anders article for details.

Another good point made by Anders is writing this without "code by example" or TDD is almost impossible. Write your sentences first and then implement the code. Actually, for people trying to learn/master TDD an excellent way of practicing is writing a fluent interface!

Even though this was really cool (at least I think so), is it any useful? If you see where fluent interfaces are used today, they tend to be around configuration. Instead of hacking around in an xml file not really knowing when you miss type something, using a type safe fluent interface might be a good idea. Examples of this is Ninject, NHibernate and others. Is my Email client any good as a fluent interface? If you remove the PauseAfter functionality the answer is: not really. However, the PauseAfter thing actually adds some value to it all. There are other ways of solving that quite nice just using a plain API, but that's no fun is it?! :-)

.Net | CSharp | DSL | Patterns
Tuesday, September 02, 2008 7:57:23 PM (W. Europe Daylight Time, UTC+02:00)
RSS RSS - Comments Twitter LinkedIn
         
SEARCH
 
 
         
TOP POSTS
   
         
NAVIGATION
   
         
CATEGORIES
  .Net (42) Agile (22) Ajax (5) Architecture (3) Blogging (11) Books (1) BPEL (1) CloudComputing (3) CSharp (6) DasBlog (5) Database (2) DDD (1) Deployment (12) DSL (1) Events (26) ExtremeProgramming (3) Fun (5) Gadgets (3) IIS (6) Java (1) Linq (2) MemoryLeaks (5) Microsoft (35) NDC (2) NNUG (26) Other (8) Patterns (3) Performance (1) Scrum (13) Security (2) Silverlight (4) Software (18) TeamManagement (8) TechEd (7) Testing (4) Tools (20) TvGuide (1) Vista (15) VisualStudio (15) WCF (7) Web (12) Windows (6) WiX (6) Work (13) Workflow (3)  
         
ARCHIVE
   
         
BLOGROLL
   
         
ON THIS PAGE...
 
Fluent email interface