Colin Hamilton's Blog

Keeping software soft

Software has become an everyday word, but we don’t often think about what it really means. I’m very interested in linguistics and etymology, so I started thinking about this recently. It’s maybe not too hard to think of computer programs as being “wares” — a consumer good. But what’s “soft” about a computer program?

The term software was originally coined to contrast with the pre-existing term “hardware.”1 The pair of words is meant to suggest the dichotomy of the computer. There’s the physical, “hard” computer itself — the wires and circuits that are pretty much stuck in place once they’ve been manufactured and connected. Then there are the programs that run on the computer — they’re not made out of metal, but rather exist in the computer’s memory.

The parts of a computer’s behavior managed by its hardware are very hard to change: you’ll need to turn the machine off, take pieces out, manufacture new pieces, and carefully connect it all back together. But behavior in software is easy to change: just find where the instructions are stored in memory, delete and add instructions, and then you can re-execute it with new behavior immediately. That’s why it’s thought of as “soft” — it’s easier to work with than the physical parts of the computer.

For me, the terminology brings to mind the creation of pottery through clay. Wet clay is soft, and yields easily beneath your fingers, letting you shape it however you want. When the clay is fired, it becomes hard: sturdy and reliable, but also impossible to change any longer. Software is wet clay, and developers are the potters. We keep the clay wet so we can continue to change its structure, constantly experimenting and fixing things.

Coding is at its most fun when it feels like that, like the whole system is bending beneath the movements of your fingers, like you have complete creative control. That’s what coding is supposed to be like.

But in practice, I don’t think a lot of developers feel like working with code is like this. Maybe at the very start of a project, when it’s a completely fresh lump of clay on a pottery wheel. But for developers working on large or old codebases, it can seem like the system fights against the changes they try to make. It’s like clay that has started to dry out and harden.

And when this gets really bad, working with code can come to feel constantly frustrating, even painful. Whenever you try to make a change, you encounter roadblock after roadblock. Just understanding the code enough to change it might be difficult. Then when you make a change it causes compiler errors in modules you didn’t even know existed. When you fix those, tests start breaking that seem completely unrelated. And even when those are fixed, you just know that probably some other things got broken too that there aren’t tests for. Instead of bending pliably like wet clay, you instead find it cracking and breaking whenever you press against it.

How does code get like this? Bit by bit, and piece by piece. It happens over the course of hundreds of changes, with a small dependency added here, a wacky workaround introduced there. A tight deadline where we need to add this new feature and don’t have time to write tests. A code reviewer who doesn’t understand the change but approves it anyways. Dozens of thoughts of “this is getting messy, we should refactor it” that never get followed up on.

Once code has gotten to this state, it’s almost impossible to salvage it. The clay has been fired, and it’s pretty much stuck in its shape now. No one wants to admit it, but the code is doomed. Either the organization will need to make a massive investment to rewrite everything from scratch, or, more likely, they’ll just find themselves spending more time and more money on each incremental change until they either abandon the project or go out of business.

There are a number of problems that can lead to this, but the simple, underlying explanation is that the developers didn’t keep the software soft. As they kept adding complexity to it, they allowed it to harden and eventually solidify.

If you let your software get hard, then you’re dooming the project in the long term. The value that software provides — the reason it revolutionized the world in the last half century — is flexibility, which enables experimentation, which allows for optimization. This is the competitive advantage of effective software companies, and it’s completely lost when the software becomes hard.

So, how do you do it then? How do you keep software soft? In short, you fight against complexity. Complexity is the heat that works to harden our clay. Every time the code is changed, some new complexity is potentially introduced. The best developers keep a constant watch for this creeping complexity and provide a counter-force to fight back against it. There are many different specific strategies for doing this, and developers grow and improve by continually seeking out and learning new ones. But the same underlying motivation stays there to guide us: keep the complexity under control.

Software development is working with clay. The best developers keep it soft.

  1. https://web.archive.org/web/20110726102157/http://www.niquette.com/books/softword/part4.htm