Higher-Order Code Smells
Code smells are a well established idea.
The “smell” part is perfectly descriptive: like opening the fridge after a weekend away. You know when something is off.
There are popular tools to help detect them (Checkstyle, SonarQube, etc). There are research papers giving them a taxonomy, and to measure their relative costs. As a thought exercise, it’s fun to name them and give classifications (and ponder which are the worst), but I’m most interested in how they appear in the wild.
And in the wild, code smells appear in groups. Disorganization spreads disorganization, chaos begets chaos. And different code smells compound into unique, pungent aromas. I’m going to call these groupings higher order code smells where a lot of things are going wrong, together.
I’d like to share one higher order code smell with you today, and who knows, maybe this article will have a part 2 and 3.
(Edit: It totally has a Part 2 now.)
The N-Dimensional Object
A method or constructor that has many inter-dependent parameters, with some valid and some invalid combinations.
Characterized by: (1) Uncontrolled Side Effects, (2) Too Many Parameters, and (3) Cyclomatic Complexity
An N-Dimensional Object is trying to be too many things.
The wrong combination of arguments will look valid to the eye, but run with side effects (1). It tries to cram all the parameters of different uses into one place (2). And the many varieties of inputs will reach different branches of code, and it’s hard to reason about them (3).
The worst n-dimensional objects have a large possibility space: the Cartesian product of the inputs. All of them lay traps. It’s like that crocodile dentist game except you’re the only player and you’re also the crocodile.
A model intended to be used with a
Profile screen, capable of showing an individual
User, a user group, and/or a few controls for admins:
N-Dimensional Objects show up in places where a simple feature kept acquiring new variations without revising the data model. Or sometimes a series of design decisions lead to a UI with lots of different “flavors”, and the permutations got out of hand. Other times it’s a UI container, like an Android
Activity that has many different modes of initialization.
The fix should be clear given the causes: split the class into distinct types with their own custom-fit arguments. Who knows, maybe even compose it?
Fixing a higher order code smell like this leads to a cascade of other needed fixes: old call sites will now read more clearly, and the UI layer handling will have code paths de-branched. The time investment to make those followup fixes goes a long way to explain how a smell like this can stick around for a while.
That’s all for now!
Collin keeps code lemon fresh at Livefront, and he thanks you for reading.