With Software, the Code IS the Design

With Software, the Code IS the Design October 18, 2014

When you want to manufacture a new piece of hardware—an engine, say, or a stand mixer, or a washing machine—the first thing you do is design it. Some people equate “design” with the visual appearance of a product, as in the iconic look of an Apple iMac. I’m using design in a more technical sense: before you manufacture a product, you need to work out a whole bunch of things:

  • What it’s supposed to do
  • How it’s supposed to do it
  • What it looks like
  • How it’s assembled out of parts
  • What those parts are
  • Precisely how those parts are shaped, what they are made of, and so forth.

The end result of a hardware design is a thick stack of drawings (or CAD files, these days) that can be used to actually build the desired hardware. If you’re going to build one at a time, that’s all you need; if you’re going to build a lot of them, you go on to design and build the machines you need to make the parts efficiently.

Note that the bullet points above are more or less in the order in which you’d do them, going from the most general to the most specific.

Designing a piece of software is very different than designing a piece of hardware; the skill sets are entirely different. But the steps are similar. First you understand the need; then you figure out how to meet it; then you break that problem down into pieces; and so on. The problem is the engineering drawings. These drawings are how you share the designs for the parts with other people; you wrangle over them and discuss them, and finally agree on them.

This is part of the Quill code.  It's also the design for one of Quill's tools.
This is part of the Quill code. It’s also the design for one of Quill’s tools.

Software engineering theorists spend a lot of time thinking about design and how to capture software design with the equivalent of CAD drawings. Massive graphical languages have been devised to document software designs. (UML, I’m looking at you.) And all of them miss the point, which is this: a hardware design, as documented by a stack of drawings, is a set of information that is isomorphic to the physical hardware to be built. The two are one-to-one: each part has its drawing and associated data.

But a software’s program code is simply information. The only set of information that’s precisely isomorphic to the finished program without losing essential detail is the finished program. Any more abstract representation is either a program in its own right, or loses information and hence isn’t a complete design.

Productive software design, in my experience, starts at the top of those bullet items, above, and goes no lower than necessary to get the job done. If you’ve got multiple developers involved, you break down the problem into pieces and assign them to developers; and they repeat the process from the top for their parts. You worry about how the parts interact; but you don’t try to capture every bit of the design in some kind of overarching design document, because it’s wasted effort.

I could go on at length about the particulars of a good software design process, what you capture and what you don’t and what matters, but I’ll slide past that for now, to make my main point: the ultimate record of the design of the software is the software’s program code itself. And that means that the architecture of the software and the things a new developer needs to know need to be, insofar as it’s possible, discoverable from the program code alone. Oh, you can provide some high-level design documentation; it’s often useful, so long as it’s at a high-enough level that it doesn’t go out of date easily. For the specifics, though, it’s the code.

And that has implications for how you write your code—at the lines of code level, certainly, but even more in how you break up your code into individual files.

More on that next time.


Browse Our Archives