Journey, destination and story

I’ve been thinking about writing this one for a while, actually longer than that. I really needed an example to talk about. Fortunately I wrote some code recently. This is about code changes, how they made and how to present them.

I’m going to talk about code changes as having a few different parts:

  • The journey is how you take the existing code and make whatever changes are needed. You might have a clear specification that lets you go in a straight line. You might have a few notes about what is needed so the path may be winding. In either case there can be surprises. That might mean a detour, a new direction or backing up and starting again.
  • The destination is the code you end up with. It might be similar to the original code, there might be a few changes or it could be completely different. If someone knew what your task was these might seem like obvious changes or they might be opaque.
  • The story is the history you leave behind showing the start to the destination. This could be the same as your journey but it doesn’t have to be. This is what a code reviewer will see when the changes are being made. This is what a developer will find if they’re going back through the history to fix or extend the code in the future.

The journey

The problem with journeys is that they are complicated and messy. We can look a my prototype’s journey and what really happened.

This is my initial implementation of single bit manipulation functions and some tests. Then I have to fix some bugs, get rid of some debugging code I forgot about, fix some names, realise their is a simpler way of writing something, fix some more names and finally fix a test.

Then a extend my implementation to multiple bit manipulation, get rid of the original single bit implementation (that’s just size=1 for the new functions), fix the changes, fix the changes again, introduce the bit field accessors that actually do something new.

Next add the helper classes one by one and sprinkle in some const and constexpr. Technically the library is complete but it’s still not as good as it can be.

I come up with a couple of ways to make the testing simpler.

I decide the library is simpler if based on Bits::Range because it caches the bit mask rather than calculate it each time. That means the file makes more sense in a different order but they I notice some bugs. Normally I would have just dropped the re-order but I wanted to capture it for posterity.

Finally I realise there are several benefits to deriving Bits::Index from Bits::Range and get rid of newline that crept in somewhere.

This is honest but much more complicated than I’d want to see in a history. Looking through it is more confusing than it needs to be. It doesn’t matter that I changed some identifiers or fixed some minor bugs. It would be better to just have them fixed in the history.

Just the highlights

In most situations it’s better to tell a simpler story.

This is more what I’d want to see. You can see the stages that I went through without getting lost in the details. However there is still more back and forth than is really needed.

A new story

Telling a new story can dramatically simplify things for later readers.

These commits don’t match up neatly to my original ones. The improved testing is used from the start, as is constexpr. Bits::Index is derived from Bits::Range as soon as the helpers are added. It tells a simple story of starting with functions for single and then multiple bits then adding helper classes and finally using those classes as a foundation.

Note that I take a full commit just to re-order the file rather than combine that with something else. Re-ordering a file or swapping things between files can make a history very confusing. It’s often best to make these moves by themselves.

Given the setup described in Iterative development it may be unrealistic to get something this simple but different situations will allow different stories. I could have decided to take the library further. It only deals with continuous bit ranges but
a Bits::Mask class would easily allow non-contiguous bit ranges. I have to stop somewhere though.

Just the destination

In the limit your story could be just the destination.

For this simple library that’s probably okay. The Bit::Range is as easy to understand as the initial functions. I wouldn’t recommend it for anything complicated.

A story takes time

Checking in your full journey doesn’t take you any time but crafting a new story certainly does, why bother? I think the benefit is for the code reviewers and developers who look back on it, including future you.

Doing a proper code review can be hard work. You may not completely understand what the original code does. You have to try and understand what the changes are doing and whether they are correct. Is that refactored code really doing the same thing as the original? Are they using the library correctly? Does the algorithm do what they think it does? It’s much easier to do all this if you’re just seeing the highlights or have a clear story to follow. For this example it’s possible to understand just the destination. However with a complicated change I don’t think it’s possible properly review all the changes in one go. You can certainly look at a bunch of changes all at once but you can’t understand them as well.

So this is an exchange of time. Some extra time in order to set up a good story but less time to do the review and less time for anyone inspecting the history later.

In the end

I’ve found it worthwhile to tell good stories. I know that I want to be able to look back at code histories 6 months from now or 6 years from now.

I have changed tools recently and am finding it harder to do this. I had been using Sourcetree for MacOS for several years. Recently I have been using… Sourcetree for Windows but involving Windows Subsystem for Linux and it’s slow, so slow I can’t reliably edit my history. I think the problem is something to do with how file caching works for WSL. So a lot more has to be done directly on the command line. It’s just not as good as being able to edit the history directly with a visual tool.


Posted

in

by

Tags:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *