I hate dishes. Like, I really, truly, deep down in the bottom of my heart’s right ventricle hate dishes. And when I’ve made dinner and then spent the successive half hour cleaning up the mess I made in the kitchen as a result of said dinner preparations, I get annoyed, nay, angry when someone decides to make another mess in the kitchen and leave it dirty.
Perhaps you’ve heard the saying “clutter attracts clutter”. The kitchen is a great example of this. “Oh, what’s this? A dirty plate and fork in the sink? Well, certainly my dirty bowl and spoon won’t add too much mess to the pile!”
Soon the sink is overflowing with 17 bowls, 24 plates, all the forks, knives, and spoons you own, 3 small pots, 1 large pot, an Alclad saucier pan, 2 cookie sheets, a roasting pan, the mixing bowl off of your Kitchenaid, the inner pot of your InstantPot pressure cooker, and the blender pitcher of your Blendtec.
And then no one wants to do the dishes and no one fesses up to making the mess, because the truth is that everyone contributed to it.
Turns out codebases are similar, perhaps too similar, to our hypothetical kitchen. If not diligently guarded, mess can unintentionally creep in, attracting more and more mess along with it, until you’ve got a fire breathing product support developer calling you at 12:08 at night, furious because the system is incomprehensible and unmanageable and if you don’t help them diagnose the problem in prod that is preventing the company’s China market from getting their hands on those stupid Fingerlings (no, that isn’t a sponsored link. We will make no money if you click it), you can expect months (if not years) of their critical comments, daily doses of demeaning and derisive dictums, and annoying aptitude for always alliterating all animadversions.
All because the code was messy. You don’t want to deal with that person, and worse yet, you don’t want to be that person either. No one has an appetite for associates who are always alliterating.
Sorry. I’m done. I promise.
So how do we protect our code? How do we simultaneously keep mess out and preserve order while continuing to add features and value to whatever product we are working? I have no silver bullets, but the last year has provided some interesting experiences that, on reflection, have taught me a few things.
Reverence the Code Review
I’ve had my fair share of Looks Good To Me™ code reviews. Opening the pull request, I’d think “Yep. Looks like C# code to me. Merged!” I’ve committed my sins. We all have. But perhaps my biggest regret is that I did not treat code reviews with the respect I should have.
At least where I work, the pull request / code review process is the only thing keeping code from being merged into prod. When I first started, I had a habit of trusting other developers and devaluing any questions I had about what they had done, mainly because I was junior to everyone else around me, so who was I to question their work? Certainly they knew more than I did.
And yet as time passed, I found myself asking small questions about why something was being done the way it was, which often led to having conversations about how the code fit into the rest of the system, and sometimes it even led to a discussion that revealed a flaw in the code or a way that it could better fit into the rest of the system.
Even the times that those discussions didn’t reveal any bugs or design flaws, it helped to transfer domain knowledge from the requester to me, which is also hugely beneficial should I ever need to work in that code at some point in the future.
In an effort to level up my code reviewing skills, I created a list that provides questions / prompts that I ask myself as I’m looking at someone’s code. I think that these lists are going to be fairly customized from person to person, but a few good starting places might be
- Does this code change follow my organization’s style guide?
- Does this added code following the single responsibility principle?
- Do variable / function names make immediate sense to me?
- Does this code change have added / modified tests that are passing?
The list could go on and on, and I would strongly recommend that you create your own list. Doing so will only add to the quality of the code review you are performing, resulting in a better product overall.
Put the Code in front of a Newbie
You want expressive code. I want expressive code. Even the product director wants expressive code, and they can’t even write a line of it. So how can we get to the point of consistently writing expressive code? Well, practicing every day is a great place to start, and one great way to practice is to follow test driven development principles, but I’m not here to sell you on TDD.
When it comes to the expressiveness of my code, I have found no faster feedback cycle than placing it in front of a newbie and noting down what questions they ask / how many WTFs per minute they utter while looking at my code. I then take their questions and comments to heart, ask myself how I can address their concerns and confusion, and then go to work changing the code to be more comprehensible.
Thing is I used to think that putting code in front of a newbie simply meant having someone who was “junior” to me look at my code. But really, what this means is to have a fresh set of eyes look at my code. I suppose you could interpret newbie to mean someone who doesn’t have any domain knowledge of the problem you are working on, someone who can bring a fresh set of eyes to the work you are doing.
So really, take time outside of code reviews to have others read your code. Others are going to have to read, make sense of, and work on it at some point, and if it is incomprehensible, it would be better for you to learn and fix that now while you have the context of the problem fresh in your mind instead of trying to recall the context at 12:08 am after being awoken from the first good sleep you’ve had in days.
Seriously though, great writers have other writers read the multiple drafts of the books they are working on, until something great gets crafted from all those revisions. As software developers, we should probably also write multiple “drafts” (at least a second one), and allow the revisions and reviews with other developers improve our code.
Take Time to Reflect
This is one that I have wanted to do for some time, but haven’t created any habits around yet. Still, I’ve had some thoughts that I intend to implement in 2018, and I think they are worth sharing.
Where I work, we follow scrum / agile / etc. and have 2 week sprints. We have organization level retros, developer retros, and team retros, which is just a fancy way of saying we have lots of time to reflect on the work we’ve done for the sprint, talk about what worked, what didn’t work, and what we are going to do to improve. I think that this is generally an okay thing to do, but these existing ceremonies and meetings seem to leave little time for an individual developer or a set of developers on a team to look at the health of the system they are responsible for, consider how well past work is aging, and ask if there are any ways it could be improved or cleaned up. Instead we are onto the next feature and its associated body of work, leaving little time or incentive to to reflect back on what we’ve done.
Especially now that organizationally we have moved toward a product mentality, the team I am on owns 10 different “products”, a few of which we have never worked on. Knowing that I will eventually work on or have to support these products drives me to want to carve out time to just read code and understand it, and begin to formulate ways in which I might improve said code. Doing so would help improve my domain knowledge of our products, which would in turn improve my confidence in my ability to work on and support it should problems with it arise. It’s a win-win, really.
Much of this stems from the fact that, for me, concepts, problems, and potential solutions tend to take time to marinate and become understandable to me over time. Hat tip to all out there where that isn’t the case, but sometimes the best debugger is an evening with a great fiction book and a reasonable night’s sleep. Removing myself from a body of work for a period of time often resets my perspective, giving the ability to view something with fresh eyes, but only if I ever make the time to reflect on it. Otherwise the neural defragmentation that takes place over time gets wasted if I never go back and inspect previous bodies of work. Making and taking that time will only end up helping me to clean up and maintain the system I work on.
So that’s it. These are my 3 bits of advice I’m giving myself, and perhaps any others who would listen, in 2018 to help me keep my kitchen sink of a codebase clean and manageable. Best of luck to all you out there trying to do the same!