Archive for May, 2009

If I had more time, I would have written less

Friday, May 22nd, 2009

The prolific Mark Twain wasn’t talking about computer programmers, but he could have been.

There are a lot of differences between excellent computer programmers and your average, run-of-the-mill hackers. But there’s one major difference, and it’s subtle but critical. And, in my experience, it doesn’t have anything to do with age or tenure.

Great programmers can accomplish the same thing as run-of-the-mill hackers with a lot less code and a lot less complexity. I’m not talking about the kind of code you write for the IOCCC contest or Perl golf. I’m talking about simple, readable, minimal code that gets the job done.

It’s story time

A couple years ago, I was sitting in a room with some great programmers. Management had asked them to solve an engineering problem. The problem seemed hopelessly complicated, and most of our engineering team had put it on the back burner because it was so unapproachable. Finally management forced the problem on us, and we all sat down in a conference room and brainstormed solutions. Ideas slowly began to emerge. After 30 minutes, the engineers had produced lots of complex ideas to solve the problem: client/server approaches, database-driven approaches, roll-your-own-Linux-distro approaches, and so on. All the ideas scared us. At that point, a light turned on. Ideas started getting simpler, and simpler, and by the end of the meeting we had whittled the solution down to something more elegant, a simple Python script that Byron hacked out in a couple hours.

The point of the story is this: Great programmers produce simple solutions.

The converse of this point is that bad programmers produce huge, complicated, and expensive solutions.

It’s time for another story.

To protect the guilty, I won’t share any specifics. I’ve heard tell of a team that had produced a piece of software over the course of a few years. The software had, as usual, grown to be quite complex, and the engineering team had grown to a dozen people. The software was deployed at a few customer sites, and was reasonably successful. I talked to some of the users, and every time the story was the same: “This software is so complicated”. The users weren’t judgmental. I think they just assumed that the problem was hard to solve, so the software was hard to use, and equally hard to write. One of the most complicated parts of the software was its installation procedure. It required the user to run several scripts in a custom csh environment. The user had to become an expert in a lot of areas unrelated to the problem domain. Customers approached the team and asked them to package the software in a standard installer format for Linux. The engineers dutifully estimated how much this would cost, and came back with an estimate of nearly … are you sitting down? … a half million dollars. Why so expensive you may ask? Their software had grown so complex and so hard to maintain, that a simple change like this would cost hundreds of thousands of dollars. Customers agreed (great customers, eh?), and the team went to work. After a few months, the job was so badly done, that the installer wasn’t “standard” at all, and it totally failed.

Why does this happen?

I don’t know for sure, but I think this blog post might give a hint.

Design Patterns: Easy to Write, Hard to Recognize

Tuesday, May 5th, 2009

Have you made this classic programming mistake?

You’re 2,000 lines into developing this awesome framework that is going to make your team’s life so much easier when you realize that you’ve just done it:

You just reinvented the wheel.

This happens because you are a programmer, and therefore you are lazy. You love to write code, but you hate reading it. Reading code is for computers, you tell yourself, and you are, after all, made of carbon not silicon, so there. Plus, you write Perl, so it’s basically impossible to read anyway. But back to design patterns…

Design patterns are great because they provide a common vocabulary that helps developers communicate complicated ideas with a few short words like “Observer” or “Singleton”. If you’ve ever read a book on design patterns, I bet the first thing you did afterwards was implement one in your current project. That’s what I did. If you’re thick like me, which you obviously are, because you’re reading this drivel (be honest with yourself), then you probably missed the main point of design patterns. The main point of design patterns isn’t to give you something to code up. They exist to help you recognize patterns in code that already exists so you can reuse it in your project. Sure, you’ll implement one once in a while, but you really ought to be using them more than you’re writing them.

It’s story time

I recently spent some time with a friend reviewing his software project. It was a Qt/C++ user interface project in its infancy. He’s a super smart guy, and a good programmer. He knows Qt pretty well, and he knows that one of the things that makes it great are its signals and slots. Signals and slots are awesome. They make it so you can easily interact with the Qt library with very little work. They tell you when a user clicked on a button or changed some text in a text box, and things like that. In a nutshell, they let your code “observe” the state of things. Back to my friend and his model/view. For my friend’s model, he implemented the observer design pattern. This required each of his classes to implement an Observer or an Observable interface. He used C++ vectors to store pointers to each Observer so he could notify them of when things changed, and wrote all the code to add and remove new Observers on each Observable object. He was careful not to leak memory, or hang on to deleted Observer instances in each Observable. Great, right?

Head scratching time

Yes, my friend reinvented the wheel. Qt already provides the observer design pattern. Qt calls them signals and slots. Yes, you can define your own signals and slots, and Qt manages all the “observer” stuff for you, and I guarantee Qt does it better than my friend’s code (less memory, faster, etc etc). So now my friend has two observer design pattern implementations in his code base, one from Qt and one he coded up himself. Which one do you think has fewer bugs? The one that’s been around for 10 years and used by thousands of people, or the one he hacked together in a few days at work? Oh, and by the way, Qt’s signal/slot system handles crossing thread boundaries too. I’m telling you, signals and slots are awesome.

Why does this happen?

The answer is chilling: Those who fail to read the documentation are doomed to reimplement it (apologies to Mr. Churchill). The next time you are reading an API documentation, try plucking out the design patterns, and boiling the library down to its essence. What does this library really resemble, at its heart? How could I describe this feature in 3 words or less? You may be surprised by what you see that has been there all along.