What makes a DSL a DSL?

I recently released Flexjson to the world, and I've been thrilled by the response I've gotten. But, someone asked why I called Flexjson a Domain Specific Language. It's a good question so I thought I'd write down some ideas around what makes me say something is a DSL vs. when it's just an API.

DSL does get thrown around a lot, and it's hard to always pick out what's a DSL and what's just an API. Hibernate's HQL is definitely a DSL, SQL is a DSL, Phong Shader languages are DSLs, but it gets fuzzier when people say Rails is a DSL or something in LISP. LISP and Ruby are general purpose languages just like Java so how can a library written for a general purpose language be a language too. Isn't that just a well written API? I struggled to answer this question when I first encountered examples of these DSLs.

Martin Fowler wrote some thoughts of this subject and he divided DSLs into two types: external DSL and internal DSL. External DSLs examples are SQL, Hibernate's HQL, ant scripts, or phong shader languages. Internal DSLs would be certain aspects of Rails, or Javascript's Event.Behavior.

External DSLs are glaring examples of DSL. They're easy to spot. Internal DSLs are harder to spot as such. I've decided that Internal DSLs read like a sentence where an API is reads like an algorithm. It's a fuzzy definition, but no less fuzzy than spotting design patterns in code. Said another way DSL should feel more high level, like you're able to produce results in a very simple way.

So what makes an API an API? Well I guess API is not high level. Terrible definition I know, but I think it's pretty accurate. An example of a definite API is JDBC. There's no way to get things done in a simplified way. It's verbose as hell and low level as the day is long. Sorry I get that way about JDBC. ;-) But seriously, it makes me handle all the details. It just gives me access to the database, but I have to manage the connections, the statements, and results sets sure signs I'm dealing with an API.

Flexjson is an internal DSL. It's very simple DSL. There are really only three statements in this language: include, exclude, and serialize. However, while these are just simple methods include and exclude accept strings formatted in dot notation. Dot notation is a simple way of specifying the fields within the object graph. This is probably the part that is most language like. The overall style of Flexjson feels more high level almost language like. So we get something like:

new JSONSerializer().include("bids", "winner.winningBids").serialize(auction);

Let's say I had designed Flexjson like following:

JSONSerializer serializer = new JSONSerializer();
serializer.include( auction.getClass().getField("bids") );
serializer.include( auction.getClass().getField("winner") );
serializer.include( auction.getClass().getField("winner").getDeclaringClass().getField() );
serializer.serialize( auction );

I would say this is starting to look more like an API than a DSL. It doesn't really help me in specifying what I want to happen. It just does the serialization to JSON process. And not as easy to work with which means it's not fun either.

So while Flexjson purpose is to serialize Java objects to JSON. It also tackles the effort of walking the graph for you. Walking the graph is not central to it's purpose, but it's something you have to do as a client. So, Flexjson has a little language that let's you just say in a high-level way what you want to happen. This is what makes your job easier.

The difference between DSL and API sometimes boils down to just style. Java has had a tradition in writing APIs. Some better than others. However, there are a lot of good programmers out there doing things differently, and I think that's a very good thing. I've heard Rubynauts say that you can't create DSLs with Java because it doesn't support all the cool stuff Ruby has. And all that stuff is important to writing DSLs. I happen to disagree with that very much. Java is just as suitable for writing DSLs as any other general purpose language. You just have to work with what you got. I hope to add more on this subject later. DSL vs. API is root in a change in style, but it allows us to do things we couldn't do with our APIs.

It's really about reaching consensus if something is a DSL or not because these things are fuzzy. We're using these APIs to write mini-languages, and exposing our language as APIs so it can be confusing. But, just because it takes the form of an API doesn't mean it's an API. There are lot of benefits to this my favorite is code completion and use of our existing tools. Flexjson I think qualifies as a DSL, albeit a simple one.


printingeye said...
This comment has been removed by a blog administrator.
uncial said...

I certainly agree that one should use whatever facilities the host/implementation language offers in the most expressive way possible.

That said, I've always understood "DSL" as notation designed for use by a domain expert, as free of "code-like" syntax as possible. That would seem to push the Java fluent-API-style examples to the very edge of DSL, if not just past it.


Alex said...

You might be interested in a presentation I did on DSLs in Java and some links to interesting background on DSLs in general. In the presentation I ran through a series of options, including fluent interfaces in Java, writing grammars with Antlr, using beanshell, etc. Source code is provided.


chubbard said...


I think DSL's are more broad in that regard. Certainly you definition is good, but if you read Martin Fowler's Wiki or Dave Thomas' and Andy Hunt's writings they actual talk about DSLs as language we developers write to help us with our code. So they really are refering to your code acting like a language. They talk about building the language up from the general purpose code to meet the language of the domain or your business objective. I suppose I'm trying to describe a definition that meets both use cases of DSLs.


Thanks for the presentation. I'm looking foward to looking at it.

lbruno said...

DSL are Declarative.

That's as concise as I can put it.