There seems to be a fundamental difference between building a physical product vs building a software solution.
For example, if you were asked to design a computer mouse, then I am pretty sure that you would come up with a design that is semi-ok. You would probably know roughly how big the device should be and roughly where the buttons would go.
The same applies for other physical objects. If you were asked to design a door knob – again you would know roughly how big it should be, how high up it should be fitted etc.
Often bad design in our physical reality is blatantly obvious and it is more often the result of people not thinking about what they are building or a failure of different teams not communicating.
But software is inherently different. Even with tons of meetings, trying to “communicate” as effectively as possible and spending millions of pounds on research things still are guaranteed to go horribly wrong.
But why? What makes software difficult? Why does it always go wrong?
Unlike physical objects, like cars, door handles or exit buttons, how big your software is meant to be is non-obvious.
In a recent interview, David Heinemeier Hansson said:
“Software, in most cases, is inherently unpredictable, unknowable, and unshaped. It’s almost like a gas. It can fit into all sorts of different openings from the same basic idea.“
Often when building a solution you won’t really know where to begin and where it ends. It can be as complicated or as simple as you like. It can use as many third party integrations or as many built in-house as you’d like. You can spend more and more time on refactoring, or not depending on what you would like to do. It truly is like a gas. It expands or contracts largely depending on what the creator of the software is trying to achieve.
Over and over again I see people and organisations who try to develop software and who miserably fail because they aren’t able to conceptualise the size / complexity of their software project.
There are two main reasons why software behaves like a gas.
The first is that you can endlessly play with code and make it more elegant. You can refactor, you can make it more object orientated, you can divide functionality, you can keep tweaking the UI, you can rebuild with the latest language or library etc.
The second reason is that software often is created to solve a problem. And solving a large problem often means solving several smaller problems. And solving the problem you originally set out to solve often means having to solve new problems you have just created.
For example, we at Hummingbirds Medical have a feature which allows family doctors to communicate with their patients via SMS, Email or by sending a Letter (which gets sent to the patient directly via our software, without the clinic themselves having to print off and physically send the letter). We thought while building this feature that we should notify the clinician of delivery receipts so that they would know which messages have actually been received and opened by their patients and which ones haven’t.
However, we resisted the urge to build more than what was immediately necessary. We knew that once clinicians could send their patients emails and letters that we would uncover a whole host of other problems (both with our software and new problems which the clinicians would like us to solve for them). And what do you know! Delivery receipts it turned out was waaaaaaay down the list and we still haven’t built it!
So my advice is always the same:
Make your requirements as small as you can possibly bear.
Make your project smaller!!
Now that I’ve given you this wonderful piece of advice you are free to go ahead and ignore it. However, don’t say I didn’t warn you. 🙂