Archive for May, 2006

On the Importance of Naming

Saturday, May 27th, 2006

Programmers typically don’t worry much about naming within the code.  After all, the user isn’t going to see what your variable are named.  You know what they do; so what if you’ve got variables named a, a2, and _a?

The beginning of wisdom is to call things by their right names.  Giving a proper name to a module, class, method, or variable is a sign that you truly understand what it’s supposed to do.  In fact, the very act of searching for a name can often help you figure this out.  It’s a process of determining the component’s true identity.

If you can’t think of a good name for the component, there’s a good chance you don’t really understand what it should be doing.  Time to rethink your design.

There’s also the perception that the internal names for things need not match their external names.  The problem with this is that you impair communication between users, designers, and developers.  Bug reports from users will come in with their external names.  There’s a cost in mapping one name to another every time you get a bug report, and if you’re writing any kind of serious applications then you’ll have an awful lot of bug reports.  Changing the name of the component need only be done once, but you’ll have to deal with the mapping every time.

Then there’s the matter of new developers coming onto a project.  The more obvious and concrete your component names are, the easier it will be for them to get up to speed.  Let’s say you’re exploring an unfamiliar codebase that you know is an e-commerce suite of some sort.  You come across a module named “Process.”  Quick, what do you think it does?  One guess is as good as another.  On the other hand, if the module were named “Checkout”, you’d have a pretty good idea what it does before even opening up the source file.

Good names should be short and distinctive.  Many programmer, once they get past the a, a2, _a approach to naming go the other extreme and start naming variables number_of_orders and products_to_be_saved_to_disk.  A name that is too long will clutter up the code and make it hard to read, which is only slightly better than being short and cryptic.  num_orders and queued_products are about the right length.

Poor names are often not the result of a poor initial name choice, but instead a result of the natural organic change of the code over time.  The module may evolve to take on a different role, or it might stay static and the rest of the application changes around it.  Either way, the result is to make a once-good name obsolete.

As soon as you realize the name is no longer appropriate, take a moment to change it.  It’s easier than you think.  With modern search and replace tools (or the old fallback “perl -p -i -e ’s/old/new/g’ *”), version control, and even IDEs with refactoring menus, there’s just no excuse for a bad name.

Just-In-Time Design

Thursday, May 25th, 2006

Software is traditionally created with the same basic approach that one would take doing any other kind of engineering - say, building a bridge. The architect lays down a detailed blueprint; during construction, the design changes very little. Let’s call this up-front design.

Despite decades of building software in this fashion, no one has been able to get it to work as well as well for software as it does for bridges. Software is different because it’s soft. You can, and usually do, make massive changes to the design over the lifetime of a project. In most cases version 4.0 of a product has almost nothing in common with 1.0. It would be like if halfway through building the bridge, you decided to make it a boat instead.

This would be insane for a bridge, but - counter-intuitively - it’s actually possible with software. More than possible, in fact: it works better. This is what extreme programming proponents call evolutionary design. It’s what I like to call like to call it “just in time design” or “iterative design”. First, the bullet points.

  • Take small bites
  • Do the simplest possible thing that will work
  • Degrade gracefully
  • Release early, release often
  • Don’t be afraid to change the design mid-stream
  • Throw in unplanned icing when it’s easy to do so
  • Drive new features based on feedback, not speculation
  • Keep the momentum going

Let’s look at each in turn.
(more…)

Error-Prone Modules (or, When You Can Sense a Refactor)

Tuesday, May 23rd, 2006

No software project can stay healthy over the long run without ongoing refactoring. My off-the-cuff estimate is that you should spend 5 - 10% of development time on any active project refactoring existing code.

But when and where should you refactor? Much as we all hate to admit it, there’s always at least a few dark corners in any codebase that could benefit from a bit of housekeeping. Trying to keep everything spic-and-span absolutely all the time is counterproductive. So it’s important to be able to tell when a refactoring will really be beneficial, as opposed to just setting your obsessive-compulsive developer mind at ease.

The most obvious refactor-needed signal is when you try to add a new feature and find that the module you need to modify needs to be reworked in order to support it.

A less obvious occasion is what Steve McConnell calls error-prone modules. These are the sections of code that just keep breaking. Every bugfix you deploy seems to produce two more bugs a day later. You find yourself getting exasperated when you see a bug report come in for that module, and keep thinking why.. won’t.. this… stop… sucking?

If a module is producing a disproportionate number of defects, that’s when you know something is rotten on the inside. It may just be a matter of tangled code, but more likely it’s a fundamental design issue. Perhaps one object is doing too much, or too much closely0related functionally is spread out among several objects. Maybe the original developer thought they’d be clever by using some language technique or browser feature in a way they weren’t design to be used. Or maybe the functional spec is just too complicated, and the developers need to get together with the product designers and try to come up with a simpler way to achieve the same user goals.

I use the three-times-the-charm rule. One bug - sure, this is software, just fix it. Two bugs in the same area of code - ok sure, fix it that too. Three bugs - dig deeper, it may be time for a refactor.

Uphill in the Snow

Sunday, May 21st, 2006

I spend a lot of time thinking about software. In this, I am hardly different from most software geeks. But I have always gotten the impression that most geeks enjoy technology for its own sake, and in that I differ. Software (and technology in general) interests me because of what you can do with it. In 2006, software can and does serve as an incredibly powerful tool - and we’ve only barely begun to scratch the surface.

Although I do get plenty of chance to talk about software with the incredible team of developers at Bitscribe, there’s a different satisfaction which can be gained by writing about it. Structuring ideas in a way that is suitable for the page helps to crystallize the ideas in the mind of the author. Hence, this blog.

I got interested in programming at a very young age, which is not uncommon. Like most kid-programmer-wannabes, I dreamed of writing video games. This remained a passion of mine throughout my teens and into early adulthood. Sadly, my dream was shattered by the very act of achieving it. After working as a programmer in the video game industry for many years, I figured out that this wasn’t quite what I was looking for in a career. But I emerged from that experience with a passion that ran deeper than my original dream, a passion for software development itself.

In the early days, anyone who wanted to make software had to interface with the computer at a pretty low level. Graphics, for example, required a knowledge of bafflingly arcane interfaces to access the video and audio hardware directly. (For a walk down memory lane, check out this article I wrote as a teenager.) In a certain way it could be very satisfying to finally discover the techniques necessary to do something like displaying an image on the screen. But the fact was that it made the creation of even relatively simple programs long and arduous. Yep, we definitely walked uphill both ways in the snow.

I dreamed of the day when programmers would use high-level scripting languages and abstraction layers which didn’t require them to interface directly to the hardware. I imagined that cutting out all the red tape required to program - semi-mysterious language constructs like #include, compiling and linking steps, varying CPU byte order and byte depths - would someday be automatically handled, leaving the programmer with nothing to do but focus on the purpose of the program itself.

I’m pleased to say that that day is here.

Of course, it’s not quite perfect. There’s plenty of red tape issues that modern programmers bump their heads against, usually related to installing and managing all the tools and layers of abstraction that allow us to create software at a high level. But it’s extremely minimal compared to even just a decade ago. It’s true: nowadays I really do spend most of my programming time programming.