Internal DSLs: You have to give up your host’s conventions

Sometimes when talking about Internal DSLs people criticize the fact that the resulting code well-established breaks code conventions. I just got that kind of comment while showing Hash-QL, my new toy Internal DSL, to some friends. I’m currently studying DSL integration proposals and HashQL is one of the languages I created to try the integration solutions. It’s basic idea is to have some constraints that will be applying against a list of (Ruby’s) Hash objects. So if we want to find all users from Rio de Janeiro above 25 years we’ll do something like this:

user_above_25_years = create_spec{
			[:city == "Rio de Janeiro",
                         :age > 25]
		}

results = @data.find_elements_that :matches => spec

That little snippet has a problem for Rubyists. The Ruby community has a loose set of code conventions but they can be very strict about it. On of those rules says that you must always use a do…end block when you have blocks with more than one line. This makes sense for the Ruby language and I definitely think that code conventions are good (or at least better than no convention at all).

The problem is that the code above isn’t in Ruby. The code above is in HashQL, a language that looks like Ruby (and can be interpreted by a Ruby runtime) only because it was implemented as an Internal DSL. Ruby’s conventions aren’t necessarily applicable here.

I designed HashQL and thought of it as a set of constraints embraced into one thing that I call specification. My original idea was to have even less noise in the constraints grouping, I tried to make the specification above look like this:

user_above_25_years = create_spec{
			:city == "Rio de Janeiro"
                         :age > 25
		}

But couldn’t get this to work without some voodoo like having a class variable at the Symbol class (a global variable in this context) so I sticked to the simpler (to implement) yet noisier version.

Another good example is JMock. Look at the example below:

# allowing (bank).withdraw(Money.ZERO);
will(throwException(new IllegalArgumentException("you cannot withdraw nothing!"); 

This is not Java, it doesn’t follow Java conventions, it is not required to use objects to solve the problems. It is simply a language specific to define mock objects.

By using an Internal DSL you’ll probably mix a lot of host’s and DSL’s code so it is understandable that people get crazy about that convention breakage. While dealing with a DSL, being it internal or external, you have a new language and it has its own style of solving problems and writing code.

4 Responses to “Internal DSLs: You have to give up your host’s conventions”


  1. 1 Fabio Kung Nov 9th, 2007 at 7:08 pm

    Phillip, I would still rather “create_spec do..end”, as “create” might have an imperative sense. Perhaps “spec { … }” illustrates better what you are trying to say.

  2. 2 Phillip Calçado "Shoes" Nov 9th, 2007 at 7:25 pm

    The ‘business syntax’ is something like:

    {
                :city == "Rio de Janeiro"
                             :age > 25
            }
    

    Would you stick with the Ruby convention?

    ‘create’ is a nice word since what I’m doing is to create a Specification Ruby object based on what a DSL expresses. Anyway the create_spec part is Ruby, it has no direct relation to the DSL syntax.

    I still think you’re focusing on what looks nice on Ruby and forgetting that this is not Ruby, it’s HashQL ;)

  1. 1 Fragmental » Saindo da Praia Pingback on Nov 29th, 2007 at 11:51 pm
  2. 2 Internal DSLs: Can't use you tools here at Fragmental.tw Pingback on Feb 11th, 2008 at 10:25 pm

Leave a Reply








Creative Commons License

This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.