20 Comments

When I first read this analogy, accompanying it was the diaper metaphor: "If it smells, change it." I guess I found that sticky enough to remember it after about 25 years.

When the analogy fails, I fall back to "design risk". This gives me a chance to describe the difference between a risk and a problem. That usually helps.

The trouble with design risks seems not to be unique to design: it's easy to ignore risks, it's often hard to quantify the probability or cost of failure (sometimes both), and so the most common reaction is to do nothing and hope for the best. Humans don't plan well for unpredictable future events. :)

Expand full comment

Or another pov is "technical debt". Just like code "smells", it compounds interests and gets worse over time.

Love the statement "If it smells bad today it is going to be poison tomorrow." It reminds the dreading consequence of bad codes left unchecked.

Expand full comment

It's a reasonably nice metaphor, but I wouldn't want to eat with your friend. If food starts to smell bad, that generally means it *IS* bad; not going to be bad tomorrow, it's bad now. Having said all that, I can't honestly come up with a good explanation of hat is meant by code smell. It seems to imply that the code isn't obviously bad, but rather you have to use a 'sense' to get a feel for whether it is good or bad, with smell being the most obvious one to use to detect 'badness'. However, the use of smell being used to detect badness in the real world usually happens either at low level - smelling chlorine in very low concentrations; or at a safe distance - smelling a sewage works from miles away. Unfortunately, neither of those map easily onto detecting bad code. Sorry :-(

Expand full comment

One simple analogy could be given by water infiltrations or just humidity in buildings which can result in a bad smell inside the building. The smell doesn't tell us that the building structure is bad, you might still be able to live inside for years. But it tells us that with time and increase in entropy that could lead to more serious problems in the structure of the building.

A stinky setter in a business logic class could be a smell of encapsulation leak which might lead to unpredictable non linear state changes in the future.

Expand full comment

Hung meat, blue cheese, and durian fruit -- three things that smell bad, but are still delicious! :)

Expand full comment

If people struggle to understand the analogy, such as code smell, I would suggest reading more, starting with the dictionary definition of "smell" and its various use cases. Expanding vocabulary can be immensely helpful. Then, delve into literature on the subject of code smell. If there is an immediate need to demonstrate what it is, I believe it would suffice to mention it in the commit message for a pull request: "Your code smells like xyz because of this, that, and these reasons."

Expand full comment

My correspondent had done their homework. There are legitimate cross-cultural challenges to figurative language. I’ve read books of aphorisms in their language and they made no sense to me. I’m glad they asked.

Expand full comment

Thank you. I hadn't considered that aspect of the "danger of analogy" before (which happens to be the focus of my recent interest). I have updated my article and included a reference (with a link to your article) highlighting this particular use case: https://sergiistarodubtsev.substack.com/p/the-power-and-danger-of-analogies.

Expand full comment

I think the challenge is that you don't know when or if code needs to change often. Therefor having a "stable" piece of code (it works, does not change often, can be "smelly" code) is fine to leave as it is. It makes me think of the metrics about "flexibility" and "stability" in Robert Martin's book "Clean Architecture".

Also the definition of "smell" is often tied to other metrics (cohesion, coupling, etc). I think you can always improve code if you visit it, but have to be aware of the implications when you change things. Sometimes subtle changes have the biggest impact (and you're not aware of that).

Regardless; I feel there is some implicit "code has to be easy to change" metrics going on. Easy to change code often has layers of indirection (interfaces, abstractions), meaning you will have some cost in performance. Ie, if we want to write very performant code as far as I know you get more tightly coupled with the hardware for example. Ofcourse you still want to set up your code in a modular way, but I feel the definition "easy to change" is too broad. Along with the definition of a "code smell" , if you put those together it gets all a very grey area.

As for the "food" analogy; I think food starts to smell when things are bad already. Although there is a (small) period of time when food tends to go bad soon (so you can still eat today, but not tomorrow). In the case for food we assume we want to "eat" or "process" it (to eat eventually). If we want to use a word for both software & food, I'd say "consume" would fit.

You don't consume food that is bad (you get sick, etc). You can consume "smelly code" and get away with it. The "bad effects" for smelly code are less dramatic than getting sick from food poisoning.

It is an interesting analogy where things can be deepened I think.

Expand full comment

I always thought of it as a quick way to judge the quality of code. Things that are generally seen as "code smells" should cause you to have the same reaction to the code as catching a whiff of something bad from a piece of meat.

Expand full comment

I seem to use “smell” when I see something that is typically bad, but sometimes perfectly appropriate. So I’m raising a red flag, but acknowledging that it’s based on limited information about what’s going on. So I wouldn’t be shocked if we dove further and it turned out to have been a good choice - or at least one that was dictated by the nature of the task, deadline, language, or codebase.

Expand full comment

I remember we had a plenty of funny terminologies when working at Lifeware with Massimo. Things like code massaging, the dancing tests, etc. At some point we decided to create a list of them on the Wiki. If you ask them to give you a copy of it you might get some inspiration for future articles :-)

Expand full comment

Is it the code that smells? Or is the code merely a stovepipe?

Expand full comment

It's definitely the code, or more specifically the structure of the code. If you do not fix it, it will guess worse with every change.

Expand full comment

How'd the code get there in the first place? Fix "It?" What is "It?" Whatever "It" is, I agree that if it isn't fixed, "It" and other things will get worse. The best line of the code is the one you don't need to write...or can eliminate. Symptoms vs root causes. Peeling an onion will surely make one cry. But...to remediate the "Smell", one has to go beyond the code.

Expand full comment

Well, you could certainly go after the coder. Or you could go after the teacher or process that taught the coder.

But there is a massive advantage to be gained by simply fixing the code, one smell at a time, and the result will likely be code that is easier to maintain. There is a lot of value in that.

Expand full comment

Does one have to come at the expense of the other? Can't we fix the code... and then from there, teach people how to maintain the code...and to write better code in the first place? This is ultimately a leadership issue. Anything else, and you're having to go through a lot of Febreeze because it's just a lavender-based smell...instead of being fragrant. Perhaps more tolerable, but not in the long run..

Expand full comment

Oh, absolutely. In fact, a major part of this is doing exactly that.

And that seems to be a bit of a challenge, at present. Developers learn bad habits through self-learning and computer science classes... and helping them unlearn those things often runs into resistance.

But the underlying point here is teaching developers to recognize problems in code. Most have probably never seen well-written code, and since they learn on tiny programs, most of which are discarded after the assignment is over, they don't experience the pain of maintaining bad code.

This is not a new problem. Forty-five years ago, my college class lab partner suggested a course on maintaining code: the assignments would be to read bad code with a bug, and figure out what was wrong. But that doesn't really fit into a "computer science" program, as it is usually understood, and students spend more time learning big-O notation and recognizing what problems are NP-complete, than how to code well.

Expand full comment

I think the challenge is that a big part of the remediation involves fundamental organizational re-design. It will also require a good deal of dual-loop learning.. Unlearning and then learning. It isn't relearning. It's trying to understand at a rapid pace. Leadership that is fixated on "Efficiency." don't appreciate how difficult this is considering that "Organizational knowledge" is almost non-existent. Most in mid-level positions today at your typical "Microsoft Enterprise Customer" doesn't understand anything meaningful about what their systems are, what they're supposed to do, How they work, etc. In many cases..let's just say the witness is unavailable for one reason or another..

Indeed, this is not a new problem. And I get you on the need for "Strategic Tunnel Vision" (my words, not yours.. :-) ) We call that focus, right? But the other, derived work items that have to be addressed. Making sure those pieces don't get lost. Sure, the developer might enter something into Azure DevOps, Jira, whatever..

The challenge is founded in how this chaotic bureaucracy is used as teflon by so many in decision-making roles today. Who pays the real price? The front-line developer. So I guess that Is my addition to this...to make explicit.. not implied - the real context that devs need to know.. As you say, not a new problem. Why is that??? :-P

I appreciate you, the dialog, this place. So...Thank you!!

JP

Expand full comment

Great analogy.

Expand full comment