DSL vs. Fluent interface: Compare & Contrast

time to read 2 min | 295 words

Let us take a simple example, scheduling tasks, and see how we can demonstrate the difference between the two. From the perspective of the client, what do we want from a scheduling tasks?

  • Define named tasks
  • Define what happens when the task is executed
  • Define when a task should execute
  • Define conditions to execute the task
  • Define recurrence pattern

Now, let us look at the fluent interface for this:

new FluentTask("warn if website is not alive")
	.Every( TimeSpan.FromMinutes(3) )
	.StartingFrom( DateTime.Now )
	.When(delegate
	{
		return WebSite("http://example.org").IsAlive == false;
	})
	.Execute(delegate
	{
		Notify(“admin@example.org”, “server down!”);
	});

And contrast that with the DSL sample:

task "warn if website is not alive":
	every 3.Minutes
	starting now
	when WebSite("http://example.org").IsAlive is false
	then:
		notify "admin@example.org", "server down!"

The second version has far less line noise, it a lot more clearer, and allows me to grow my DSL as I get more information, without hitting the language limits.

It also brings to mind another issue, who define these tasks and when?

Most of the time, I use a DSL as a way to setup and configure a runtime engine. I might talk later about imperative vs. declarative DSL. I tend to write my DSL at a different time than the code.

In fact, if you have no need to ever do something externally, and a fluent interface manages to express the ideas that you have clearly enough, than you probably should just use that.

If you need to do things externally, than a DSL is the place to look for. In fact, if you feel the urge to put XML into place, as anything except strict data storage mechanism, that is a place to go with a DSL.