Six easy pieces on thinking about sustainable code
Your application is on fire. Something is consuming it, a process converting fresh and shiny code into rigid, opaque legacy code.
Seriously, your applications is on fire. You should look into it.
Are you going to fight the fire? Will you keep throwing logs into it, hoping that you can corner it at some point down the line? Do you draw a line in the sand and start containing the fire and eventually suffocating it?
The fire is every change you make to your application in haste. The fire is every design decision that is bolted onto one part of the application without care for how it fits into another part of the application. The fire is every stopgap put in place to fix a short-term problem that isn’t revisited once the short-term has elapsed.
Once time is not the most critical concern, you stop and think about how to make the application better in the long term. You consider what worked about the stop-gap solution, how to design your application with care, how to iterate on improving the architecture of your application.
You fight the fire by trading time for quality. Knowing how to solve your problems, knowing what is important about your application and what is consequential, you start to express a design. You write down principles that worked for you and write down an architecture that joins the principles and the design in the middle. That’s where your application lives, once it’s not on fire.
The reason green field software projects are appealing is that they aren’t on fire. A green field is lush with possibility, without the constraint of decisions already made. More so, a green field is not bound by decisions implicitly accepted but never considered.
The unconsidered decision is how the fire starts. A class here, a subsystem there. Soon you’ve got a system but no design, emergent or otherwise. You’ve got a ball of mud, but the mud is on fire.
That fire is sustained by every time you bolt something else on. It’s sustained by implementing the feature or fixing the bug without care for the program as a whole. It’s fed by making progress without making care.
The fire is warm, but eventually it will consume your application. No one wants to work on the burnt out wrecks inside of it.
Everyone can smell it, but no one wants to go near it. Firewalls are erected, teams establish practices that allow them to avoid working on or near the fire.
So it burns on.
One day, you decide enough is enough. No more fuel on the fire. Every change to the application has to meet standards: does this make the code better, does this make the design better? This here is the design; adhere to the why’s, use your creativity for the what’s and how’s.
That day is the day you start thinking for the long term. In the language of economics, its when you internalize external costs. You accept that the cost of maintaining this application is worthwhile, so you should mitigate that cost, optimizing input effort for output value.
You can’t maximize cost by just getting the work done. You can’t maximize value by building grand structures. You optimize cost for value by continuously making decisions that mitigate or reduce the fire.
Internal combustion engines are made of fire. Despite being powered by flame, combustion engines are pretty mundane things. They became mundane because they have a design and a standard of engineering that contains that fire, harnesses it, and turns it into a mechanism for converting fuel into energy.
When do we harness and focus our code, instead of letting it burn inefficiently and out of control? The moment we do is when we stop being firefighters and start being the wizards we set out to be when we started writing software.