Want to write the better code? Here’s a simple technique that programmers of all levels can apply. It works equally well for novices and for even the most experienced programmers.
That method is the simple act of revisiting your work. ‘Revisiting’, like refactoring, has a specific meaning and process behind it, which I’ll explain.
You probably have a good idea of what revisiting means already. It’s a little bit like when you’re taught at school to double-check your work, or read over your essay at least once before you hand it in.
The difference is that when we systematically revisit, just like when we systematically refactor, we break down an obvious idea into delicious, bitesize chunks of process. The benefit of doing so is to make sure that we’re doing it properly, and to ensure that our teammates are all on the same page.
This concept may be blindingly obvious to you, but I’ve always found it helpful to be explicit about process details like this.
Revisiting is going back over an implementation of a working feature in order to try to improve it. Obvious, right?
Sure it is, but to do it systematically requires the following steps.
Implement your first solution to the problem. Not just any attempt; it has to be a good attempt. Something that you believe is already the simplest solution. It may be a spike, a prototype, or it may even it a finished product. The point is that it solves the problem, and it solves it in a way that you believe to be the right/best/highest-quality way.
Take time away from thinking about it. Shift your focus to something else. Take a weekend off, or (my favorite) take a vacation. It requires a period of time to pass, and it requires you to forget about what you were doing. This allows you to come back to the problem with a fresh perspective.
Now come back, and re-build your solution. From scratch if possible. Re-learn the problem, and re-do your work. This is the key part, and will require you to carve out some extra time to do it.
Notice I used the terms ‘re-learn’ and ‘re-do’.
Re-learn is about coming at the problem with a different perspective. That’s why it’s important to shift your focus. You forget the decisions and assumptions you made before, and come back with a clean slate.
Re-do means exactly that: rewrite the solution from scratch. You might be used to the concept of spiking, where you write one version to learn from but then throw it away after. This is perfectly normal practice in the TDD world. But it’s also good practice even if you’re not following TDD, because by starting from scratch you’re forcing yourself to re-think every implementation decision you made along the way.
What’s the point in all this?
Almost always you’ll surprise yourself with a simpler solution that you didn’t see the first time.
That’s what it means to revisit your work.
Even though it’s straightforward and easy to apply, I can think of two major obstacles to this method.
The first is finding the time to do this. You may find it hard to convince your team that it’s a worthwhile undertaking, particularly when you have a full backlog waiting to be picked up. Many teams are hurtling along at such a fast speed that code becomes like cement. Once it’s set, it’s there forever. And once our code is committed to mainline, it’s not to be touched.
Industry experience tells us that simpler software is cheaper and more valuable in the long term. Complex software becomes more difficult to maintain, and as codebases accumulate in complex code, adding features becomes harder and slower to do.
So the more time you can spend up-front to simplify, the cheaper the software becomes in the long run.
The second problem is that your ego doesn’t want to believe that there’s a better solution. How willing are you to let go of your original ideas? How fixed are you to your original solution? Many programmers see a solution and then believe that it’s the only and best way. Convincing yourself otherwise can be hard. Feedback from others can help beat this, which I’ll come back to below.
If you’re anything like me, you probably think you always make your best effort when writing code. What’s more, you go out of your way to learn about writing great software. You’ve read all the books about good software design, you strive for simplicity, and you always aim to write maintainable software.
Obviously I can’t speak for you, but I know for sure that unless I’m revisiting my work, I’m not doing my best work. I almost always see new possibilities the second time I approach the problem.
I’m sure there are programmers out there who do their best work straight off the bat, but I’m not sure I know anyone like that. Plus, most of the environments I’ve worked in have some kind of time pressure that means the best programmers just don’t have the time to think before they begin coding.
Imagine the following scenario, which may be familiar to you. It’s certainly happened to me many times.
You delivered a bunch of work in your last sprint. You built some neat features. Your team and the product owner were satisfied. The sprint demo went swimmingly. Everyone was happy.
But at home that night, you’re thinking over your solution in your mind and you realise there was a simpler, more elegant implementation.
Sprint planning is the next day. Your team has a full backlog of work, and can’t deliver functionality quick enough.
What do you do?
Do you say, ‘Hey you know what? I think I have a better way of building that feature we just delivered. I’d like to revisit it.’
What will the product owner say to that? How will you convince them that re-doing the work is worth more than picking a new feature off the backlog?
Unfortunately, the scenario above isn’t an ideal one for launching into a new habit of revisiting your code.
What you need to do instead is build a culture of revisiting. That means encouraging your team to work with spikes, prototypes, or any planning process that allows you freedom to redo work at a later date.
So the next time a feature comes up that is unlike anything you or the team have built before, suggest that you use a first sprint to spike the solution. Then, the next sprint after you can take what you did and revisit it.
Revisiting should be part of your development culture. By judicious use of spikes and prototypes you can bake revisiting into your process without having to ask permission.
Another way is to help your colleagues understand—if they don’t already—the long-term consequences of software complexity. Highlight the importance of writing clear, maintainable code, and the high costs associated with over-complex codebases. You could even show them this blog post ;)
Revisiting should ideally happen after an initial round of code reviews. Give your teammates an opportunity to poke holes in your design. Even if you argue against their suggestions, what that feedback does is sow the seeds of a fresh perspective. When you come back to revisit your work later, you’ll remember those comments and be able to evaluate them with more objectivity than when you wrote the original implementation.
It might not be that you take on the feedback verbatim, but at the very least the feedback will help you break down your own assumptions when you do revisit.
Quite simply, no. Pairing is another strategy to help write simple software. The ultimate combination would be pairing and then revisiting as a pair.
Now that is a winning strategy.
Got thoughts or comments about this technique? I’d love to hear! Leave your comments below.