Article
Higher-Order Code Smells (Part 2)
August 21, 2021
In Part 1 we established the idea of the higher-order code smell: how small units of disorder combine to make surprising new problems (and complex odors). Little deferrals of (extra) effort aggregate into more trouble than the sum of their weights. Check it out here to see the first example, the N-dimensional Object — a monster of too many purposes.
Here in Part 2 we’re looking at another — and this one likes to hide until you’re making large, difficult changes. The very moment you least want surprises.
Start by visualizing your application architecture as a set of walkways, sending traffic on designated paths to their architecture-sanctioned destinations.
If a well-lit stroll on pre-determined path is how you designed the application, then a Desire Path is when you violate your own rules and trample the grass.
You could’ve made a path, but you didn’t.
The Lateral Pass (Aka the Path of Desire)
A surprising back-channel pass of information in violation of existing architecture, which couples components that have no reason to know about each other.
Characterized By, (1) Inappropriate Intimacy, (2) God Object, and (3) Uncontrolled Side Effects
A lateral pass is an undisciplined call or data handoff that some too-clever component “just knows” to make.
It’s often an over-share of information exposing implementation details across application layers (1). To perform it, an object has to overstep its boundaries (2) and the links between these layers can get accidentally broken during refactoring due to an obfuscated connection outside of the architecture (3).
An example.
Here’s a repository
that holds the user’s Preferences
, and exposes changes to those preferences as an observable
value (in this case, a KotlinFlow
). Downstream application components can watch and react appropriately when preferences change.
Additionally, suppose the PreferencesRepository
has some method to set the UI theme, perhaps DARK_MODE
. Below we see the setUiTheme(theme)
method:
And since the application has to restart after a Theme
change, it just… hey wait a second!
Application.restart()
?
This is a contained example of an architecture pattern right next to its violation — the observable has become the observer. Responsibilities out the window! In a sample this small, the fix is clear: let some other component observe the StateFlow
for theme changes and react with its own restart logic. But in a large application, this kind of pattern violation can induce havoc during a difficult refactor, or upgrading dependencies, or trying to isolate coupled components. That’s why it’s so important to not introduce a Lateral Pass as a hack (see: shortcut vs hack , because the difference matters).
Sometimes a developer will write a Lateral Pass if they’re failing to embody the perspective of the application component they’re writing. The developer just knows what should happen next, not considering what the component itself should know.
That’s all for now!
Collin keeps the grass green at Livefront .