The value of a domain-specific language lies in how well it captures and expresses a particular professional jargon, which in turn depends on the related concerns of fluency and context. In this second article in his series on DSLs, Venkat Subramaniam demystifies these essential characteristics of DSLs with examples based on real-world APIs such as EasyMock and Guice. He concludes with an iterative example in building a fluent, context-aware DSL using Groovy.
When domain experts communicate with each other, you may notice that they do not always use complete, grammatically correct sentences. Often, they use a specific technical or professional jargon, which allows them to communicate effectively. The terseness and specificity of jargon can be read in this partial transcript from the first moon landing:
... 102:45:44 Aldrin: Okay. Engine Stop. 102:45:45 Aldrin: ACA out of Detent. 102:45:46 Armstrong: Out of Detent. Auto. 102:45:47 Aldrin: Mode Control, both Auto. Descent Engine Command Override Off. Engine Arm, Off. 413 is in. 102:45:57 Duke: We copy you down, Eagle. 102:45:58 Armstrong (on-board): Engine arm is off. (Pause) Houston, Tranquility Base here. The Eagle has landed. ...
The above conversation makes little sense to those who don't share the experience and terminology of astronauts landing on the moon; but still you can detect the fluency of the communication. According to one definition, "Fluency indicates a very good information processing speed; i.e., very low average time between successively generated messages." While typically applied to language speakers, the term fluent can also apply to a language itself. The fluency of a language can be measured by how quickly and easily it allows users to process information.
Jargon is a key aspect of fluency in many professional domains. If you want to communicate well with other professionals, you need to be fluent in the professional jargon. The specialized terseness of jargon is a handy tool for communicating within a given domain of expertise: it supports a higher signal-to-noise ratio.
Martin Fowler and Eric Evans use the term fluent interface or humane interface to describe more "language-like" interfaces, or interfaces well designed for human use. Fluency is a design characteristic of DSLs. A fluent DSL is highly readable and flows naturally for users in its domain.
Examples of fluency
It might help to take a look at some examples of fluency in programming languages and APIs. For instance, let's see how we loop through a collection of names in different languages. The traditional syntax in Java would be as follows:
Listing 1. Looping through a collection in Java
for(int i = 0; i < names.size(); i++)
{
String name = (String) name.get(i);
//...
}
If you are like me, you want to scream when someone shows you such banal syntax. The index variable i is redundant, especially if your real intent is to work with the elements of the collection. Another approach would be to use the iterator to traverse the collection, as follows:
Listing 2. Iterating through a collection in Java
Iterator iter = name.iterator();
while(iter.hasMore())
{
String name = (String) iter.next();
//...
}
Unfortunately, this approach does not seem especially fluent, either. Once you process an element, you have to explicitly push the iterator to the next element. Fortunately, Java 5 introduced a more fluent syntax to loop through the elements of a collection:
Listing 3. Fluent looping in Java 5
for(String name : names)
{
// ...
}
The above syntax is simple, fluent, easy to understand and work with; it has less ceremony.