Montag, 26. November 2012

An XML configuration file frakkup

Only recently, I came across an XML configuration file for a web app that looked something like this:

<environment name="global">
    ...
</environment>
<environment name="production" extends="global">
    ...
    <database>
        <host>IP1.IP1.IP1.IP1</host>
        <user>...</user>
    <password>...</password>
</environment>
<environment name="staging" extends="production">
    ...
    <database>
        <host>IP2.IP2.IP2.IP2</host>
        <user>...</user>
        <password>...</password>
    </database>
</environment>
<environment name="development" extends="production">
    <database>
        <host>IP3.IP3.IP3.IP3</host>
        <user>...</user>
        <password>...</password>
    </database>
</environment>


I'm sure that, when they started things that way, there seemed to be good reasons for it. Still, I maintain that there are two Really Bad Ideas(TM) in there, and they are glaringly obvious:

1. Environments inherit from each other. This is just wrong - different environments may inherit from a common base, but they do not depend on each other in any way. Development machines are, by definition, different from the production machine. Remember, the reason we use inheritance is NOT to avoid code duplication, but to model realistic relationships between objects and classes of object in code.

2. The database host IPs (along with other addresses not mentioned here) are hardcoded in every single environment.

At one point, they had to change the database entry of a staging environment to point at the production database for some reason. Then change it back. Then change it to a completely new address...

Add to that the fact that there were really two different staging environments. Add to that the fact that they had to do this in several git branches, with tiny but important differences. Under fierce time pressure, of course, and with one new guy on board who hadn't quite grokked the whole jazz yet. Imagine the chaos that necessarily ensued. (It gets even funnier once you know that the addresses often differed in only one digit, so one had to look twice and remember which one was correct.) Imagine how often this went wrong. Imagine the understandable frustration on part of the developers, the CTO, and the customer.

The solution is so obvious that it's almost embarrassing to spell it out: Put the database entries into their own entities, and untangle the environments. Might take 30 minutes to do so, and will spare them tremendous suffering in the future.

<database name="productionDb">
    <host>IP1.IP1.IP1.IP1</host>
    <user>...</user>
    <password>...</password>
</database>
<database name="stagingDb">
    <host>IP2.IP2.IP2.IP2</host>
    <user>...</user>
    <password>...</password>
</database>
<database name="developmentDb">
    <host>IP3.IP3.IP3.IP3</host>
    <user>...</user>
    <password>...</password>
</database>
<environment name="global">
    ...
</environment>
<environment name="productionEnv" extends="global">
    <database references="productionDb" />
    ....
</environment>
<environment name="stagingEnv" extends="global">
    <database references="stagingDb" />
    ....
</environment>
<environment name="developmentEnv" extends="global">
    <database references="developmentDb" />
    ....
</environment>





Of course, it is perfectly possible that the XML specification doesn't allow for that, in which case... tough luck; it really just shifts the responsibility from whoever wrote the config, to whoever wrote the XML spec (I was unable to find it, sadly). In an XML describing a server configuration, you sure want to be able to reference every entity from every other entity. After all, it's basically just another way to describe objects and their relationships. And you surely wouldn't copy the database descriptor into every single object in any somewhat sane OOP environment!

The most interesting part, to me, is that this is not a major frakkup, not by any means. It's a detail. But those minor frakkups add up, they crawl on each other's shoulders and become major frakkups over time, and at some point, they can easily endanger the success of a project or a whole company.

And that, my friends, is just sad.