The Second Iteration: Your Key to Finally Writing Excellent Code

JulesWritesCode - Sep 3 - - Dev Community

Your first version of a piece of code is mediocre at best.

When you start developing a feature, the beginning feels great. You know where the code needs to sit and how to implement it. But halfway through, you bump into an unforeseen problem, and you find yourself copy-pasting if-statements or meddling with data structures. Towards the end, your work feels rough and unfinished, but you’ve already invested hours and just want to finish it.

If you had discovered the problems and quirks beforehand, it would’ve been easy to handle them properly and to write simple code from the outset. You couldn’t discover them, however, since you first had to write the damn thing.

But there’s a simple trick to accelerate making those discoveries and getting a complete picture.

Always throw away the first iteration.

Once I started doing this, my PRs had fewer requested changes, my code produced fewer bugs, and it became easier to integrate subsequent features.

Here’s why.

You’ll arrive at a working version rapidly.

If you throw away everything regardless, you’ll spend less time on making it work.

During the first iteration, I often don’t even implement functions. Instead, I jot down the signature, return mock data or an error, and continue with the important stuff. Since I know that and how the function will work (you must be sure of those two things), I don’t have to spend time on it.

By only spending time on parts I haven’t fully grasped, I’m significantly reducing the time it takes to finish the first iteration.

You’ll get a complete overview before you do the real work.

To understand what your feature requires, you must first make it work.

The rapidly completed first iteration gives you an overview of requirements, quirks, and issues. You can then identify the spots where you could solve problems or make features work elegantly. This will help you a lot once you start the next iteration.

Then, designing an elegant implementation becomes straightforward.

You won’t waste time on unnecessary details.

As devs, we love to worry about variable names or think about performance optimization.

But the temptation of optimizing a lower-level function or rewriting code for readability can suck you in for hours. Worse, after finishing a feature, you might realize you never needed the now-optimized function in the first place. Your time would’ve been better spent elsewhere.

If you consider your first iteration a throwaway, that compulsion to optimize will be easier to resist.

Cleaning up will now be a breeze.

Once you start with the second iteration, starting from scratch won’t feel as bad.

If you invest too much into the first iteration, if you spend too many hours fixing bugs, writing tests, rewriting functions, and optimizing or commenting code, you won’t feel motivated to start over — and understandably so. You don’t want to throw away your work. But if you are less diligent during the first iteration, you are less invested, so it won’t feel like you’re throwing away anything important.

Instead, you’ll feel motivated to start building it right.


The con argument is that this approach takes longer.

But is that the case? How much time do you spend rewriting code once you’ve stumbled upon your first hurdles? Wouldn’t starting from scratch be easier than cleaning up the mess?

Give it a try and see if you like it.

. . .