Suppose that you arrange stones into a spiral on a sandy beach.
After meticulously arranging your stone spiral, the world seems hell-bent on destroying it. A dog steps on some of the stones, a big wave carries some of them away, and a child throws part of your spiral into the ocean.
There are many ways to form a spiral with those stones; countless millions of arrangements that enable someone to perceive a spiral on the sand. However, there is an almost infinite number of ways to arrange those stones that do not form a spiral. The odds are overwhelmingly in favor of your creation losing its spiral-ness simply because there are so many more non-spiral arrangements.
Now suppose that each stone is a tiny piece of a computer program. Like the stones, the individual parts of a program are carefully arranged to induce an emergent phenomenon. Instead of a spiral emerging from stones and sand, features emerge from logic and state.
The unpredictable world in which we live indiscriminately nudges our creations toward chaos. Features break because of minute changes made to those tiny pieces of the program.
What can and should developers do to defend their creations against unceasing entropy?
You should write a book “Zen and the art of software engineering”
I wish I knew how to do that!
Crazy glue 🙂
Yes! Crazy glue. 🙂
Is that another way of saying “immutability” perhaps?
So I’m thinking about it. Just like a garden, or any living thing (yes to me software does have a life and growth of its own), it needs to be properly tended and nurtured so that it grows as intended.
Similar to how skyscrapers in earthquake-prone areas are designed to withstand shaking, software can and should be designed to cope with environmental/external instabilities. Networks will go down, servers will crash, etc. This flexibility only handles a fixed set of predetermined problems. But what about problems that cannot be anticipated, such as changing requirements?
That’s where your gardening analogy fits in. Refactoring is like pulling out the weeds and removing diseased plants from your garden. Sometimes cleaning up isn’t enough, and parts of the garden must be overhauled. Long-lived systems subject to changing requirements have an ongoing need for “course adjustments” to align old code with new facts.
Is this all we can do, as software developers, to cope with the harsh realities of production code? Try to design flexibility for known problems, and deal with unknown problems as they come up? Are there more fundamental principles that could be employed in more intelligent ways? Are we missing something obvious, out of habit or lack of imagination?
If we are talking about big projects, I think it’s mostly down to the tools we use. In particular, I would encourage every app developer to try Elm (http://elm-lang.org); it’s a great language to write apps in because it’s simple, reactive out-of-the-box, bulletproof (meaning there’s no runtime errors) and easy to test and refactor, and on top of all that it teaches you to write better code in other languages as well.
I agree that tools make a big difference in the quality of software. Elm sounds interesting. Thanks!