Code as if you are going to rip it out tomorrow…
… aka how do I improve my code?
As engineers, we take pride in our code, like an artist does in their creations. Just like a photographer obsessing over the exposure, f-stop or the depth of field before shooting, an engineer spend hours figuring out the best design, coding styles and tools for their problems. Over the years many a great engineers have contemplated on how to write better designed code.
Lets say good code is something that works as intended, in an acceptable manner. But that alone doesn’t make the design good. There are enough coding patterns, anti-patterns, paradigms and anarchist theories that we all love or hate. Plenty of static checkers out there can go over your code and tell you when your code seems to have been barfed out by a bunch of monkeys trying to write Shakespeare after reading Nietzsche, or is simply illegible. Most of these ideologies cut across programming language boundaries and can be filed under “Zen and the Art of Software Design”. But with all this plethora of paradigms available, how does one choose the right one? How does one remember all these when one is actually about to code? Thinking about the code’s replaceability is one of these ways that can be used as a guide post when designing software.
Whenever I sit down to code, before I even write the first line I always ask myself, how am I going to rip this code out? How will I replace this with something else?
Why am I worried about replacing code that I just wrote? For me this is a way to synchronize my thoughts and distill most common guidelines into a baseline acceptability criteria. Anything that can be replaced with ease tends to have certain qualities that make it so.
Efficiently Organized, Well Isolated
Building code that is designed to be ripped out means we ensure things are disentangled and modular. More thought is put on interfaces and interactions allowing us to establish a readable code with well defined boundaries. This also means that the logic is abstracted at each level, and well isolated. You cant rip off parts of a strongly coupled system, can you?
Replaceable means Improvable
We are evolving continuously, and getting better. Why should our code not benefit from that? Anyone who has worked on a project lasting longer than a mouse’s life span has heard of legacy code and tech debt. A large part of what we do as engineers is enhancing and fixing. We are scared of changing large parts of the system because they are tightly entangled and even small pieces of code can bring big projects to their knees. Replaceable design means we can rebuild things in isolation and improve our system slowly. Furthermore it allows us to use different/newer technologies and tools and spruce up the system, without rebuilding the whole damn thing.
Why over engineer something that you are going to replace?
Designing code to be replaced ensures that we keep it simple and don’t get ahead of ourselves. It provides a realistic check on what features make it in and how they are designed. This also sets us up to easier upgrade cycles, and reasonable code paths. It also makes us quicker on our feet as the system is designed to be built and rebuilt as our needs evolve.
Tests, tests and more tests
An isolated system can be tested in isolation. When we think about how are we going to remove the code we just wrote, we put tests that verify the actual problem end to end and are not tightly coupled to implementation details.
This is by no means a definitive guide, or about how to name our variables better. Rather this is about how to start thinking about system design and architecture when solving problems.