Monday, August 3, 2015

Why create your own DSL?

  1. Why use a DSL?
  2. Why create your own DSL?
  3. What makes a good DSL?
  4. Creating your own DSL - Parsing
  5. Creating your own DSL - Parsing (with Ruby)
  6. Creating the Packager DSL - Initial steps
  7. Creating the Packager DSL - First feature
DSLs are great. The problem, though, is that there are many domains that have been too small for someone to write a DSL for. SQL and CSS exist because millions of develpers need to access relational data and style web pages. There are dozens of domains that could use a DSL, from packaging to orchestration to HTTP route management to cross-product configuration management. Let alone all the domains that are specific to your organization, from the corporation down to the team.

Just because there isn't a DSL doesn't mean you aren't programming in that domain. For example, you may have to manage a heterogenous environment of Apache and Nginx web servers for various legacy reasons. They may have server-specific configurations, but they have to share a set of configuration. Someone has to ensure that a change to the Nginx configurations is both made to the Apache configurations and that the change is translated properly and that the change occurs in the same deployment.

No-one will ever create a publicly-available generic DSL for managing web server configurations. There just isn't a large enough population who have to maintain a heterogenous web server environment. And even if there was such a DSL, it wouldn't be quite as useful for your needs. It would be generic - everything available as the lowest common denonimator. Which reduces the busat of the DSL for your purposes.

Busat ("expressive terseness") is not an objective measure equivalent for all people in all places. Expressiveness is directly related to the receiver's ability to understand what was communicated. If you can limit your listeners to only those who agree on specific terms, then you can be terser while remaining as expressive. If you have a jargon, then a DSL can take advantage of that.

Compare the following examples:

server {
    hostname "host1.domain.com"
    ssl {
        key_file "/etc/ssl/key_file"
        ca_file "/etc/ssl/ca_file"
        pem_file "/etc/ssl/pem_file"
    }
    ....
}
purpose :internal_web {
    ssl_root_directory "/etc/ssl"
    domain "domain.com"
    # Other internal_web things
    ....
}

server "host1" {
    purpose :internal_web
    ....
}

If your audience can all agree on what "internal_web" means, then that's strictly better. It describes exactly what you're doing, why you're doing it, and changes become much easier to vet for correctness. But, unless you're willing to write your own DSL, you would never be able to collapse the boilerplate in the configuration.

It's highly unlikely you specifically have to maintain both Apache and Nginx configurations to do the same thing. But, it's guaranteed that your organization or team has processes unique to it. Some special snowflake way of looking at something in the development process. Something that's just really annoying to manage in the standard language. Some good places to look are:
  • Packaging and orchestration (or most other devops/operations activities)
  • Configuration file generation
    • web servers
    • monitoring
    • datastores
  • Configuration value management across environments
  • Anything that has to interact with multiple different systems
  • Anything repetitive (such as CSS, for which there is Less)
prevnext