Domain Specific "PowerTool" Languages Promote Elegance
By Eric Armstrong on Jan 21, 2008
In both Ruby and DITA, domain specific languages make elegance possible. More importantly, each is producing an ecosystem of domain specific languages (aka "power tools") that is making it to do ever more as time goes on.
Ruby is a general purpose scripting/programming language. DITA is a markup language intended for documents and information artifacts. What both have in common is the capacity for the construction of domain specific languages. In each case, that feature is arguably the one that makes them great.
Both DITA and Ruby are examples of languages that excel at the constructing other languages. This writeup describes the ecosystems of special-purpose languages that have evolved around them.
I favor the JRuby implementation of Ruby, for its combination of powerful libraries, threading, and the enhanced potential for cross-platform ubiquity. But here, the discussion is mainly about the power inherent in the Ruby language concept.
What is a DSL?
Martin Fowler has done a lot to promote the power and utility of domain specific languages--languages that are tailored for a specific problem domain. In particular, he points out the difference between an "external" (stand-alone) DSL that is forever limited to the set of solutions the language developers had the prescience or time to enable, and "internal" DSLs that are built into a general purpose language. The beauty of the latter arrangement is that you're never limited. When the DSL does what you want, you can take advantage of its convenience. When it doesn't, you code around it. (See the Resources section for a selection of Fowler's material.)
DSLs are great because they make it easier to do things. In effect, they encapsulate knowledge about how problems are solved in a given domain, so you use shorthand for the tasks you want to perform, and the language processor expands your notation into the code that carries out the task. As a matter of history, intermittent shifts to computer languages with more expressive capability have generally been the trend--from machine language, to assembler, to high level languages. "More power" is what it's all about, after all.
At the same time that a DSL gives you more power in a given domain, it also simplifies your code. So programmers tend to like DSLs, because they enable the combination of power and simplicity that constitutes elegance. They let you get more done, more easily, in a more readily understandable way.
As Fowler indicates, a DSL that is constructed inside a general purpose language is especially great. If it exists outside the general purpose language and stands on its own, the only things it can do are things the language developer thought of or had time to implement. But if it lives inside a general purpose language, you're never limited--you have the convenience and expressive power of the DSL whenever you can use it, but have extra power at your disposal whenever you need it.
But the term domain-specific is unfortunately inaccurate in one important respect: It brings to mind highly specific problems--like those encountered in a shoe store, for example. In that sense, "domain-specific" tends to make you think of highly targeted IT applications--all very important, but unless you have such an application in mind, and can think of a language you might want for that purpose, the concept of a DSL tends to remain an interesting abstraction with little practical value.
But there is a middle ground of DSLs that is highly general. That middle ground consists of general purpose languages that help you tackle problems you face every day in the same way that others do, even though they are working in different domains. In Ruby, such languages help developers perform programming tasks. In DITA, they help writers provide information artifacts that technology users need.
The languages that live in that that middle ground might be called "general purpose domain specific languages", but that's pretty much a contradiction in terms. And it's a mouthful. So maybe we would be better served by calling them something else, like "empowerment languages" (ELs) or better, "Power Tools". Because what they do, first and foremost, is give you powerful tools you can use to help you build whatever it is you're constructing.
In Ruby Rocks!, I wrote about the intrinsic aspects of the language that makes development a pleasure. But the ecosystem of DSLs that is growing up around Ruby is perhaps it's greatest long-term asset.
Interestingly, the categorized list of Ruby gems at RubyForge shows some 800 projects devoted to software development. Some of the most powerful are DSL power tools. On the other hand, there are DSLs that aren't Ruby gems at all. Here is a list of "world-changing" DSLs:
- Rake is a fantastic build language that provides a lot of power with simple, clean syntax. For more on Rake, see Rake Rocks.
- Ruby on Rails is a well-known DSL that is designed for building web applications.
- RSpec is a tool for writing unit tests that are both readable and executable. Because they specify behavior in a readable way, they are more like specifications--hence the name: R(uby)Spec. Of course, as one blogger rightly pointed out, an RSpec file isn't really a specification, because it doesn't declare abstractions like "returns n\*\*2 for all integers greater than zero". [I've lost that link! If anyone finds it, please send it to me so I can point to it. --thanks, eric] What Rspec does in reality is to produce a "specification by example" that can be executed as a series of tests. But those comments do lead to an interesting extension to consider for RSpec:
- The capacity to randomly generate one of two specific elements that match a pattern like "an integer greater than zero", or "an integer less than zero", so that different aspects of the abstraction can be tested in a way that tends to ensure the abstraction is implemented, rather than a case statement that satisfies the tests, and only the tests. (Of course, the test harness could only generate random input values. Generated output values would require another implementation of the algorithm, which would itself be subject to testing--a never-ending loop. But the problem can be finessed with data hiding. If some external entity like the quality control group creates a table of test values, and the developer doesn't know which values will be used, then a general implementation is required to ensure success.)
- Martin Fowler's XSL in Ruby is described in what will probably turn out to be a seminal paper: Moving Away From XSLT. It combines the declarative power of XSL with the capacity for loops, conditionals, and functional coding whenever you need it.
- OptiFlag is a DSL for processing command-line options.
Here are a couple of Ruby gems that sound interesting. I don't know much about them, as yet, but I'd love to find the time to explore them further:
Starting from a generic topic, the initial DITA release included specializations for concepts, tasks (procedures), and reference topics. But as time goes on, more specialized topic types have begun to appear:
- The Learning and Training specializations let you create a SCORM-compliant structure for lessons and quizzes, in a way that lets data be shared with books, articles, and other DITA deliverables.
- The TroubleShooting topic type was designed to describe hardware and software problems and their solutions. Developed by IBM and released as an open source plugin for the Open Toolkit at SourceForge, some aspects of the topic type are highly specific to the computing industry. So a topic type designed for automobile diagnostics, for example, would have to remove those terms in a further specialization. (When the troubleshooting topic was introduced at the Silicon Valley DITA Interest Group one perceptive individual remarked that it would be nice to have an even more general precursor that could be specialized in different directions without having to remove stuff. That is an interesting area for future investigation.)
- Introduction to DSLs, from an upcoming book by Martin Fowler
- Video of a presentation on the subject by Martin Fowler
- Fowler's articles on Language Workbench programming:
- Language Workbenches: The Killer App
- Language Workbenches and Model Driven Architecture
- A Language Workbench in Action: MPS
- Writing a Domain Specific Language, by Jamis Buck
The categorized list of Ruby gems at RubyForge:
- Rake Rocks!
- Readable intro to RSpec 1.1.2
- RSpec cheat sheet:
- Martin Fowler's writeup on XSL in Ruby: Moving Away From XSLT
- Acquarium: Aspects for Ruby:
- Dhaka parser generator:
- Presentation on Specializations:
- Tutorial on specializations:
- The DITA "Cover Pages "
- SourceForge OpenToolit, with plugin-specializations for troubleshooting, music, and a thesaurus: