Ayende @ Rahien

It's a girl

Why we need for Domain Specific Languages

I speak quite often about DSL and how to build them, but so far I did not do was explain why you need a DSL at all. After all, since you are reading this blog, you already know how to program. Can’t we just use “normal” programming languages to do the same job? We can even do with a dash of fluent interfaces and Domain Driven Design to make the code easier to read.

We need to inspect the different needs that lead the drive toward a DSL.

A Technical DSL

A technical DSL is supposed to be consumed by someone that understands development. It is meant to express matters in a more concise form, but it is still very much a programming language at heart. The main difference is that it is a language focused on solving the specific problem at hand. As such, it has all the benefits (and drawbacks) of single purpose languages. Examples for technical DSL include Rake, Binsor, Rhino ETL, etc.

The driving force around that is that you want to have richer expressiveness in specifying what you want to happen. Technical DSL are usually easier to write, because your target audience already understands programming.

In fact, the use of programming features can make a DSL very sweet indeed. We have already seen a Rake sample, so let us see a Binsor sample:

for type in Assembly.Load(“MyApplication.Web”).GetTypes():
     continue unless type.IsAssignableFrom(Controller)
     component type.FullName, type

So we take three lines to register all the controllers in the application. That is quite a bit of expressiveness. Of course, it assumes that you are familiar with the API and its usage, which is not always true, which leads nicely to business focused DSL

A Business DSL

A business DSL is focused on being (at least) readable to a businessperson with no background in programming.

This type of DSL is mainly expressive in the terms of the domain, and it has a lot less emphasis on the programming features that may still exists. It is also tend to be much more declarative than technical DSL in general and a lot more emphasis is placed on the nature of the DSL so those would not really be necessary.

I can’t really think of a good example of a business DSL in the open. A good example of DSL that I have run into include a cellular company that had to have some way to handle all the myriad of different contracts and benefits that it had. It also needed to handle this with a fairly rapid time to market, since the company needed to respond quickly to market conditions.

The end result was a DSL in which you could specify the different conditions and their results. For instance, to specify that you get 300 minutes free if you speak over 300 minutes a month, you would write something similar to this:

if CallMinutesForCurrentMonth > 300 and HasBenefit “300 Minutes Free!!!”:
          AddCallMinutes -300, "300 Minutes Free!!!"

It was fairly simple to define a small language that could describe most of the types of benefits that the company wanted to express. The rest was a matter of naming conventions and dropping files in a specified folder, to be picked up and processed at regular intervals. The structure that surrounds a DSL is a subject that deserves quite a bit of attention on its own.

A businessperson may not always be able to write actions using a business DSL (more on that later), but they should be able to read and understand it. After all, it is their business and their domain that you are trying to describe.

Now, why shouldn’t a businessperson be able to write actions using a business DSL?

The main reason, as I see it, is of error handling. No, I don’t mean in the actual running of the DSL action, I mean when writing it.

A DSL is supposed to be read like a language, but it is still a programming language, and those have little tolerance for such thing as bad casing for keywords, for instance. Certain types of users will simply be unable to go over the first hurdle in the road they face, because of this.

It is important to know your audience, and it is even more important not to be contemptuous toward that mythical businessperson. You may not think that this person can understand programming, only to discover that there are quite a bit of automation going on in their life already, powered by VBScript and excel macros.

If you can leverage this knowledge, you have a very powerful combination in your hand, because you can provide that businessperson the tools, and he can provide the knowledge and the required perspective.

Automation DSL

I am not quite sure about this classification, but it certainly has its place. Another name for this may be the IT DSL. This type of a DSL it often used to expose the internal of an application to the outside world.

Modern games are usually engines that are being configured using some sort of a DSL. In fact, I fondly remember building levels in Neverwinters Nights.

More serious usage for this can certainly be found, such as a DSL that lets you go into the internals of an application and mange it. Think about the ability to run a script that will take re-route all traffic from a server, wait for all current work to complete, and then take the server down, update it and bring it up again.

Right now, it is possible to do this with shell scripts of various kinds, but most enterprise application can certainly have more visibility into them than already exist, and a DSL that will allow me to inspect and modify the internal state would be very welcome.

I can certainly think of a few administrators who would be grateful to have more power in their hands.

 

To conclude, can you think of other types of DSL in use?

Comments

The Other Steve
11/25/2007 05:38 PM by
The Other Steve

This business DSL stuff you are talking about. It's been around for years. It's called a Business Rules Engine.

Look at iLog for an example.

http://www.ilog.com/products/rulesnet/index.cfm

But there are dozens upon dozens of these out there.

Ayende Rahien
11/25/2007 05:44 PM by
Ayende Rahien

Steve,

That is a very good point, I never considered it in this sense. Probably because I don't think of this as a DSL.

clearlite mike
11/26/2007 10:06 PM by
clearlite mike

Frankly, I prefer C++ or Java.

The problem with DSL's is that inevitably some aspect of the applcation is outside the 'specific domain', even if only a little bit. Then you either have to jump through many hoops or resort to a 'general puprose' langue anyway.

I prefer to work with standard and widely used languages, because of tool support and a large body of accumulated experience in the development community.

These concerns usually outweigh the 'advantages' of some proprietary and narrowly focused 'language' or syntax, which very often is neither consistent nor complete.

Ayende Rahien
11/27/2007 01:11 AM by
Ayende Rahien

That is why my DSL language of choice is Boo, it is a CLR language that can integrate cleanly into a bigger application.

John Lopez
11/27/2007 03:23 PM by
John Lopez

SQL is the most used DSL in existance; if one would prefer to use C++ or Java to do what SQL does (hide the complexity of data access from the user) then I think something is probably amiss. Wrapping data access in a low level data access layer and a high level business objects layer of course is a different task, but I think going back to file based data access simply to reject DSLs would represent madness.

A good DSL does one thing, and does it very well. It should also be easily wrapped in a traditional procedural language so that those missing features and irregularities can be handled in a structured way.

The biggest problem with DSL creation is that often we don't keep it simple enough. We try to turn it into a full blown development language with general purpose features that mask the distinction between the tasks that the DSL is designed for, and those that the system's infrastructure should be providing.

This is where DSLs can fail to provide the value they were intended for, not simply by doing the job they were intended for: partitioning business rules, data access, logic processing and system configuration away from the infrastructure of the core system.

Mats Helander
11/28/2007 02:07 PM by
Mats Helander

Why is this:

if CallMinutesForCurrentMonth > 300 and HasBenefit “300 Minutes Free!!!”:

      AddCallMinutes -300, "300 Minutes Free!!!" 

so much clearer than this:

If client.CallMinutesForCurrentMonth > 300 And client.HasBenefit(“300 Minutes Free!!!”) Then

      client.AddCallMinutes(-300, "300 Minutes Free!!!")

End If

or even

if (client.CallMinutesForCurrentMonth > 300 && client.HasBenefit(“300 Minutes Free!!!”)

      client.AddCallMinutes(-300, "300 Minutes Free!!!");

There's definitely going to be a non-trivial cost involved in developing and supporting a new DSL for the customer.

To me it seems that someone who could parse your DSL example could be trained to understand the VB.NET or even the C# example for a much smaller cost than developing a new DSL?

/Mats

Ayende Rahien
11/28/2007 02:15 PM by
Ayende Rahien

Several reasons.

The first is that the examples that you gave are not stand alone examples, you need to wrap them by quite a bit of syntax to make them work.

The second is that the C# ones introduce syntax which is really not fun to explain to the user

(&&, what is that?).

The third is that instead of introducing language semantics, you introduce operations on API, there is usually a distinct difference between them. The language semantics are meant to be clear, readable and similar to a written language, an API has different design goals.

The forth is that while it is not shown in this example, I have a long way to go with the DSL approach, where the VB.Net / C# approach I have no way to improve on the current syntax.

Mats Helander
11/28/2007 02:42 PM by
Mats Helander

1) Just a method signature, which can easily be generated at any point. If we generate it early, we could let the user edit his code snippet inside it in VS, giving IntelliSense, error handling etc. Otherwise we could generate it late, essentially creating a VB/C# scripting environment rather than a "DSL" environment for our users. In both cases, the user would only have to write those lines I showed in the example

2) Well, this is just what I mean - I'll bet that I can explain that && means And faster than you can build a new DSL to make that ugliness go away.......hmmm....actually, I take that back. But I'll bet that you can explain it faster than I can build the DSL ;-)

Seriously, yup it is ugly, but I have the feeling I could solve it with a post-it saying "&& means And, || means Or" instead of building a DSL. I think I would at least ask the customer to decide between these options.

3) Agreed, but I would argue that you need a certain level of sophistication in your language before you can start exploiting this type of potential with a DSL. Some domains and project scopes definitely warrant this approach, but unless it can be clearly established that this is the case in one's current project, chances are that the overhead involved in developing and supporting a DSL can not be warranted by a potential that may never become used.

If the API approach becomes as clear or at least almost as clear for the actual use cases, why not go with it? All I'm saying is that the example you showed looked clearly of the kind where an API would suffice just as well. I'd love to see an example that actually motivated the DSL over the API for a business DSL, because as far as I have seen, those are rare...(though certainly not non-existing)

4) Indeed, but you can improve the API. I'm not saying that DSLs don't have value, I'm saying that in most cases I have seen, they do not have enough value when compared to an API that it motivates their higher overhead. Better tool support for DSLs would definitely change this equation.

/Mats

Ayende Rahien
11/30/2007 10:20 PM by
Ayende Rahien

Mats, thanks for asking the hard questions.

1/ No, it is not just a method signature. How do you import a custom assembly with external code? How do you enter a new namespace?

The language doesn't let me make it work.

I want to do something that is complex, and I want to be able to do that with all my usual tools, so I use C# and compile an assembly

And then I can immediately use it like this:

import Complex from SomeComplex

if ComplexCalculation(account):

do stuff

Extensibility of the DSL with external factors is important.

2/ The point of writing the book is that you will be able to write the DSL easily.

3/ My claim is that the cost of doing something like this is that you have very low cost for this.

I'll try to post a more appropriate example soon.

4/ There isn't much cost in there, but there is a lot of value in being expressive. There is also more value in being able to actually look at things without the programming language overhead.

I don't think that I disagree with that there will be times that an API is good as a DSL, but I think that I have a different idea about where that line is at.

Comments have been closed on this topic.