Inconsistent APIs Are Costly

Imagine that you're nearing the end of a productive day. Just a little more work to do to finish a feature. Then, your customer calls about a problem. You form a few ideas about the cause as you listen to your customer describe the problem. You stash your changes for the nearly complete feature and don your bug-hunting hat.

To mimic the problem on your machine, you boot the Rails 2.3 application in production mode.

$ script/server production

Sure enough, the application doesn't properly update a record.

You fire up the console to inspect the record in question.

$ script/console production

Hmm. The record doesn't have the values that you just saw in the web browser. After a little more time exploring in the console and not seeing what you expect, you go directly to the database. Yes, it's the same thing underneath it all, but you're quite puzzled at this point.

$ script/dbconsole production

It's no surprise that what you see in script/dbconsole is the same as in script/console.

We are running in production, right?

Then it hits you! script/server, script/console and script/dbconsole may not be running in the same environment. You scroll back in your terminal and see that your local server is running in the development environment.

/doh by striatic
Image Credit: /doh by striatic

How'd you miss that? Inconsistent APIs among script/server, script/console and script/dbconsole. Here's the output from running each of them with the --help option.

$ script/server --help
Usage: server [options]
    -p, --port=port                  Runs Rails on the specified port.
                                     Default: 3000
    -b, --binding=ip                 Binds Rails to the specified ip.
                                     Default: 0.0.0.0
    -c, --config=file                Use custom rackup configuration file
    -d, --daemon                     Make server run as a Daemon.
    -u, --debugger                   Enable ruby-debugging for the server.
    -e, --environment=name           Specifies the environment to run this server under (test/development/production).
                                     Default: development
    -P, --path=/path                 Runs Rails app mounted at a specific path.
                                     Default: /

    -h, --help                       Show this help message.
$ script/console --help
Usage: console [environment] [options]
    -s, --sandbox                    Rollback database modifications on exit.
        --irb=[irb]                  Invoke a different irb.
        --debugger                   Enable ruby-debugging for the console.
$ script/dbconsole --help
Usage: dbconsole [options] [environment]
    -p, --include-password           Automatically provide the password from database.yml
        --mode [MODE]                Automatically put the sqlite3 database in the specified mode (html, list, line, column).
    -h, --header
$

Even if you're new to Rails, you likely know that script/server requires the -e flag to specify an environment other than the default, development. I can't count how many times I've run the command correctly. At the end of a productive day when I was tired, though, I just ran it like I had been running script/console and script/dbconsole throughout the day, without -e preceding production.

Notice also that script/console expects [environment] [options] while script/dbconsole expects [options] [environment]. Fortunately, that didn't bite me and compound the problem.

Rails 3.0 3.1 is better

The inconsistencies among script/server, script/console and script/dbconsole described above are from the scripts included in a Rails 2.3 app. Unfortunately, Rails 3.0 is no different. Although Rails 3.1 addresses the inconsistency between rails console and rails dbconsole (the commands were renamed in Rails 3.0 and later), the inconsistency between those two commands and rails server remains. It probably will for the foreseeable future: the server command has expected -e for as long as I can remember. Perhaps the inconsistency can be discussed when the next major release is on the horizon, since addressing it will break backwards compatibility.

Conclusion

Inconsistent APIs slow us down and frustrate us, all the more so when we aren't at our best. They cost us time and therefore cost our customers money. Keep your APIs consistent, and know which ones among your tools are inconsistent.

Craig Demyanovich, Software Craftsman

Craig Demyanovich is an avid hockey player and loves visiting new places with his wife Sandy.