InfoQ

News

What's a Ruby DSL and what isn't?

Posted by Werner Schuster on Jun 15, 2007 07:00 PM

Community
Ruby
Topics
Hype,
Domain Specific Languages,
Programming
Tags
Metaprogramming,
Language Features
The term Domain Specific Language (DSL) has become very popular in the Ruby space. One popular example is the Make replacement Rake, particularly after an article by Martin Fowler  about it. The term DSL is also used to describe some of the concepts in ActiveRecord, which is part of Ruby on Rails.

The concept of a DSL is actually unrelated to Ruby, and has been around for a long time. It's generally used to describe a language that has constructs suited for expressing concepts of a particular domain. The build tool Make, for instance, has a language that allows to declaratively define build targets, how to build them and dependencies between them. Then there is the concept of an internal DSL, which uses the syntax of an exіsting language, a host language, such as Ruby. The means of the language are used to build constructs resembling a distinct language. The, already mentioned, Rake uses this to make code like this possible:
task :codeGen do        
# do the code generation
end
As can be seen, the host language must be quite flexible to allow the DSL to have a distinct look.

Recently, however, the term DSL seems to have become overused, causing it to become vague. It seems that omitting parentheses from function calls already qualifies a piece of code to be labeled a DSL. O'Reilly blogger chromatic came up with  a tongue-in-cheek checklist for deciding if a piece of code is a DSL, or at least when it's labeled as one. Here a sample:
1. Have you ever programmed in a language other than Ruby? (PHP and HTML don’t count.) If not, it’s a DSL.
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.
3. Is the code primarily a list of key-value pairs? Welcome to DSL Town, population you!
#5 on chromatic's list is particularly telling:
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!
This is a popular argument for creating DSLs: they allow to write code that is easy to read and understand and doesn't hide its meaning behind language constructs such as for loops, conditionals, etċ. However, David A. Black offers another view of this:
This:

with Employee "123-45-6789" do
 dock_salary 1000
 warn_about :misconduct
end

is not a domain specific language. It is, rather, domain specific language. Note the lack of the “a”. It’s domain specific, and it uses language-like constructs. But it isn’t a language. It’s Ruby, using expressive method names and cushy semantics and therefore facilitating the use of domain specific idioms.
Using a domain specific vocabulary for naming code elements isn't a new concept, instead it should be an obvious choice for a designer.

So, is the term DSL bad or misleading? Not necessarily. Smalltalk developer Blaine Buxton shares his view:
I've always wondered what the big deal with DSLs was. Now, i'm not saying they are bad quite the contrary.But, I believe a DSL is a healthy bi-product of a good object-oriented design. So, I was a little annoyed with all of the talk and the tricks. I kept thingking to myself, "But, if you did a good design, you would have this!"

But, I should really be kicking myself. I should be glad that good design is back in vogue. and you know what? I am. I'm not annoyed any long and I relish all of this new talk on DSLs. I even feel guilty. You see, DSLs have always been part of the Smalltalk farbic. It's natural to us because it's the way we have learned to code. I remember having the mantra "Code should read like a conversation" shoved down my throat until it became second nature. The cool thing is that there is a whole new generation finding out about this and doing it.
Languages with syntax that can be twisted/bent to allow for more concise code are useful, but good design still depends on the developer.

There is another side to this. Some DSLs make use of Ruby constructs and corner cases of Ruby syntax. While this allows the developer to achieve a certain look, this doesn't mean that this is a good design. After all, the fact that code is written once, but read and modified much more often, is certainly still true.

A recent article on Urban Honking started of a debate about this. The article explains how the HTML parser library Hpricot makes this code possible:
Hpricot(my_document) 
Basically, there's a function called Hpricot which creates a new object of the class Hpricot and parses my_document.  Smalltalk blogger James Robertson, however, takes issue with that:
Urban Honking goes to great pains to explain why using syntax tricks in Ruby to get to something like this: Hpricot(my_document) Is a good thing. Here's a question - if you stumbled on that in code, would you have any idea what it did?
After explaining how to improve the code, he continues:
I've out-clevered myself in Smalltalk many times; it's never a good idea.
This view is also backed by Stuart Halloway:
If you are going to bend a language's idiomatic usage, you should have a compelling reason, and I share James' view that this example is not compelling.
He goes on to give an interesting overview of the many different solutions to API design, and how to design an API to make it possible to write expressive code with it.

What is your opinion? Where do you draw the line between good API design, that makes code easy to read, and using tricks that save a few key strokes but make code maintenance difficult? Are there ways to check that you've strayed from good design into the realm of hacking and clever syntax tricks?

10 comments

Reply

Huzzah! by Sam Smoot Posted Jun 15, 2007 10:24 PM
Great Article........and I agree..... by Ben Hughes Posted Jun 16, 2007 2:21 AM
DSLs? by Aaron Erickson Posted Jun 16, 2007 2:15 PM
Re: DSLs? by Werner Schuster Posted Jun 18, 2007 6:37 AM
Re: DSLs? by Peter Bell Posted Jun 18, 2007 6:42 AM
Re: DSLs? by Peter Bell Posted Jun 18, 2007 3:20 PM
Motives by Daniel Berger Posted Jun 19, 2007 8:52 PM
Re: Motives by brian d foy Posted Jul 23, 2007 9:44 AM
Re: Motives by Daniel Berger Posted Feb 20, 2008 10:02 PM
Re: Motives by berkay NiQuiL Posted Jun 30, 2008 5:28 PM
  1. Back to top

    Huzzah!

    Jun 15, 2007 10:24 PM by Sam Smoot

    It's nice to see topics like this getting attention. One nit to pick: I'd agree with a commenter on Stuart Halloway's blog: Hpricot() is actually pretty classic Ruby if you've done much data-crunching with the language. (The most likely scenario in my experience to need/run-in-to Integer().)

  2. Back to top

    Great Article........and I agree.....

    Jun 16, 2007 2:21 AM by Ben Hughes

    Meaningful methods on objects and API's is simply a hallmark of good design, which seems to have become DSL branded ! However, I think DSL's become much more useful in the design and specification of the code (BDD and to an extent unit tests) where the impact of ambiguity can have far wider (and more expensive) consequences, than in the execution of the code itself.

  3. Back to top

    DSLs?

    Jun 16, 2007 2:15 PM by Aaron Erickson

    "with Employee "123-45-6789" do dock_salary 1000 warn_about :misconduct end" I am not Ruby or DSL expert, but it looks like you are hardcoding an employee's SSN in a program here. Maybe I am being too literal ;) Seriously, in real programs, wouldn't most domain specific language not deal with any specific nouns? I ask because nearly every example I ever seen in an article about DSLs uses nouns (i.e., the person that SSN indicates, above) that refer to a hardcoded thing. It seems once you start placing symbols in where the proper nouns go, the code becomes less and less readable to non-programmer humans, and more like... computer language. Maybe I just don't get it. Seriously, this concept is new to me, and I may still be able to be convinced.

  4. Back to top

    Re: DSLs?

    Jun 18, 2007 6:37 AM by Werner Schuster

    Aaron, InfoQ has a new presentation by Obie Fernandez on DSL design and the ideas behind it: http://www.infoq.com/presentations/agile-dsl-development-in-ruby As for the hardcoded values: I think the problem is that short examples just aren't perfectly representative - eg. when JSPs (Java Server Pages) were introduced in Java, every sample contained a page that did an SQL query .. obviously not good either. Another side to this is: DSLs can be used as a way to configure an application. So, instead of defining yet another XML format or some other ad hoc format, you do something with a DSL. Eric S. Raymonds' book "The Art of Unix Programming" has a great chapter where he looks at "Minilanguages": http://www.catb.org/~esr/writings/taoup/html/minilanguageschapter.html where he describes the spectrum of these formats or languages, from simple name/value pairs to full Turing complete languages.

  5. Back to top

    Re: DSLs?

    Jun 18, 2007 6:42 AM by Peter Bell

    The real value of the idea of DSLs is twofold. Firstly it makes explicit what great programmers have always known - they are in the business of language design (what else are class methods but carefully layers constructs for allowing your code to be more readable and to express intent). Secondly it reminds you that you have options. You aren't writing an API - you are designing a language. Depending on the use case you might want to write an API, extend the language, come up with an XSD to define an XML config file, read in statements from a database, allow users to describe intent using a formatted spreadsheet, build a content management system for expressing intent or implement some kind of "boxes and arrows". When you see all of these as possible concrete syntaxes for implementing your abstract grammar you are much more likely to use the right tool for the job depending on use case. I wrote something about this yesterday: http://www.pbell.com/index.cfm/2007/6/17/Why-You-Want-to-Learn-About-DSLs

  6. Back to top

    Re: DSLs?

    Jun 18, 2007 3:20 PM by Peter Bell

    While we're posting quotes, there is Martin Fowlers great old piece on Language Workbenches: http://www.martinfowler.com/articles/languageWorkbench.html

  7. Back to top

    Motives

    Jun 19, 2007 8:52 PM by Daniel Berger

    Something you may not know about chromatic is that he's a Perl 6 core developer. It's something to consider when reading his (now several) opinion pieces on Ruby, Rails and/or its users.

  8. Back to top

    Re: Motives

    Jul 23, 2007 9:44 AM by brian d foy

    Actually, chromatic is a core *Parrot* designer. However, you're accusing him of lying about Ruby, Rails, and Ruby users. In the peice quoted here, he's merely showing that most people don't understand what a DSL actually is, and especially how it's not anything special to Ruby. So, what's your motive? Are you afraid that someone might find out that Ruby is just a programming language and not the cure for all the world's problems?

  9. Back to top

    Re: Motives

    Feb 20, 2008 10:02 PM by Daniel Berger

    Actually, chromatic is a core *Parrot* designer.
    Yeah. Ok. Right.
    However, you're accusing him of lying about Ruby, Rails, and Ruby users.
    I've made no such accusation. Strange comment really, since chromatic's article is just a sarcastic opinion piece. Accusing him of lying would be nonsensical.
    In the peice [sic] quoted here, he's merely showing that most people don't understand what a DSL actually is, and especially how it's not anything special to Ruby.
    It's external vs internal Brian. Mostly it seems to be a terminology issue.
    So, what's your motive? Are you afraid that someone might find out that Ruby is just a programming language and not the cure for all the world's problems?
    Yes, that's it Brian. You've found me out.

  10. Back to top

    Re: Motives

    Jun 30, 2008 5:28 PM by berkay NiQuiL

Exclusive Content

Agile Project Management: Lessons Learned at Google

In this presentation filmed during QCon 2007, Jeff Sutherland, the creator of Scrum, talks about his visit at Google to do an analysis of Google's first implementation of Scrum.

AtomServer – The Power of Publishing for Data Distribution

In this article, Bryon Jacob and Chris Berry introduce AtomServer, their implementation of a full-fledged Atom Store based on Apache Abdera, which is now available as open source.

An Introduction to Virtualization

It is easy to think that virtualization applies only to servers. In reality the recent resurgence of the concept is also being applied to networking, storage, and application infrastructure.

REST Anti-Patterns

In this article, Stefan Tilkov explains some of the most common anti-patterns found in applications that claim to follow a "RESTful" design and suggests ways to avoid them.

Choosing between Routing and Orchestration in an ESB

In this article, Adrien Louis and Marc Dutoo discuss the differences and relative merits of using orchestration vs. routing in a typical ESB setup, and discuss various implementation options.

Enterprise Batch Processing with Spring

Wayne Lund discusses batch processing, Spring Batch objectives and features, scenarios for usage, Spring Batch architecture, scaling, example code, failures and retrying, and the future roadmap.

User Story Estimation Techniques

Developer Jay Fields draws on his experiences as a ThoughtWorks consultant to describe effective user story estimation techniques.

Security (CAS and OpenID) with Ruby

In this talk from QCon SF 2007, Justin Gehtland explains two open solutions to distributed identity and their Rails integration components: OpenID (using ruby-openid) and CAS (using rubycas-client).