Gardening - Cultivating Better Software
Tags: design, architecture, programming
Published: 2019-09-12 09:57:34

# Entropy

![alt test](https://media.giphy.com/media/l0ExcD85yA584ICOI/source.gif)

Systems in life, it seems, no matter how hard we try as humans to keep them going, tend to entropy. No matter how hard we try we cannot build things that live forever - immortality, even in the abstract sense, seems an unattainable goal. 

Systems are built and they exist for a period of a time, a lifetime. More successful systems lasting much longer, and doing more. Such systems can survive the ebb of time, and with maintenance and care the intensity of the erosion of use can be lessened - but not prevented.

There is one crucial component that keeps good systems running for much longer - _gardening_. The meticulous grooming, watering, and weeding of a garden bed is crucial to its survival. It requires continuous monitoring and vigilance - removing weeds, as they pop up; watering the flowers when the ground becomes dry; fertilising the soil when it becomes infertile.

# Gardening

![alt test](https://media.giphy.com/media/xT8qBnw9AxRHmVea9a/source.gif)

A beautiful garden is a joyful thing. The value of it, the time and care that went into it, are implicit in its existence. There is a certain joy found in its design - and this is the human element of the _system_.

A garden can only exist with a **gardener**; and a beautiful garden needs a good **gardener** that does _constant gardening_. Without a **gardener** a garden would wilt and die - just like a system. Gardening is essential, for the creation, maintenance and preservation of a beautiful garden; but gardeners come and pass, and just so gardens do too.

Software to me is the obsession with building beautiful systems, and just like beautiful gardens these systems require _constant gardening_. Without it they decay - the ground dries up; the soil becomes infertile, and the _the weeds take over_. 

It's up to us as conscientious, well-mannered, gardeners to keep our gardens healthy. Healthy software lives much longer and performs much better. Maintenance is easier, and it responds well to change. 

So how do we tend to our software? How do we water the beds of our code, weed out the bugs, and remove the rot?

## Everything is on **FIRE**

![alt text](https://startupyard.com/wp-content/uploads/2017/04/f60db82acb9510030d2cf396c5bfa087_its-fine-the-anthem-of-meme-everything-is-fine-fire_1280-720.jpeg)

Very seldom do we get to start on something _new_. The majority of what we do is maintaining that which is already done - and usually it's an awful mess. The _welcoming committee_ on these projects always has _reasons_ and _excuses_ as to why this happened. There's always a reason for the _mess_. but honestly, who cares. 

Let's take a minute to acknowledge those well-intentioned fools, ourselves included, without whom the majority of us wouldn't have jobs. _Thanks past me, and thanks past you_.

Starting on such a project is intimidating and daunting. The code base is big and tangled, and there are always parts of the code that no one touches. With both hands, and **I can't stress this enough**, reach out and grab those parts. Shake them around; break them some more; figure out how they work and slowly start to understand them. 

Doing this will make you a key-player in your team - you're the guy that's willing to work with the _icky_ stuff. It will allow you to fix it, clean it, and scrub away the rot.

## Small fixes are fixes too

![alt text](https://media.giphy.com/media/mG7xN3NU7WeUUGiKjM/source.gif)

All fixes are valuable. Renaming variables, restructuring code, or large functional changes all add value to the code. Don't be hesitant because your change would be too small.

## But what is **Legacy Code**?

Legacy code is untested code. Keep a good coverage percentage for your unit tests - choose one at your own discretion - and always ensure that the heart of your system is unit tested _completely_. This will allow you to chop and change, refactoring to your heart's content, without having to worry about breaking something crucial.

But **don't** get lost in a testing labyrinth. This can happen in a few ways. The first is when you start writing so many test that you end up testing silly things _like controllers_. A 100% test coverage is silly - it makes me think of [Russell's Paradox](https://en.wikipedia.org/wiki/Russell%27s_paradox) _what tests the tests_? There is a good level of testing, and then there is an arbitrary level of testing - try and stick to the former. 

The second maze you may find yourself in, is trying to test code that is coupled tighter than _Betty White in the 1956 spandex swim suit catalog_. You start injecting, and injecting _and injecting_ dependencies and your test starts looking like a mess. In this case it's best to leave it for a later stage.

## The Time Investment

![alt text](https://media.giphy.com/media/9u514UZd57mRhnBCEk/source.gif)

When the weeds pop up take time to weed the garden. The most elegant fixes take time - and the most elegant fixes last the longest. Writing good code takes time - fixing bad code takes even longer. Tending to a _bed of code_, understand that it takes time and don't rush it (but don't go too slow either).

As a _professional_ software engineer I adhere to the [IEEE Code of Ethics](https://www.computer.org/education/code-of-ethics). Because of this, I hold myself to a certain standard - and this is a standard my clients can expect. I simply won't rush something and push it into production _because business needs it now_. It's irresponsible, and unethical. I won't go at a snails pace either, but I'll ensure that I generate minimal technical debt.

## A Full Bed of Roses

![alt text](https://media.giphy.com/media/QvwMDYpAMUm6Q/source.gif)

Reading code is a painful experience; writing code is a joyful one. This can lead us down a very dangerous path - where we start writing all the code that we need _even though most of the functionality exists already_.

Remember that any code you write is old already. Spend some time before you start, and scour the code base for _what's already there_. Extend it if you must and write new code if you absolutely have to. Practice your [Coding golf](https://en.wikipedia.org/wiki/Code_golf).

Coding golf is the art of using as few key _strokes_ as possible to write a function. It's a great exercise in being terse with your code.

## Context is key

Ensure that you understand the context of what you're doing. Don't do something because you've been told to. The **bigger picture** is key to writing purposeful software. Understanding how all the moving parts work together allows you to write your API's cleanly, and to define those contracts strongly. You'll soon figure out exactly what _your piece_ needs to look like to work _cleanly_ in the bigger system.

## Terminate with Extreme Prejudice

![alt text](https://media.giphy.com/media/Pxf6zNzEhD7wc/source.gif)

Another controversial point, very dear to my developer's heart, is eliminating bad code with **extreme prejudice**. If you can see it, if you can logically explain why it's bad - cut it out like a **tumor**. 

With version control tools like Git removing bad code should be easy, and should be done without trepidation. If you break something, so what? You now have broken code with less rot - fix the thing that broke cleanly and everything is better. Worst case just roll back your change and try again.

Don't be scared to change things - the only way code can get better, healthier, is by taking a zero-tolerance approach to cleaning it.

## Take a Break

Breaking things is bad, _right_? Let me be crystal clear here when I say

**BREAKING THINGS IS GREAT (FANTASTIC EVEN)**! 

Did you just break some crucial part of the code? If the proper unit tests were in place, this code would _never_ have made it into the code base. So write the tests to prevent this _next time_. fix it, understand it, and restructure the code so it **can't** break here again.

Good code should be written to do two things well - it should allow for itself break gracefully; and it should allow for itself to be fixed rapidly.

Breaking code might be a controversial topic. Because the concept of _breaking_ is inherently bad. But if you keep breaking something, in different ways, and removed all the flaws that broke it you have a much stronger, more resilient system.

## No Good Deed goes unpunished

In your _crusade of truth_, and honor, and better code, you're inevitable going to be stepping on some toes. Honestly, this is probably the hardest part of _gardening_. People have feelings, and people write code. These same people see their code as an extension of themselves. I do too - and I _really shouldn't_. It's going to happen and the best thing you can do is be very vocal about what you're doing and why you're doing it. 

Explain yourself with complete clarity. Leave no shadow of a doubt over what you're doing; and make it crystal clear that you do so without contempt or malice. You're making the code better _for everyone_.

It's a **hard** cultural change, and it sucks hurting people's feelings - but you have to _crack some eggs to make an omelet_. And if that omelet is for the betterment of everyone then that's quite alright.

## The Naked Truth

In the end we're all human. We err, and make mistakes. Work together, not against one another. You can achieve so much more as a team than an individual. Search for common ground and build unity with your fellow developers. We're all in this together, and a healthy work environment makes life better for everyone involved.

# Goodbye, and thanks for all the Fish

This is a softer piece, and a lot less technical than what I usually write - but it comes straight from my heart. I stand by all the points I've made and I hope it helps you in your endeavors to build a _beautiful garden_. 

Now if you don't mind me - I'll just be over here _gardening_ :)

![alt text](https://media.giphy.com/media/l0HlLrIzwGy9k3Kbm/source.gif)