Category Archives: Development

Know Thy Tools

A while ago, I was reading an issue of Dr. Dobb’s when I came across the assertion that programmers waste a significant proportion of time because they don’t know their tools well enough. And I think that’s probably right. But it doesn’t go far enough.

Earlier on the blog, there’s a post about the importance of having a broad and deep toolset. But both the Dr. Dobb’s comment and the earlier post focus on the development side of things. I think the assertion is just as true on the design side as well, although the perils may be a little different.

When developing, if you’re working in an IDE and you don’t know the intricacies of how it works, you’re definitely going to be working more slowly than you need be. When designing, if you’re working in a design tool and you don’t know the ins and outs, you’re restricting the scope of your creative output. That’s perhaps an even more catastrophic outcome!

Think about Photoshop, for instance. That tool is both broad and deep, and it gets moreso every cycle. Now that it will largely be available as a subscription only, the changes will just keep on comin’. But if you don’t know how the filters work, you may no longer have those design choices in your visual vocabulary to work with.

In contrast, if you don’t know how to do multi-file grep-based search and replace in BBEdit — something that is roughly comparable in terms of complexity and importance, I think — you have a bunch more work to do to get to the outcome, but you can still get there.

Regardless of the specific poor outcome, the lesson remains the same: know your tools. Whether you’re an information worker who lives in Word, Excel, and PowerPoint; a coder who lives in emacs, BBEdit, or Notepad++; or a designer who lives in the Adobe or Corel worlds, you’re probably missing out.

Besides, how can you complain about the limitations of your toolset if you don’t really know what they are? Think of the fun you’re denying yourself!

Making Comments Count

Earlier this week, Graham Lee wrote an opinion piece about what separates a good code comment from a bad one. It’s thoughtful and well-written, with plenty of examples and some excerpts from the relevant literature.

I must admit that my philosophy on code commenting has changed quite a bit over the years, as both I and my projects have gotten more sophisticated. (Well, the projects have gotten more sophisticated; I think I’ve just gotten older.)

When I was just starting out, commenting code seemed like a boring waste of time. Why on Earth would I spendwaste valuable time putting in comments when it was perfectly clear what the code was doing? Besides, I wrote the code, and I’d surely be the only one ever asked to maintain it, so there’s little point.

Of course, this was also a time in my career when coding projects numbered maybe into the hundreds of lines. So, arguably, there may have been some merit in the notion that comments wouldn’t have added a lot of value.

Then came the time when I needed to ACTUALLY go back and revise some code I had written years earlier. Yeesh. If there was ever a way to feel you had amnesia, this was it. I was looking at code I had written — I knew I had written it — but couldn’t recognize it for the life of me. I had gotten so much better in the language and the algorithmic design that I recognized the old code for what it was: a mess. And a virtually uncommented-one at that.

If losing a hard drive full of data is what makes most people fervent backer-uppers, getting baffled by my own historical code was what drove me to commenting. And in a multi-person team, it’s essential, since comments can also document required parameters and their meanings, and actions that need to be picked up by someone else. Heck, I even use comments to myself in the code to remind myself where I stopped work one day and where I need to pick up the next.

Beyond the act of commenting, though, there are some key differences between good ones and bad ones. But I’ll let Graham Lee pick up that ball. He’s done a good job of it in his article. Worth a read!

Data Structures Are Dead…Long Live Data Structures!

Eons ago, when I was first learning how to code, we spent a fair amount of time focusing on data structures at the heart of development. In that time, both memory and fixed storage were expensive and scarce, so by learning how the base structures worked (and learning how to code them up from scratch), we could pick the most economical version and save an extra kilobyte of memory or two — a precious commodity!

These days, neither memory nor storage are terribly expensive nor scarce (although in our networked environment, there are still reasons to conserve). So it may not be much surprise that there are many programmers who couldn’t write an implementation of a doubly-linked list or b-tree.

Yet it’s not stopping them from being productive, great developers. Why? Because in today’s framework and higher-level language-driven world, those lower-level structures are often abstracted away or handled behind the scenes. Take Cocoa, for instance, which has classes for arrays, sets, dictionaries, and more — all with optimizations and methods to do querying, modification, and more built in.

Sounds like unbridled progress to many, and I certainly agree with the ‘progress’ part. But unbridled? I’m not so sure. I continue to think there’s value in knowing how the fundamental data structures work — for at least two reasons:

First, in knowing the internals, you can make more informed decisions about which to use when. With Cocoa, for instance, Apple has released a whole set of tech docs about the best uses for each of the “collection” types. It’s helpful and well-written, but mostly superfluous if you have the underpinnings needed to internalize that kind of thing.

Second, there’s still a role for optimization. Hardware and networks continue to get faster and frameworks continue to get more efficient — but it is poor form to rely on those increases when you don’t have to. And to optimize, there’s really no substitute for knowing the basics of how things work.

So maybe we’re seeing the slow erosion of understanding about low-level data structures like stacks, queues, and heaps. And for some, maybe that’s OK. But I’m not ready to see them go just yet.

The Paradox of Black Boxes

When I was a young programmer, I was developing an application for a client — it may have been for Windows 3.1 or Mac System 6, I don’t remember — and my code just wouldn’t work. I banged my head against it for quite a while, and just couldn’t see any errors.

So I made an intellectual leap. One of youth and hubris, in part. I concluded that there was a bug in the system’s API. Somehow, in the millions of lines of code that comprise the (then-new) operating system, a bug had been placed that was causing my code to fail.

Incensed, I dashed off a bug report and posted indignantly to a programming community (probably on CompuServe or AppleLink). My unhappiness at the bug was trumped only by my self-righteousness at finding someone else’s.

But of course, you know the end of this story. My indignation and feeling of superiority evaporated quickly when the programming community noted no such error in THEIR code, which took me back to my own — where I found my problem. My happiness at solving the problem was eclipsed by my embarrassment.

This may be an anecdote borne of, as I mentioned, youth and hubris, but it also derives from another phenomenon: the black box. My code was relying on someone else’s code, so when mine didn’t work, it was intuitive to blame the mystery “other” code.

This happens all the time today — likely more than at any time in recent memory — because of the rise of modularized code. It is trivial today to take code libraries from multiple places, call a remote API or two, and package it up as a new application. In fact, in some cases, it increases one’s efficiency by several orders of magnitude.

This is the virtue of the black box. We can drop one in whenever we need specific functionality and we don’t have to do much to make it work.

The difficulty, however, is in provenance. Who knows how that code was written, or how well it works? You can get a sense of the latter often by doing some web searching, but if you are using a narrow-niche kind of code where few use it, or you are using a “black box” in a corner-case/niche-y way, you may not be able to rely on the commons.

So what’s the answer? Surely it’s not to build everything yourself from scratch. If that were true, we’d all be releasing our own versions of iPhone operating systems to go with our applications, and it would be worse than the Android fragmentation! (Kidding, kidding. Mostly.) Rather, it’s to be judicious when using external libraries and APIs, to do so where you can degrade gracefully if something breaks, and to code defensively, handling any errors or anomalies that could involve the foreign code.

Because even though it’s unlikely, it’s possible that next time, it really WILL be the black box code that’s broken, and not my application. And that will make my younger self smile.