Sometimes adding features to software is like cycling on a hilly road.

You start off at the bottom of the hill, a little unsure of the hight and gradient, and how well you’ll be able to tackle it. You start the uphill climb, writing new code, adding tests, trying an approach that may not work, backtracking and starting again. This uphill climb is starting to tire you out. You’re making forward progress, even thought it may not feel like it, but it’s slow and you’re not sure how much longer you can keep cycling for.

Eventually, you reach the top: you have a solution that does what it needs to do with decent test coverage, but it’s ugly as sin. There’s an approach there that works, but it’s hidden underneath all the attempts that didn’t. You’re tired, but you’ve got a sense of accomplishment.

Now the downhill coast begins. You begin hacking and slashing, deleting code that you no longer need, and generally simplifying the solution, every time running tests to make sure you haven’t removed too much. Travelling further along the road gets easier with each file deleted and each model refactored, until you have something that actually looks good. Eventually you level out, and you’ll need to start peddling again, as you tidy up and add documentation in preparation for the pull request.

The feature is built, the hill is behind you, and you are further along the road, ready to tackle the next hill.