Why Not YAML?

I enjoyed Joe O’Brien’s recent post Why Yml?. He asked why we use external config files when we have an dynamic language like Ruby. Yeah, Ruby is more expressive and it would be simpler to use only one language, but to me it makes sense to use YAML for config data. And I think YAML is used a lot because it can represent config data more clearly.

So, why would you store data outside of code when Ruby is so
freaking expressive?

  1. Interoperability — When you have applications in different languages that use the same configuration, then having a separate file makes a lot of sense. For example, when writing a JRuby on Rails app that  has bits of Java code (i.e. servlets w/ JDBC) that share the DB, you want to centralize your DB config to avoid having to do something nasty like generating properties files from database.yml.
  2. Security — Keeping config details, like DB login information out of the source is a good idea. It’s more secure because you often have a lot of sensitive information in your config files. The less places that information appears, the better. They should, ideally, not be checked into source control. For some reason, I feel more uncomfortable with the idea of not checking in source files than I do yaml files.
  3. Convention — Rail’s database.yml has a very stable structure. Keeping it as a YAML file encourages developers to not muck about with it. Why do this? There are times when having less expressivity is better because it’s harder to shoot yourself in the foot that way. It makes adding unnecessary behaviors more awkward. For database connections, this makes a lot of sense because they should not usually have a lot of logic around configuring them.

I generally agree with Joe on the ugly use of ERB in yml files, at least for things like data store configuration. When I see that or find myself doing it, I have a little a sense of “you’re doing it wrong!” Code smell, indeed.

I also think that the YAML vs XML vs JSON discussion is important here, because YAML as a language has some interesting properties that make it well suited to config type situations. In particular, I’m thinking of the ability to name chunks of the document and substitute them in other parts of the document in an override-able manner.

For example, in YAML, a set of configurations where one inherits from another might look like

development: &default
  adapter: foo_store
  port: 1337
  database: base_development
  <<: *default
  database: base_production

The equivalent in Ruby could be represented something like

#using 1.9 syntax, so it looks more yamlish
config_hash = {
  development: {
    adapter: 'foo_store',
    port: 1337,
    database: 'base_development'}
config_hash['production'] = config_hash['development'].merge(
                                                database: 'base_production'

Which I don’t think is quite as easy to scan.

I guess my point is that while Ruby is very expressive and powerful, sometimes a more constrained language can better express config information in a declarative manner.

Comments are closed.