Many years ago, I was working on application software that we configured and shipped to nearly a hundred clients. Although we did the first installation on a machine that we provided, the customer had to install updates a few times a year. (This was before most people knew about the Internet.)
A few of us tried to convince the president of the company that we could make good use of a professional installation program. But, he could not see the point. He pointed out that we were already working in C, and C could do everything that the installer could do. So he concluded we could just write our own. He could not see the use of a specialized language for installation, what we would now call a Domain Specific Language (DSL).
Amusingly enough, we were already using a DSL to build all of the software. This guy was a big fan of make
. We used a reasonably complex build system based around make
to generate over twenty different variants of the program.
His question is actually a valid one, although at the time I didn’t have the terminology to make my point. Everything I can do with a DSL, I can do in a general purpose language. In fact, I can package up the functionality for the DSL in libraries or classes and even make calling it almost as easy as using a DSL. So, why would a DSL be a advantage? I believe the answer is notation. The DSL provides no increase in functionality. But what it does do is provide a better notation for working in the domain.
Let’s take make
as an example. Even though almost everyone complains about the tab thing in Makefiles and the reliance on the shell, make
is still in wide use. Anything you can do with make
can be done with any general purpose language. It would even be possible to build libraries for common functionality needed by build tools. Yet, we still use make or other tools similar to them. Why? Despite its flaws, the make DSL is very effective for specifying dependencies and tasks needed to build one set of resources from another set of resources.
SQL is another good example of a DSL, I remember accessing databases before SQL was wide-spread. Every database API was slightly different. They all provided the same basic functionality, but there were differences. You also needed to write quite a bit of common code in every place you used a particular database’s API. Then SQL came along, and things changed. No, it was not a complete language, but it did allow you to talk to the database at a higher level. In the beginning, SQL libraries were not any faster (and were often slower) than the native APIs. Nevertheless, the notation was more convenient for the kinds of operations that you need to perform on a relational database.
In many domains, a library is enough to allow you to get your work done. When the domain is understood well enough that we can really talk about it at a high level, it becomes possible to make a DSL. There seems to be a large difference in usability when a DSL is designed well. Even if a DSL is not perfect (like make), it may be enough better than the alternatives that still use it…even if we still reserve the right to complain.