I'm coming down with a serious case of the DSLs!

Published 04 July 07 08:28 PM | andersnoras 

Back in May chromatic published a tongue-in-cheek checklist to determine whether your code is a DSL or an API. Regular readers know that I've done quite a bit of fooling around with various embedded DSLs in Java and I assure you that getting serious with embedded DSLs is contagious. Check out this snippet from a calendar integration framework I've been working on for the last few days.

ToDo planningTask =
Plan.ToDo("Plan project X").
StartingNow.
MustBeCompletedBy("2007.08.17").
ClassifyAs("Public");
planningTask.Save();

Event planningMeeting =
Plan.Event("Project planning meeting").
RelatedTo(planningTask).
WithPriority(1).
At("Head office").
OrganizedBy("jane@megacorp.com", "Jane Doe").
StartingAt("12:00").Lasting(45).Minutes.
Attendants(
"peter@megacorp.com",
"paul@megacorp.com",
"mary@contractor.com").AreRequired.
Attendant("john@megacorp.com").IsOptional.
Resource("Projector").IsRequired.
ClassifyAs("Public").
CategorizeAs("Businees", "Development").
Recurring.Until(2008).EverySingle.Week.On(Day.Thursday).
Except.Each.Year.In(Month.July | Month.August);

planningMeeting.SendInvitations();

So is it a DSL or API? Lets take chromatics test.

1. Have you ever programmed in a language other than Ruby? (PHP and HTML don’t count.) If not, it’s a DSL.

Yes, the code is C# so I've done that.

2. Is the defining syntactic feature that you’ve cleverly left the parentheses off of a list of function arguments? If so, it’s a DSL.

Nope, can't be done in C#.

3. Is the code primarily a list of key-value pairs? Welcome to DSL Town, population you!

No. This is strongly typed.

4. Does the code require the liberal use of eval() or equivalent? DSL, yay!

To some extent. For instance you can write "12:00" to specify a TimeSpan of twelve hours, so this relies on some parsing. Of course you can supply a real TimeSpan if you're iffy.

5. Have you ever used the phrase “… and it reads just like English!” in seriousness? You’d better get to the hospital; you’re coming down with a case of the DSLs!

Check. I wrote this phrase in my JavaZone abstract. I actually tested this snippet on my computer illiterate girlfriend and she could make sense of it.

6. Are there colons on the front of otherwise-normal English nouns? Did it hurt when your DSL fell down from heaven?

7. Is your code full of language-specific idioms, such as the placement of curly braces and the pipe characters? Smells like a DSL in here!

Oh yes! Not colons but all sorts of other punctuation characters. Didn't feel all that bad, but I must admit that things like..

Recur.Times(20).Every(10).Week.On(Day.Tuesday & Day.Thursday);

...looks a little odd. (It should read "Recur 20 times on Tuesday and Thursday every 10th week")

8. Are examples of the code in question pervasive throughout your entire project rather than localized to particular sections in terms of encapsulation? Pardon me, I think you have a little DSL on you.

No. The DSL builds on top of a vanilla API which works like this:

Event @event = new Event (
new Organizer(new UriParameter("mailto:jsmith@host1.com"),
new LanguageParameter(CultureInfo.CurrentCulture),
new CommonNameParamter("JohnSmith"),
new DirectoryParameter("ldap://host.com:6666/o=3DDC%20Associates,c=3DUS??(cn=3DJohn%20Smith)"),
new SentByParameter("MAILTO:jsmith@host1.com"),
new ExtensionParameter("Extension1", "Some value"),
new ExtensionParameter("Extension2", "Some other value")
),
new Timestamp(1997, 9, 1, 13, 0, 0, new ExtensionParameter("Hello", "world...")),
new StartTime(
new DateTime(1997, 9, 3, 16, 30, 0, DateTimeKind.Utc),
new TimeZoneIdentifier(TimeZone.CurrentTimeZone)),
new EndTime(new DateTime(1997, 9, 3, 19, 0, 0, DateTimeKind.Utc),
new TimeZoneIdentifier(TimeZone.CurrentTimeZone),
new ExtensionParameter("Stuff", "More stuff")),
new Summary("Annual \nEmployee\n \\Review",
new LanguageParameter(CultureInfo.CreateSpecificCulture("en-US")),
new AlternativeTextRepresentationParameter(new Uri("http://www.host1.com")),
new ExtensionParameter("Expand", "Your mind")
),
new Classification(Classification.Private, new ExtensionParameter("This", "That")),
new Categories(new string[] {"Business", "HR"}, new LanguageParameter("sv"))
);

9. Did you build your own parser and interpreter? Haha… oh wait, that might really be a DSL.

No, it's plain old C#.

10. Did you merely choose names for identifiers that match the language of the problem domain? Sorry buddy, that’s just an API. Try again next time!

Sort of. The identifiers relate to the problem domain, but there is quite a lot of syntactic sugar to make the language more humane. For an example, consider the Attendant and Attendants methods of the event planning DSL. These do exactly the same thing but they have different signatures to make the language read better.

IAttendantInfo Attendant(string attendant);
IAttendantsInfo Attendants(params string[] attendants);

 The only difference between the IAttendantInfo and the IAttendantsInfo interface is that the first has singular naming of its members while the other has plural naming.

So is it a DSL or is it just an API? It is both. And I believe that developing an API and a DSL to uses that API is the best way to go. This keeps things from getting tangled up in each other. So which would you rather use the DSL or the API?

Update: Rather than reading chromatic's post you should listen to it. It makes it even more funny when a really dry computerized voice reads out the ten checkpoints.

Filed under: , ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# Jeremy D. Miller -- The Shade Tree Developer said on July 6, 2007 9:49 AM:

Start with http://andersnoras.com/blogs/anoras/archive/2007/07/04/i-m-coming-down-with-a-serious-case

# Anders Norås' Blog said on July 10, 2007 7:54 AM:

Last week I blogged about an embedded DSL for creating different calendar components like events and

# Sadek Drobi said on July 12, 2007 2:15 PM:

Well, Fluent Interface is closer to API than to a Dsl, what makes this API good is that it is Domain Driven. A good thing worth noting here is that C# 3.0 offers some interesting syntactic features like Extension methods that makes it easier to implement fluent interfaces. I wrote twice about extension methods

http://sadekdrobi.com/2007/01/07/obsev-fluentinterface-and-c-30-extension-methods-the-flexibility-of-dynamic-typing-with-the-powerfull-autocompletion/

and

http://sadekdrobi.com/2007/02/25/obsev-implementing-domain-friendly-predicates-like-specifications-with-c-30-expression-trees-2/

But I guess there is something that you told implicitly, and i would like to make it explicit. Fluent APIs, especially in a statically typed language, do NOT replace DSL. I prefer External DSLS, that are not constrained by any programming language. They should be English, just text in plain English. Like what i tried to explain here

http://sadekdrobi.com/2007/04/08/draft-obsev-patterns-of-domain-specific-languages/

# TrackBack said on July 13, 2007 2:35 AM:
Anders Norås has written two interesting articles on writing internal DSLs in C#.
# Anders Norås' Blog said on July 15, 2007 3:11 PM:

My latest posts on DSLs caused a bit of a stir around the blogosphere. Some of of the more constructive

# am said on July 17, 2007 10:39 AM:

I think you missed the point about key/value pairs. In Smalltalk parameters are passed as key/value pairs. Something like:

#MyClass asClass

 withInstanceVariables: '()'

 withClassVariables: '()'

 withPoolDictonaries: '()'

(or something similar.. I don't remember the exact methods/mechanisms)

Parameters are passed as key/value pairs. The syntax equivalent C#/Java/C++ is:

"MyClass".asClass().

 .withInstanceVariables("()")

 .withClassVariable("()")

 .withPoolDictonaries("()")

(of course none of these languages support doing this.. but I think you get the idea)

Sounds like the Ruby/Java/C# people are starting to rediscover Smalltalk. :)

# andersnoras said on July 17, 2007 1:57 PM:

@am;

You're right, I didn't make that association, but I must admit Smalltalk's message passing can be handy for crafting embedded DSLs. I don't "speak" the language that well, but I guess we could have done something it.

# Steve Freeman said on July 18, 2007 7:19 PM:

Actually, Smalltalk was a strong influence on jMock which was Fluent before the term was coined. When we first presented it, we had a cute demo where we turned off all the punctuation in the IDE and the code turned into Smalltalk.

For more background, read our OOPLSA paper.

http://www.mockobjects.com/files/evolving_an_edsl.ooplsa2006.pdf

# Software Architect’s Site » Blog Archive » DslReadings said on September 18, 2007 4:38 AM:

PingBack from http://projects.akela.ro/portal/architectsblog/?p=122

# Anders Norås' Blog said on January 30, 2008 12:52 PM:

Today it is exactly one year since I pick up on blogging after a long break. To celebrate, I’ll

Leave a Comment

(required) 
(optional)
(required) 
Enter the code you see below