I have used and written some very productive DSLs.
While the idea of extending language may seem out of ordinary if you are not coming from ruby/lisp etc. but writing DSLs makes a lot of everyday programming grunt work easier
and sometimes even enjoyable. Let me see if I can elaborate a few "concrete" use cases without bogging down with implementation
details.
Perhaps the first DSL I wrote was to build data entry wizards. This was an obligatory routine work for some society in my
college. But I was able to write a high level ruby DSL with basic instructions and could delegate much of the work to
freshers, with limited ruby exposure who could get productive right away.
The code would look something like this:
wizard do
step do
before do
# ... fetch some data.
end
inputs do |f|
f.input :name
f.input :email
f.input :department
# ...
end
validate :name, presence: true
validate :email, presence: true, format: :email
# ...
after do |submission|
# save submission
end
end
step do
# ...
end
end
Implementation wise it was a light wrapper over formtastic backed by a simple Rails application which would persist the data
in a sqlite database. But though it was implemented in ruby, it could be used by people with very little ruby familiarity - and
this was a lot simpler and flexible to work with than GUI based form builders. I would love to be proven wrong by an Excel/VBA
enthusiast.
In a job in a ruby shop, when building administrative dashboards, activeadmin's user friendly DSL had proven to be very helpful when
building internal crud interfaces without having to bother with styling, UI etc.
Later I extended the wizard builder code when I needed to build some questionnairs for marketing. An advantage
of using a high level DSL was that I could have the same specification to generate user facing forms as well as integrate
with our internal activeadmin based dashboard - both having very different appearances.
Similarly, we had a use-case where using SQL was much more convenient than abstracting through an ORM. So I wrote a simple DSL to
manage SQL templates.
template "find_users" do
accept do |input|
input.string :name
input.string :age
end
query do
"select * from users where age = :name"
end
map do |result|
# Post processing to transform result array to
# a well behaved ruby object
end
end
Yes, it was not database neutral. And I am pretty sure that somewhere there is a commercial solution that does something
like this in a lot more powerful way, but the thing is it was written for a specific use case, insulated users from common sql
interpolation errors, was written in a single evening and got the job done.
Similarly our deployment scripts used Capistrano. In pre-docker era, when capistrano 3 had recently been released and
good cloud service integrations were yet to be released, we had extended the Capistrano DSL with AWS ruby SDK to support
EC2 deployments and integration with ELB and Cloudfront. This worked for a long while - without having to invest a lot of effort in a
complex configuration management systems, and also without having to manage a lot of messy shell scripts. I am never going
back to maven.
The common theme here is that a lot of cases where many people resort to XML, YAML or other configuration languages,
you can handle more expressively through a DSL. This also a big advantage that you can just put a debugger somewhere
and use pry to walk through the configuration.
This is applicable for templating languages like HAML as well - if some div does not show the correct value just put a debugger
inside the div and inspect the local environment. Try that with velocity.