5 Strategies You Can Use Today To Write More, Better Code
Over the past 15 years that I’ve been studying and thinking deeply about software engineering, there have been a few core concepts that have really levelled up my ability to produce great software. In this article I’ll cover one of those — feedback cycles.
Here’s the rule I follow when I’m developing code:
If the code I’m working on is going to take more than a couple of iterations, any feedback cycle longer than a few seconds is too long.
I’ve found some great techniques to help with this — read on to find out. But first, what are feedback cycles and why are they important?
At the start of my career I used compiled languages heavily — C, C++, FORTRAN (that makes me sound older than I am!). The codebases were also pretty large, so a disproportionately large amount of time was spent waiting for code to compile. The code -> compile -> test cycle lasted minutes, sometimes tens of minutes.
Long feedback cycles are the enemy of productivity
Shortening the feedback cycle is a crucial element of increasing productivity across engineering disciplines, especially when doing something new and complex. Elon Musk lists “Accelerate Cycle Time” as one of the 5 steps of his engineering protocol. And shortening cycle time is a core principle behind the agile manifesto, as well as being one of the 7 “lean principles” identified by Mary & Tom Poppendieck (for more on this listen to this great episode of the Tech Lead journal).
As well as being important on a “macro” level, shorter feedback cycles are crucial on the “micro” level of software production (writing code).
It’s not just compilation
When it comes to being productive as a software engineer, there are a bunch of problems with long feedback cycles. And it’s not just compilation that can introduce long feedback cycles; any amount of development process inefficiencies can lead to this problem:
- Testing that requires a lot of clicks through to bug/feature reproduction
- Bugs or features that can “only be demonstrated” on a non-local environment
- Long-running analysis or simulation processes
There are techniques available to the dedicated software craftsperson that address all of these issues, but first let’s look at some of the problems that long feedback cycles cause.
Failure to get into a flow state
One of the great joys of software engineering is the flow state that we achieve when we’re flying through code and adding features at the speed of thought. When your thought process is constantly interrupted by the need to wait to test your changes, the flow state is never achieved and development progresses more slowly.
Increased likelihood of bugs
When feedback cycles are longer, the tendency for the developer is to write more code per test. This increases the likelihood that not all of the code under development is rigorously tested, and therefore increases the chance of bugs creeping in.
Lower developer creativity
When it takes so long to get feedback on code changes, less creative “risks” will be taken and tested. This results in sub-optimal code and design in the name of “just getting it working”.
Simply takes longer
Of course when you have an additional wait for each code/test cycle, everything is going to take longer, resulting in fewer features being added in the long run.
Moment of revelation
The moment this all changed for me is when I saw this video by Bret Victor. In it, he explains how he developed a new system for seeing code changes reflected live in the game he was demoing:
The whole video is worth a watch, but the takeaway is that by shortening feedback cycles we can be much more productive. Since watching this video, I have been a strong believer that we should always look to shorten our feedback cycles when developing software.
How can we shorten our feedback cycles?
Once we’ve identified that we need to shorten our development feedback cycles, there are a number of techniques available to us:
Test Driven Development
I won’t go into the details of TDD here, as there are ample resources out there. If you’re unfamiliar with TDD, I encourage you to learn and embrace the approach, but also be pragmatic about when to use it.
One situation where this approach is definitely useful is when we’re building a piece of core functionality that would otherwise be very difficult to test. By writing our tests first, we ensure that our testing is targeted to the code that we’re currently working on. Any tests you write can be incorporated into automated test suites for improved quality.
Write a Test Harness
Similar to TDD, a test harness can be used to exercise only a small part of your whole code base. This can be useful in the case that your code is part of a bigger application and you want a way of only testing a small feature.
For web applications, UI component explorers such as React Storybook are great tools for building test harnesses.
Use Test Data
A lot of the code I write is for data analytics and simulation. In these cases running a full simulation can often take hours. A good approach here would be to invest the time to develop a test dataset or parameter set that is smaller or quicker to run, but still exhibits the same features as a full dataset.
Use Modern Web Development Tools
Many “modern” (read: post-2015) web dev tools come with features that promote faster feedback cycles. As an example, webpack-dev-server automatically reloads the page on changes, and even for languages requiring a transpilation step like TypeScript this is super quick.
Use A Different Language To Prototype
What if you have a requirement to produce code in a compiled language like C++? Is there a way to get around the long feedback cycles?
Yes! If you’re working on an algorithm it’s a great idea to prototype the code in a quick-to-run language before committing to your final production language. Use a language like Python or Julia to provide fast feedback and get creative when developing your code.
A step on the way to greater productivity
I hope these tips help you get more out of your development process. What about you? Do you have any tips for reducing feedback cycles? Leave a message in the comments!