We all know naming is a pain in the ass and you can’t trust the names in your code. But it doesn’t have to be that way.
Many people try to come up with a great name all at once. This is hard and rarely works well. The problem is that naming is design. Here are the things you are typically trying to do all at once while naming:
- Deciding the things the code should do
- Deciding which things go together
- Deciding which abstractions best represent those clusters
- Picking a name that clarifies intent
- Picking a name that distinguishes from all the other similar intents
- Describing the side effects of the code
- Keeping your name under 15 characters
This is why naming is hard.
Our brains can’t juggle seven cognitively complicated tasks at once. After brain overload, most of us give up and settle for a crappy name.
Naming something perfectly the first time isn’t going to happen. Let’s talk about evolutionary naming.
The easiest approach for finding good names is to progress along a series of regular steps.
The solution … annoyingly simplified
At each step, I look at one part of the code, understand one kind of thing that is happening, have an insight, and write it down. I repeat this until I have moved one step down this list. I keep going until I have a good enough name for my purpose.
The big picture
Those of you who are reading ahead will wonder why I am focusing on names. I mean, names are annoying to come up with and perhaps this will make it easier, but is that really a problem?
The answer to that question lies at the heart of understanding, preventing, and paying off technical waste.
The source of all technical waste
Wasteful code is any code that is hard to scan. Technical waste is anything that increases the difficulty of reading code.Me.
My focus on code reading may seem odd to many of you. After all, we’re programmers. We’re good at reading complex code, and our job is to update code. Shouldn’t the definition of technical waste be something about the cost and risk of changing code?
It turns out that the largest single thing developers spend time doing is reading code.
More than design.
More than writing code.
More than scanning.
And yes. Even more than meetings (well, probably).
According to an analysis from Eclipse data, programmers spend around 60-70% of their entire programming time reading code.
So if we want to be more efficient, we need to improve our ability to read code.
It’s about risk too
Bugs aren’t random. Unsurprisingly, bugs get written more often when:
- methods are long or deeply nested (cyclomatic complexity),
- concepts are spread around,
- code does multiple things,
- there are side effects.
Make a method longer or make code more complex to reason about and people write more bugs when they edit it.
But those aren’t the #1 cause of bugs. Poor naming was #2 but became #1 when inconsistent indentation was solved by IDE’s.
Bugs come from incomplete understanding
Now that we know bugs aren’t random, let’s look at what leads to a bug.
- Mistakes happen when our mental model doesn’t match the reality of the code.
- Neuroscience shows that our short-term memory only has seven registers.
So if the real code would take more than seven registers to model, we can’t help but write bugs. So let’s make the code take fewer registers. Since it takes more registers to comprehend code than to remember what it does, the easiest way to reduce registers is to make the code easy to comprehend.
So if our definition of technical debt is code that is difficult, expensive, or risky to change, then the root cause of that is code that is hard to scan. And what makes code easy to scan? Good names.
Which brings us back to names
Definitions are where we communicate instructions to the computer. Names are the place we communicate our insights and intentions to other humans.
Implementing the solution
Remember, the annoyingly simplified solution is to have one insight at a time, write it into a name, and repeat until your name shifts to the next stage. The remaining challenge is to learn how to make each kind of naming shift. For each stage you will need to know:
- where to look for insights,
- what kinds of insights to glean,
- how to write them down in a name,
- how to use tools to do this at speed, and
- how to know when you are done.
We have extracted this into a series of micro-skills that are designed to be easy to learn and pay off with advantages from the start. That sequence is Code by Refactoring. Start by helping your team learn Naming as a Process.