Monday, October 15, 2007

Is it really a domain specific language?

We have now reached the point where the term Domain Specific Language is so overused that it has become meaningless. And if not, then we are quickly approaching it. In my mind, this Fall's No Fluff conference will be remembered as "the one about DSL". But we need to slow down... I feel like standing up and shouting, "Not everything is a DSL!" Excel functions? Yes, great example. EasyMock's humane interface? Eh, perhaps. Ordering hashbrowns at Waffle House? umm... maybe this one has questionable value.

It seems that several terms are being confused, and we should be specific about different ideas. A domain specific language is a vocabulary for discussing a specific problem you have. Excel functions are a darn good vocabulary for working with spreadsheet data. They may not be easy to learn, but they are an extremely powerful language to solve the problem of expressing complex formulas in spreadsheets. A fluent interface (or humane interface, or literate interface) is not the same thing as a DSL! A fluent interface is an API design that allows users to work with concepts in a way that closely matches most Western sentence structure, such as:

receipt = order.2.lattes.andPay($10)
Compare this API to the traditional Java style API:
Order order = new Order();
order.setQuantity(2);
order.setItem(latte);
Receipt receipt = order.pay(new Currency(10, DOLLARS));
Which API is easier to read, the first or second? Yes, fluent interfaces are easier to read (you answered "first", right?). Hopefully your native language follows the same subject-then-predicate order of English, or else the code example may confuse you, but that's an aside. I do think fluent interfaces are a good idea: they're easy to read and easy to write, despite sometimes being harder to debug because of their multi-step nature.

But just because something has a fluent interface doesn't mean it is a DSL. EasyMock has a fluent interface, but it is not a DSL. Consider the following unit test code:

MyObject mock = new EasyMock.createMock(MyObject.class);
EasyMock.expect(mock.foo()).andReturn(10).once();
new SystemUnderTest().perform(mock);
EasyMock.verify(mock);
This code, if you're at all familiar, creates a mock object and tells it to return 10 when the foo() method is called, and only do it once. The system under test is then exercised and the mock is verified to have been called correctly. This is a fluent interface. The methods are chained together on the 2nd line and it is sort of easy to read.

Let's revisit my definition of a DSL: "a vocabulary for discussing a specific problem you have". Is EasyMock a DSL for unit testing? EasyMock's fluent interface provides a nice way to set and verify expectations on mock objects. But setting expectations was not my problem, unit testing collaborating objects was my problem. And the two are different! EasyMock uses a record/playback metaphor to create mocks, and its interface is a DSL for record and playback. Using EasyMock's API in my project didn't solve the problem of writing better unit tests, it created a problem of how to work with record/playback frameworks. Since this fluent interface does not provide a vocabulary for unit testing, it is therefore not a DSL.

So a very important part of a DSL is that it solves the problem you have, not just any problem. Let's consider the famous Waffle House ordering "DSL" of "scattered, covered, and smothered" (these are three different ways to order hashbrowns, by the way). Is this a DSL? What problem does it solve? If you wait tables at Waffle House then it is a terser than English vocabulary used to communicate with the cooks, and therefore a DSL. But if you are a customer at Waffle House, what possible problem does it solve? Can you not say the words "with cheese"? I say ordering at Waffle House is harder than it needs to be because we are forced to adopt the language of the cooks (the implementers). Have you ever ordered a Philly Cheese Steak in Philadelphia? If you don't say it right then you don't get your food. It's nerve wracking for the tourists! Imagine this one... imagine a restaurant where the cooks are Mexican. Can you imagine that? I've just described a ton of places you eat, trust me. Wait if you had to order in Spanish because that is the DSL of the cooks? Well, that's what you're doing at Waffle House. And that is what I'm doing with EasyMock every time I set an expectation.

My preference is to define a DSL in relationship to a person and their particular problem. A language might be a DSL for one person and not another. If you're an API designer, simply saying that you're going to wrap your implementation in a fluent interface is not the same thing as creating a DSL, and you might be exposing the wrong level of abstraction to your users. Creating mini-languages cannot be our goal. We need to first think hard about which problem we need to solve. And providing a nice, fluent interface at just the right level of abstraction can then be a beautiful thing.

9 comments:

Unknown said...

Great blog post! I really like your analogy between ordering food and easymock. What changes would you make to help bring mock testing to a DSL?

Hamlet D'Arcy said...

One suggestion is to not use mocks for everything. http://hamletdarcy.blogspot.com/2007/10/mocks-and-stubs-arent-spies.html

Otherwise, some of the behavior driven development test frameworks look promising. I'll try to look into this more in the future and formulate a better answer. (I don't have a good one just now!)

Stephan.Schmidt said...

Classical strawmen attack.

"Using EasyMock's API in my project didn't solve the problem of writing better unit tests, it created a problem of how to work with record/playback frameworks. Since this fluent interface does not provide a vocabulary for unit testing, it is therefore not a DSL."

EasyMock is not a DSL for unit testing but for mock expectations. So obviously it can't solve the unit test problem. And it can't be a unit test DSL. But it does solve the mock expectation problem by introducing a new language to setup expectation specific to the domain of mocks. Therefore it's a mock DSL. qed.

Peace
-stephan


--
Stephan Schmidt :: stephan@reposita.org
Reposita Open Source - Monitor your software development
http://www.reposita.org
Blog at http://stephan.reposita.org - No signal. No noise.

Pai Rico said...

Totally agree that the term DSL is sufferting from a very dangerours abuse. Industry’s big players are looking for the next big thing and since visionaries are talking about this all sort of ‘DSL toolkit’ pops up. I’ve been to one presentation by Neal Ford on the waffles example and eve not being something geeky it is a pretty good way of teaching about DSLs. Actually I found that talking in examples is better to get make people understand why DSLs are a natural way of thinking.

I have a different view of Fluent Interfaces but I liked yours. I only wouldn’t attach that with sentences, Fluent Interfaces are readable. Some times this means an English-like sentence, sometimes not.

I think EasyMock uses language adaptation and JMock uses DSL. JMock has evolved an internal language fr years.

Cheers
Phillip Calcado
http://fragmental.tw

Anonymous said...

Great blog with lots of useful information and excellent commentary! Thanks for sharing. DSL high speed internet accessv

Aravind Ajad Yarra said...
This comment has been removed by the author.
Aravind Ajad Yarra said...

"A domain specific language is a vocabulary for discussing a specific problem you have. Excel functions are a darn good vocabulary for working with spreadsheet data. They may not be easy to learn, but they are an extremely powerful language to solve the problem of expressing complex formulas in spreadsheets."

By this example, can we infer "Java" is a DSL for the problem of programming? I think we got to see the problem domain in perspective. In the end, it all boils down to what one thinks is the domain that they are dealing with.

I feel fluent interfaces just a way to make the languages read easier, probably targeting domains with users who are not realy programmers, but say analysts and domain expects.

BTW, great blog post.

-Aravind

Anonymous said...
This comment has been removed by a blog administrator.
木須炒餅Jerry said...
This comment has been removed by a blog administrator.