Cross-contamination
Having worked with students and junior developers for the better part of a decade now, I find myself fascinated by just how much developers depend on their ability to keep track of things…and how often this skill is taken for granted.
It’s not the most important skill software engineers can have overall1, but I think it is easily the most important factor that determines how quickly a junior developer can get up-to-speed.
Here’s what it looks like when a developer is struggling to keep track of things:
The developer is working to fix an error or get some functionality to work. They try one approach and don’t get the result they expected, so they back out their changes to try something else — but they forgot some of the files they touched and end up only removing part of the attempted solution.
They try again with a different approach that would have worked, but instead it fails because of the changes they forgot to revert from the first attempt. However, the developer doesn’t realise this, and so they [partially] back out their changes to try something else.
After a few iterations, the developer has cross-contaminated the codebase with overlapping partially-implemented solutions. The app is now showing the white screen of death, and the developer is well and truly stuck.
Preventing cross-contamination
Cross-contamination is easy to catch during pair programming as long as the navigator is paying attention, and you can sometimes find artefacts of it during code review as well. However, the surest way to fix the problem is to coach the developer to build good habits, so that they can avoid it in the first place:
Check working copy status regularly
Each time they back out their changes to try a different approach, ask the developer to do a quick git status
to make sure they caught everything. By regularly comparing their recollection of everything they touched against the actual state of their working copy, the developer will build that mental muscle.
Debugging statements need to get backed out, too
For better or for worse, developers (of all skill levels) tend to do most of their debugging by adding statements to print out values of variables and expressions…and they almost always forget to remove those statements later.
After a few iterations, the console gets polluted with lots of no-longer-relevant information, further increasing cognitive load and making it that much harder to keep track of things. Get the developer in the habit of removing debugging statements as soon as they are no longer needed.2
Teaching the developer how to use their IDE’s debugger is also super helpful in the long run, but choose your moment carefully — it takes significant mental effort and a context switch to learn a new tool.
Diff the code before committing
Every time a developer types git add . && git commit
into their console, there is a fairy somewhere that falls down dead.
Before creating a new commit, encourage the developer to run git diff --cached
and go over the changes they are about to commit. Reviewing the change set as a whole puts the developer in a different mindset to help them catch issues that they overlooked during coding, and it is another way to build that mental muscle by checking how well they remember the changes they made.
Teach them to love tiny commits
Expert rock climbers can scale sheer cliffs without a safety rope. In order to survive long enough to become expert rock climbers, novices must learn to hammer pitons into the cliff face periodically and attach their safety rope, so that they won’t lose too much progress (amongst other things) if they fall.
Software developers can do the same thing with code commits: as soon as the developer makes incremental progress towards solving a problem (and has passing tests to prove it), get them to make a commit. This helps to keep cognitive load manageable, and it acts as a piton for the developer’s progress — they can feel confident to make even radical changes to the code without risking losing their progress towards the overall solution.
Just as in cooking, the key to preventing cross-contamination is to build healthy habits. Coach your junior developers to manage cognitive load and build their capacity to keep track of the changes they make to the code, and it won’t take long before they develop the confidence and independence that they need to start their journey to intermediate status.
Empathy gets that title, and I’ll for sure be exploring that in a future post.
And while you’re in there, why not configure the linter to treat debugging statements as linting errors?