There is a feeling familiar to many programmers. You're sitting (or standing, if you're fancy) at your desk, working on a programming problem, when out of nowhere you’re overcome with what can only be called a “weird vibe.” You start to experience the awkward hunch that something is not quite right with this code. You run your tests — everything passes. You try to work through the logic, looking for holes — but it all seems sound. You go back to work, having found nothing to worry about, but you can’t shake the spooky feeling that you’ve missed something.
Often, if I share the problem with another developer, they will suggest a minor naming change or refactor justified by an anecdote of a similar situation in which they went down the very same road with some level of disastrous consequences.
If you’ve been a programmer on the internet for any period of time, you’ve probably had this experience of other developers trying to steer you around the mistakes of their past, whether in person or via StackOverflow comments, pull requests, or tweets.
You’ve probably wondered how these people are able to bring their experience to bear on almost any topic with relatively limited information. Where did they get all this knowledge? How much of it should you take seriously? Will you ever reach the point where you’ll have the level of instinct of these StackOverflow gods?
This brings me to Code Smell, the dirty little secret of every experienced programmer. A phrase which (although apparently coined by the great Kent Beck in the ‘90s) has really only entered my vernacular in the past year.
According to Martin Fowler:
"a code smell is a surface indication that usually corresponds to a deeper problem in the system."
Code smell is a variety of Information Chunking that associates small recognizable patterns in design or implementation with larger design or architectural anti-patterns. And like all Chunking, to the inexperienced it’s undifferentiable from magic.
It wasn’t until I (after several years of making the mistakes that are a part of programming) started to be able to solve some problems by instinct that I began to understand that the instinct to avoid problems is like a muscle that can be exercised and developed. I’m no miracle worker, but I’ve got some years of making educated guesses under my belt, and I’m at the point where I know what a lot of my common mistakes smell like.
There’s plenty of writing on the topic of code smells. Some developers have gone so far as to create their own libraries of code smells, attempting to pass on their own experience to others. They’re passing on warning signs in areas like naming, class architecture and code reuse. I like to think of this as the programmer’s version of letting me know a gas leak smells like rotten eggs. The intention here is great, but I’ve always had a hard time learning from the mistakes of others. Just like IRL bad smells, I think it’s hard to recognize code smells until you’ve really stepped in it once or twice.
I believe that many of the practices of mindfulness can be really valuable in developing the sort of awareness and experience it takes to be able to identify and recognize code smells for yourself. If you’re unfamiliar, “mindfulness” is a sort of catch-all word for a group of practices and attitudes which share the common goal of making the practitioner more present and aware of the current moment. While there are as many mindfulness traditions as there are flavors of Linux, many of them share a few common ideals:
This is a big one. If I ever want to get better at something, the first step is to be open and honest with myself about where I am now.
When problems arise, I try to take a step back and think about what I was doing right before this problem came up. What was my goal? Was I trying to work too fast to hit a deadline? Was I distracted? Did I just get excited and start banging out code without thinking? Or did I do my best and just get it wrong this time?
This is most obvious in traditions that include breathing exercises or meditation, wherein the goal is to bring the focus of the mind to bear on the breath (or in some Buddhist traditions, some task like raking stones). Often, the goal is to observe other thoughts as they pass by, but not to fixate on them or follow them too far, and always return to the breath.
In the same way, when I’m programming I can occasionally get spun up wondering about my design. One thing leads to another, and before you know it, I have 3 copies of my class written different ways and twelve open StackOverflow tabs.
These are the moments where Test Driven Development saves my hide. I try to treat the test like my breath. When I start getting distracted by everything I could change about my implementation, I try to take a breath and return to the test. What is failing right now? What is the next step to fix that failure? This brings my attention back to the present and the task at hand.
Mindfulness is not an overnight thing. When I first started meditating, my goal was to fix my insomnia. However, I meditated every day for a week and still had trouble sleeping. Over time, the reason I stuck with it shifted from the reason I started: I had noticed other areas of my life where I was carrying stress around with me. And slowly, over the course of several years of gentle attention, that stress dissipated from one place and then another until finally I am generally able to sleep on a normal schedule. Mindfulness enabled me to learn to be patient with myself in that and many other areas.
The same applies to growing in pattern recognition as a programmer. Recognizing code smells and anti-patterns takes time, but if approached with a methodical and open mind, it can help to develop confidence and useful knowledge.