Monday, 6 June 2011

I Make Life a Bit Easier for Federal Prisoners

Writing computer code is an art form. Once you become familiar with someone's style you can recognize it the same way that you would recognize the writing style of a favorite author, or the musical style of a composer. Everyone has his little habits and personal quirks. One of my quirks was that I insisted on absolute neatness. My columns would line up precisely; comments would appear in consistent places. And, code was as brief as possible. If I could combine two or three steps in one line of code, I would. If an operation was going to be repeated more than once, it would be written as a subroutine or function--even if the data types were different. I'd handle that in the subroutine.

In other words, my code was as compact and efficient as I could make it--as well as looking good.

Another feature of my code was that it worked. You might think that of course it should work, shouldn't all computer code work? Yes and no. I've seen a lot of code during my time that not only did not work, but had potential nasty side-effects. As much as possible, I ensured that my code would do only what it was supposed to do and nothing else. A manager once gave me an assignment to write a function for a complex application. When we tried it as a test, the program failed. The boss was not surprised. Everyone's code failed on the first run-through. But, in debugging I found the problem: it was not in my code, but the data was not in the format it was supposed to be. In other words, the database manager had screwed up and my code worked perfectly. I'll never forget how amazed they were that my code actually did what it was supposed to on the first run, once you discount the data error. Those sorts of events confused me somewhat. If code does not do what it is supposed to do, then what is its purpose?

As I moved from computer site to computer site I took my programs with me. There wasn't much point in re-writing something I had already done. But, I noticed a curious thing when I returned to a site after having been somewhere else for a month or longer. My code would have someone else's name attached to it. To add insult to injury, there were changes that made the code not as clean and efficient--and would sometimes make the entire program, or significant parts of it, fail. The true professionals who were familiar with my coding style recognized that my code had been tinkered with by someone else. Lines of code would suddenly not be lined up, spelling errors would appear, inconsistencies would pop up, and code was suddenly not as concise and carefully delimited as it could be. Another thing: I simply didn't do some of the idiotic things that they did under my name.

Ironic situations would arise. For example, I once worked at a few sites with another consultant. I had a good reputation and stayed in touch with people I had worked for, sometimes running into them again and again in different circumstances. I was told that this joker would take my code and, as he put it, change it to a standard format. The only changes he ever made were to erase my name and put his in its place. He had the gall to telephone me once to complain about a program I had written some five years before. He admitted that, yes, it had run every day without fail for five years. The obvious question is: What changed? He insisted that nothing had changed and he wanted me to drop everything and rush to where he was working to fix my code. I wasn't buying any of that bulls**t. A few days later one of my friends who was working with this clown called to tell me about what really happened. The slimy bastard had modified my code to make it "more efficient," and, now that it no longer worked, he was trying to blame me. Eventually they restored my original code from backup tapes and the problems went away.

Talking about bad code, when I arrived on contract at Corrections Canada the first assignment I was given was to determine if there were ways to speed up the backup process. A full backup of all of Correction Canada's regional computers was started at midnight every Saturday. The entire process typically took from ten to twelve hours, sometimes longer. The problem was that while the backup was running the computers were inaccessible--and while the computers were inaccessible no visitors were allowed into or out of any federal prison anywhere in the country. Relatives and friends would line up Sunday mornings to visit the government's guests, hoping that the computers would be back online before visiting hours expired.

The code I looked at was a bad joke. The full backup ran Saturday while incremental backups (backup of only the data that had changed since the last full backup) were run Mondays through Thursdays. There was no backup run Fridays. (Don't ask: that wasn't my problem.) So, the first thing such a program needs to know is: what day of the week it is. I read through the code, block after block of it marked off with If today .eq. "Friday" then... skip the following. And nested inside the check for Friday was a block like this: If today .eq. "Saturday" then... execute this code, else execute this other code. To make things worse, the program never did figure out what day of the week it was until it came to the final section of code, and then it would recall itself (run the entire thing again), this time with the day of the week information.

Common sense says that the first thing you do is find out the day of the week. If it is Friday then exit, quit, don't do anything else, just stop right there, we're done. If it is Saturday, then execute the program that contains the code for a full backup. If it is not one of those days, then execute the program that contains the code for incremental backups. And, in the event that they ever do decide to run a backup on Friday, make it simple to change the program so that it would run on Friday--or perform a full backup on a different day of the week. I cannot understand why anyone would want to approach it differently.

Then I addressed the problem of getting those backups done more efficiently, and hence faster. I looked at my resources: I had four high-speed tape drives available. It made sense to keep them all busy simultaneously (unlike the earlier code which accessed them one at a time). The solution to me was to create a queue with a list of all the backups to be run. This queue would release the jobs, one at a time, to whichever tape drive was free. So, we start with four tape drives busy, but, how do we make sure that they will all be busy until the entire process is finished? I doodled a lot with pictures of a tube breaking into four channels and it hit me. The most efficient way to arrange the backup jobs was order of size, processing them from largest to smallest. Think about it. Drive number four should finish the first round of backups first because it is processing the smallest of the four jobs, so it will immediately start processing the next largest backup. And so on. As each drive is freed up, it takes the next largest job. This could mean that one tape drive could spend the entire time on one huge job while the others race through the smaller jobs, but so what: in the end they do roughly the same amount of work in total.

With my code, the entire full backup took two hours to complete. That's down from 10 to 12, or more hours. At 2:00 am Sunday, Canada's prisons, could, in theory, start processing visitors.

You can guess what happened next. Nine months later after I left Corrections Canada to move on, my name disappeared from the programs and they suddenly started failing and having other problems. If only people would get over the idea that they have to fix things that are not broken, remove the name of the original programmer, and then insert their own name.

Have I ever mentioned that there were (and probably still are) a lot of phonies and fakes posing as "computer experts" getting paid large salaries? That sort of thing is easier to get away with in the government than in the private section where you are expected to produce results. In the government accountability is a very rare commodity and it is always easy to blame someone else. I'm proud of the work I did, even if I did make the occasional mistake. I do know that years afterwards some of my code with my name still attached was still running, as reliably as it should be.

No comments:

Post a Comment