Smart people can invent solutions to problems you don’t actually have yet. The problem is, it’s easy to think of problems you don’t have yet. Stopping to solve them all now is a recipe for paralysis.

– Chip Morningstar, Smart People Can Rationalize Anything

It’s important to focus on your current difficulties. And if you don’t have a current difficulty, pick any of your brilliant ideas and solve them in the simplest way first: with people. At MeshU 2008, Reg Braithwaite left me with some great advice: don’t automate what you haven’t already done manually.* And I hope I got that right, because he’s a smart guy and it’s stuck in my head now. What I do know is that anything you can do to increase your understanding of a problem will help you formulate a solution.

But you can’t really solve problems that don’t exist, because only problems have solutions – the absence of a problem necessarily implies the absence of a solution. Still, even the simple solutions of simple problems tend to reveal additional simple problems.

Here’s a real-world example. Several years ago, our developers designed a poll widget for our web sites. At the time, they didn’t have a semblance of the manual effort required to insert/delete/update poll questions. So they didn’t solve for it, and this was a very rational decision at the time, because it wasn’t a problem then. However, when it did manifest itself as a problem, they didn’t update their assessment of possible solutions. That’s why it’s important to revisit solutions over the course of their respective lifetimes; you need to keep solving the right problems while throwing away inadequate solutions.

It’s easy to neglect old features in light of new and exciting features, but that’s how projects get bloated to the point where anyone who touches the code gets this burning desire to just rebuild it from scratch.

Most people have a vague notion of the fact that new things get old, but it’s much rarer to find people who understand that old things get older. It’s not a binary definition. Things aren’t either “new” or “old”. They have an age that can be measured in continuous time units. It’s like how on the books, your company’s assets depreciate in value over time. That new widget-maker your company bought last week will have a different value after 4, 8, 15, 16, 23, or 42 years. Eventually, the machine itself has no value, but at any point in the interim, it does still have at least a bit. Accountants will take a look every year during tax season and advise the appropriate stakeholders that they need a new way to make widgets. And so a new machine will be purchased and the cycle starts all over again.

Software is the same way. Certain features depreciate in value over time. Eventually, those features no longer deliver any value to the end user and they become more costly to maintain than the benefit they deliver. That’s probably one of the best reasons to use a modular design that won’t break when you remove a feature.

But every project team has a different way of determining when a feature or product has lost its value. Ruby on Rails decided to *6 components after two years. On the other hand, Intel went on adding new features to their x86 chip for over 30 years without removing extraneous features: “The 8086 was the first processor in the x86 family launched in mid 1978. All future members are backwards compatible with it.”

Features – and feature sets – are built up from an initial spec, regardless of what methodology you follow. What’s important is how often you revisit those initial specs and evaluate them in light of the true, underlying requirements of the project, which themselves necessarily change over time. I agree with Jurgen Appelo’s concept of growing software rather than building it, although he’s wise enough to not claim it as his own :oP.

We also talk about building software. And (in many cases) that’s incorrect too. What we build are lines of code, design documents, and compiled assemblies. What we grow are user interaction, data repositories, social networks, and (for the systems that I grow myself) extensive bug reports and issues. The sum of all that we call software systems.

Software is versatile. It’s programmable (of course). More importantly, it’s re-programmable. To throw away that kind of power by refusing to acknowledge the changing nature of users, developers, business owners, and all their various, also-changing needs is a fruitless exercise.

Focus on delivering the best possible value regardless of your past decisions.

*The corollary is that if you’ve done something manually and it can be automated, do so.