"Easiest Nearest Owwie First". When facing especially weak code, it’s easy to feel daunted; there just seems so much wrong with it. To get my mojo on, I find the simplest infelicity to fix, I fix it. Then I do it again.
Everyone encounters code from time to time that she does not understand. This is true for the noob and equally so for the olb. It is a fact of being a geek.
Early in one’s refactoring career, one tends to blame oneself. While it must be said that you have a certain peculiar charm, you feel basically stupid, and that you are at fault and not the code.
Slowly, over time, you will begin to suspect otherwise, and you’ll start to realize the code works for you, you don’t work for the code. Congratulations! That is the correct attitude.
But the fact remains: Tho I am a lot better at reading code than I was a bazillion years ago, I still routinely encounter code that I don’t get. Not understanding code is ordinary. The difference between the noob & the olb is the reaction it provokes.
So what do I do when I face code I don’t get? I change it, that’s all, until I get it. But here’s the entry point to this muse: change it how!?? I don’t understand it. I can’t just jump in anywhere and start changing shit.
It might be tested, which will certainly help. But it might not be. Further, a) it might not even be testable yet, and b) even if it is tested, that doesn’t tell you where to start.
The trick is to narrow your focus until you find a line or two that on the one hand, you can understand, but on the other hand, takes you a reading or two to get. In other words, tho graspable, it’s not readily so. Then you fix it. Then you try again.
So what kinds of thing are we talking about? Well, here’s three things my eye goes to right away.
First, a local variable is named in a way that obscures its intention. It’s not "i", it’s the "linenumber". Total no-brainer. Fix that. Look again.
Notice, btw, I just picked an obvious meaning-obscuring name. It’s just as common to find variables that are over-named as it is undernamed. When scopes get too large, people tend to overspecify. A variable name camel-cased with seven words is a very bad sign.
Second, I look for places where a variable is declared but not initialized. This is very rarely legit behavior, and it hides meaning quite well.
A place you see this is itself a clue to a later refactoring: when it’s declared then we immediately hit an if, both of whose branches set it. This is a strong clue that the if is an extractable method. If I’m feeling the power, I might jump right to that, but I might not.
Third, I look for early-return opportunities. (Oh, that reminds me, I was gonna do a muse advocating for early returns.) An early return is a way to "undent", a way to get the hell out of a long method with at least one case totally dealt with, and therefore out of my head.
Slalom code is called that because the indents go way to the right then way to the left then way to the right. We need to have a separate muse about dealing with this, but early-returns often remove later indents, too.
So, that’s three. I probably have a dozen or so. If I were any sort of decent responsible person, I would write them up & share them. Thankfully, my faithful followers already know the dismal truth about that. Hey, you knew I was a snake when you clutched me to your breast.
Anyway, as I continue to work this way, find a tiny thing, fix it, find a tiny thing, fix it, two things occur, one straightforward and one remarkable.
The straightforward thing that occurs is that I gradually gain some modest understanding as I work. I see that that "lineitem" — not "l" — is being added to a map-by-category. I see that later we take those groups and process them a little differently, and so on.
And the remarkable thing? The search for "easiest nearest owwie" starts returning different results. Say my first pass turns up ten easiest nearest owwies and that’s all. After I fix them, my second pass will turn up another dozen. After I fix them, I’ll get more.
I call this whole process "brush-cutting". My mission is to get to the trees. But I can barely even see the trees in the lush undergrowth that surrounds them. The more I take care of that brush, the more I see the trees, and the more I see how to cut them.
(I can’t believe I just used a metaphor I associate with the clear-cutting of forests. What, truly, will become of me?)
The two hard parts of all this are these: 1) remembering I’m not stupid because I don’t understand what’s there. 2) recognizing that "easiest nearest owwie" is the fastest way to find and fix "hardest distant nightmare".
In the beginning I found the first one hardest. Now I find the second one hardest. I want the big money too quickly sometimes, even now, after years and years of learning the hard way that the big money very often can’t be had without first getting the small money.
So. "Easiest Nearest Owwie" is my motto when I’m facing code that I don’t understand, a situation that occurs to olbs far more often than noobs think. Find the tiny quick improvement. Make it. Do it again.
You’ll quickly be doing massive refactorings with confidence.