As a student of Computer Science, a university can have two roles. One is to teach you how the very fundamentals of Computer Science and the other is to teach you how to think independently in situations which you may not have encountered before. Situations in which you can use your creativity and intelligence to develop better solutions. The latter is highly important because that is the one which makes use of all your gray matter. But now I feel it may not be so important.

How many jobs can you think of in the industry where you will be working on something new? Something exciting? Something that will keep you up at night trying to think out an elegant yet logical solution? Not many I would say. Most of the time, when you join a place as a Software Developer or a Programmer or an Analyst, you will be working on something that has been developed by someone else. Sometimes it will be interesting, most of the time, not. Most of the time you will be maintaining, and not developing. It is no one’s fault, it just the way industry works.

The Software Developer is dead. Long live the Software Maintainer.

I needed a table to store some text and its index in a list at which the text occured. So as part of my migration, I decided to make sure the schema did not add to my legacy database structure, but relationally associate it. So part of the schema involved specifying the ‘index’ column, which I defined as

CREATE TABLE `meow` (
`index` tinyint(3) unsigned NOT NULL DEFAULT 1,
......
) ENGINE=InnoDB

Now I thought I was safe as I had not used something like int(11), something unfortunately I have come across previously *shudder*. Off I go, happily plodding along with my model and code, till I actually needed to implement the association.

I wrote a simple spec test for it:

Cat.meows = Meow.new(:index => 2)
cat_meows = Cat.meows
cat_meows.should have(1).meow
cat_meows.first.should be_a_kind_of(Meow)

And then inside my model Cat, I had:

has_many :meows, :foreign_key => 'cat_id', :class_name => 'Meow'

Seems simple, doesn’t it! AHA! You fool! You thought you could do this and life would be easy and wonderful and the world would make sense!
Such naivete! Adorable!

When I ran the spec and started getting errors which interpreted the `index` as boolean, I was intrigued. Looking at the API, I find this:

By default, the MysqlAdapter will consider all columns of type tinyint(1) as boolean. If you wish to disable this emulation (which was the default behavior in versions 0.13.1 and earlier) you can add the following line to your application.rb file:

ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans = false

Now while the fix seems simple enough, I would like to point out that this is a very neat and elegant solution for a problem that simply should not have existed! Had Rails made the assumption about a `bit(1)` field, then I would have been fine. Had they made the assumption about `tinyint(1)`, even then I would not have complained. Even the MySQL docs list `tinyint(1)` only as a boolean. Anything else, is simply not a boolean. Rails however, treats all declarations of `tinyint` as booleans. Which is annoying! Not hard to fix, not complicated, but annoying.

Why couldn’t they make that assumption about the `bit` field ?

Today was fun. A lot of fun! I paired all day today with Jared Hunter from operations and we spent all day deploying about four applications written in three different languages to two different environments using three different deployment tools. And today’s attempts have made me realise a lot of things

….

OK fine, I am lying. It wasn’t a lot of things!!!

But this experience has made me realise a few things!

Operations are over worked. I knew this fact of course. I knew this in the same sense as I know getting shot or being stabbed hurts. There is a lot of difference between knowing and realising. We spent nearly two hours in total debugging failed deployment because certain assumptions were made in the applications which did not coincide across all environments. Sometimes the environments were at fault, sometimes the applications.

I have learnt that one cannot leave deployment towards the end of the iteration. It must be planned at the same time as when we kick our iteration off. When we discuss the work planned in the iteration, it is at that point, we must write our deployment notes, and keep adding to them as work keeps getting done. The deployment notes should be nothing less than a technical card and must be approached by the business in the exact same way as developer asking to remove some technical debt.

The problem with leaving deployment planning towards the end of the iteration is that people have to now remember work they did at the start. Do it at the same time as you hand over the card to QA and you are done with it; no more chasing up after the fact.

I have learnt that having consistent deployment procedures when you deploy applications written in three different languages is not possible. Layers and layers of decoration buffers must be applied between the deployment procedure and the applications for that to happen and God help you if you have to then debug something. Java is very different from Ruby and Perl. And even though the latter are both interpreted, the way they manage dependencies and interact with other system layers is different. At least the way we do it. Choose one platform, if you can, and stick with it, if you can. It makes deployment, debugging, rollbacks and dependencies much much easier.

I learnt Puppet is very cool. I managed to give access to a bunch of users across different environments, documented the change and kept the history of the change for posterity using puppet in a few simple steps. I will however have to shelve my idea of using Babushka and Puppet together. (I think I had had too much coffee at that time).

Last thing I learnt is that canadians have a very good sense of humour, no matter how much you needle them about maple syrup, or ice hockey or you know, basically being Canadian. They are a lot of fun to work with! Mad props to Jared and Kerri for giving me that belief. Come to think of it, even the tree we associate with Canada, the Maple tree and the tree associated with Kashmir, the Chinar tree are similar.

Recently we started working with database migrations via Liquibase. Even though we have used ActiveRecord migrations extensively in the past here, because a lot of our work in another part of the team was in liquibase, and the fact that we would run liquibase via a rake task, we decided to go with it.

First thing that hit me is that because Liquibase uses XML as its source code format, it is not as readable as Active::Record migrations, but it does allow a lot of hooks. You can set context on a bunch of migrations and run them together should you want to (something that comes in very handy for seeding a database). Dependencies and pre-conditions are also handled and in case the latter fails, you can set up logical paths of executions. And as is the case with most decent and self respecting migration tools, a roll back is provided.

So recently I wrote a migration to add a few measly rows to the test database and ran it, confirmed execution, removed the data, called the QA over to show her that I had indeed done it. QA comes over, I run the migration, open mysql and show the contents of the database. and what do I get, nothingness :(.

Turns out, that Liquibase, like ActiveRecord writes to the DATABASECHANGELOG table in the database. But unlike the latter, when you rerun something without having run the rollback, it checked the mentioned log table, sees that it was run and exits, without any message to the contrary. So if you were looking at the output of liquibase when you ran it initially and when you ran it a second time, you would see no difference. *insert loud scream*

In conclusion; I like Liquibase, its simple, neat and allows a lot of hooks to do a lot of stuff, but its execution pattern leaves a little bit to be desired. Also, provide rollbacks if you use liquibase, or get in the habit of running DELETE FROM DATABASECHANGELOG;