Site Archive (Complete)
Architecture Blog: A&D 2007 : Building DSLs in Static and Dynamic Languages (Neal Ford)
Architecture & Design
PATTERN LANGUAGE

Modeling, Managing, Making it Right.

by Jonathan Erickson
IF YOU BUILD IT

... Will they Come?

by Arnon Rotem-Gal-Oz
August 30, 2007

A&D 2007 : Building DSLs in Static and Dynamic Languages (Neal Ford)

Another great presentation at Dr. Dobb's Architecture & Design World was Neal Ford's presentation on Domain Specific Languages (DSLs). As the title suggests, Neal gave examples both in static languages (Java) and Dynamic ones (Groovy, Ruby).

One interesting observation Neal made was that humans tend to create DSLs in real life whenever they (okay, "we" :)) have any non-trivial interaction or behavior. Neal gave sevaral examples such as the Starbuck's order taking ("Venti Iced Decaf with whip..."), musicians, and a few others.

The next important point was contrasting ("classic") APIs and DSLs. The main difference is that the context is implicit and not repeated.

A key technique for building DSLs Neal mentioned was Fluent Interfaces. Fluent Interfaces means modeling the API so that lines of code are readable English-like sentences. The fluency comes from the easier readability by the interface user.

Fluent Interfaces, now that's a novel idea -- what would a fluent interface look like, hmm, wait, I have an idea. Here are three samples that come to mind:

DIVIDE x BY z GIVING y ROUNDED

INSPECT data REPLACING ALL "foo" BY "bar

READ someFile AT END SET eof TO TRUE


If you haven't guessed, the statements above are in ...Cobol (by the way pardon the caps that's Cobol conventions..)

So okay, it isn't a new idea, but it is interesting to see it is making a comeback. Anyway one area where we see a lot of fluent interfaces emerging is configuration (mainly as an alternative to those lengthy XML files).

For instance, the following is an excerpt of configuring Restlet components (taken from my Edge Component pattern paper):

Builders.buildContainer()

            .addServer(Protocol.HTTP, portNumeber)

            .attachLog("Log Entry")

            .attachStatus(true, "webmaster@mysite.org", "http://www.mysite.org")

            .attachHost(portNumber)

            .attachRouter("/orders/[+")

            .attach("/getAll$", getAllRestlet).owner().start();

            .attach("/getLast$", getLastOrderRestlet).owner().start();

Note that this example also uses another fluent interface/DSL technique which is method chaining.

Dynamic languages make it even easier to write DSLs since they provide a lot of extension capabilities (see my previous post on OCP in Ruby), are less strict about types, allow reopening classes, etc.

One example of a Ruby DSL is RSpec which is a framework to support Behavior Driven Development (BDD) in Ruby. The example below shows an excerpt for defining specifications for an eight-ball game.

require 'eight_ball'



describe Eight_ball do

    before(:each) do

        @eight_ball=Eight_ball.new

    end
    .

    .

    .

    it "should lose if 8-ball sinked in pocket other than called" do

        [1,2,3,4,5,6,7].each ( | val | @eight_ball.sink(:player =>"Player1", :Ball=> val)

        @eight_ball.call(:player => "Player1", :pocket => :upper_left)

        @eight_ball.sink(:player => "Player1", :Ball => 8, :pocket =>:middle_left)

        @eight_ball.game_status.should == :ended

        @eight_ball.player_status("Player1").should == :lost

    end

end

 

By the way, Joe Ocampo built a very nice port for rbehave (another Ruby BDD framework) to .NET 3.5 by extending NUnit which has a very Ruby-like syntax.

Anyway, the DSLs demonstrated by Neal provide a very good example of the difference between dreaming big and actually doing stuff in the small. The counter example for that are "Software Factories". As I wrote here about a year and half ago:

Software Factories is not a new idea; see for example "Software Reuse: From Library to Factory" by M. L. Griss (published in 1993(!)) which talks about "Software Factories" and "Domain Specific kits": components, frameworks, glue languages etc.The current Microsoft incarnation of Software Factories takes a similar approach focusing on Domain Specific Languages, Frameworks but also adding important aspects like multiple viewpoints, patterns and designers. The idea is that building on modern technologies, as well as learning from the mistakes from sister approaches to code generation (OMG's MDA, in case you are wondering) will enable us to build something that is useable.

Microsoft seems to be taking some steps in the right direction (GAT is probablythe best example). Nevertheless there is still a long way to go before we can realize the dream of "factories" for vertical applications.

Unlike small code based DSLs, the modeling based approaches of software factories, MDA etc. aim too high and thus provide much less value or suffer too much from the generation gap (the code generated is too generalized or far off from the actual need of the solution). Another problem with software factories/ MDA DSLs is the modeling (i.e.,diagrams) -- they say a picture is worth a thousand words. This is true if you treat models as sketches you can raise the level of abstraction by as much as you want and convey ideas with less clutter. However when you need to make the model very specific so it would allow code generation -- you get to a stage where it is more convenient to do it in code and rely on generated or pre-built DSL or framework

Lastly you can download Neal's presentation (in PDF form) from his site.


Posted by Arnon Rotem-Gal-Oz at 03:42 PM  Permalink




 
INFO-LINK


Related Sites: DotNetJunkies, SD Expo, SqlJunkies