Prune your code, to grow it healthier and stronger.
Did you ever have the feeling, as a developer, of fighting with an ever growing code base, stemming and branching like a living thing?
You update your sandbox everyday (at least) and you get hundreds of new lines of code each time, sometime for reasons almost unknown to you, because the other team is working on a feature you are not following directly.
Let’s face it: if you work in a team, you wrote just a small portion of the code you touch every day. Even with a small team of four, you write just 25% of your code, if the team is well balanced. Scale it to 20 teammates, and you’re down to 5%.
The risk of letting the code base free to grow wild is to end up with something like this: long branches, broken or dead ones, fruits far and hard to reach.
Also, you’re likely going to have unpredictable results: one year the branches break under the weight of the fruits, the next one you barely see a few of them.
How to avoid this? If you have any experience with fruit or flower trees in your garden, or even more if you are a bonsai fan, you know that the only way to grow a balanced, good-looking and healthy tree is to regularly prune it, bending it to your designed shape one small cut at a time. It is a multi-year challenge, and just one missed season can jeopardize the results. If you start when the tree is like the one above, well… nothing is lost but it will be much harder to get control back.
Software is not that different. Any code base started small and simple, but soon things begin to get messy: new features grow over the main concept like branches on a tree, the complexity and interactions between them increases; what you thought was going to be the main branch becomes a dead one, and success unexpectedly arrives from an small side feature. You can’t design all upfront, you must cope with the evolution and be ready to cut dead branches as soon as possible.
Cut early, cut neat
This is one of the first lessons you learn as a gardener. Sure, you can try to recover an old tree like the one in the picture above, but it is a long and uncertain endeavor. Much better is to cut the unwanted small branches regularly, as soon as you realize they don’t fit your design. Each cut must be neat, without smudges that can give a way for parasites to infect the tree.
In the same way, the sooner you identify the parts of code that are not fitting your design, the cleaner you cut them out without leaving pieces that may confuse the next one looking at the same code, the better design you will get.
Too often, instead, while we’re focused on our current task we leave these unwanted parts there for a future review. Maybe we add a FIXME or TODO comment here and there, just to loose track of them afterwards. When you realize the code has become a tangle of uncertain statements, you may feel it’s too late to clean the mess.
The good news is: it’s never too late, it’s just harder. Roll up your sleeves and work on it! But while you’re cleaning the old mess, take the lesson home and clean up the code you touch, every day. One class at a time, leave it better then you found it. Every day, like a workout. It will pay back.
Take a step back
While you are on the tree, among the branches, cutting the top ones, it’s not easy to grasp the shape you’re giving to it. You have to step down, walk a few meters away and look how’s coming together from there. And you have to constantly adapt your design to the reality, even to the mistakes you did while you were focusing on the details.
In a complex application, you can hardly think the whole design of it. Sure, you have the big blocks in mind, you stick to hi-level roles and responsibilities for your classes. But then, evil sneaks in the details and you end up finding weak dependencies you didn’t mean to have, boilerplate code hiding behaviors you didn’t expect.
You have to take a step back from time to time, review the modules and the interactions in your app, decide which one has to be reinforced and which one can be cut, and prioritize your tasks list. Then you can climb again on the tree knowing what to focus on.
Bend young branches
You know those beautiful bonsai trees with complex shapes, looking like an old tree in the forest, with branches bent in strange and artistic ways? There’s a trick behind it, one that is also widely used in fruit cultivation: the young branches are tied tightly and bent to the desired shape.
How are you shaping your code base in the same way? Which are the constraints that keeps the production code faithful to the requirements (when you get them right, of course)? You got it: tests.
The unit tests are the ties giving shape to the growing code and, just like you can’t bend a tick old branch, they shape your design if you write them before the production code. Adding tests to an existing application is just like tying an old branch: you can fix it on the current shape, but you can hardly change it. When you are at that point, you can only cut the legacy code one piece at a time and start growing a new one.
Pruning is fun!
Everyone likes to find a clean code base to work on. But, the same person finds any possible good reason to skip its cleaning turn — and not just for the piece of code she has just written, but in general on the class she’s touching. Of course, there is pressure to complete the current task, the time is always not enough. All good and understandable reasons.
But, are we sure this is all the truth?
Or, perhaps, is it also that we (developers) like more the writing part, the creation of new code, than the removal of the outdated one?
The same is for the company around us: we are valued for the feature we ship at the end of the sprint, not for the one we’ve removed. It is not easy to make a team (including the stakeholders) to really estimate the worth of a clean code and to pay the fee to get it. It takes time, dedication and some frustration to show how much it pays back.
Also, most of the times, this is not an activity you can estimate in advance: we’re not talking about a big rewriting here, which is something to plan and prioritize, but more about an ongoing activity made of small steps. If the developer does not feel safe in cleaning the code on a daily basis, without risks of regressions and side effects, pruning becomes an impossible activity.
I wonder if, and how, we could make this role something that is more valued in organizations big and small.
And you? Your are a smart code developer. Are you ready to become also a code pruner?