The Trouble With Side Effects

Side effects in code are a form of technical debt that create compounding complexity, but they won't ruin a marriage, right? Right?!

The Trouble With Side Effects
Photo by Ty Carlson / Unsplash

It turns out that the main source of technical debt and mounting complexity in code bases is the proliferation of side effects.

tl;dr: Side effects are bad.

(You should probably stop reading now. You were warned.)

It starts innocently enough. You have a CreateInvoice() function. At first, it just creates a record in an Invoice table. But later, you add inventory management to the application. And now when you create an invoice, you want to decrement the inventory for the purchased items. So CreateInvoice() gets a new side effect: create a record in the Invoice table and you reduce the Quantity field in one or more Product records.

To avoid repeating yourself, you write a ReduceInventory() function to encapsulate that logic and call it from CreateInvoice(). A few months go by, and the shop foreman asks if he can be notified when inventory drops below a certain threshold. So you add the new check to the ReduceInventory() function. If the product on-hand quantity gets too low, an email gets sent to the foreman alerting him to the problem.

The sales guy talks to the shop foreman at the water cooler and gets big jealous when he hears about this amazing email alert. Pretty soon he comes to you and asks to get copied on the same email. No problem, you just add his name to the .To property on the email code inside the ReduceInventory() function.

A few weeks go by and the inventory runs out for a key product. The foreman didn't get his email in time because that particular product had a long lead time to order replacements. So he walks back to the nerdery and says to you, "Hey, you need to adjust the threshold on the low-product alerts to take product lead time into account so this never happens again."

So now your ReduceInventory() function has to embed the calculation for lead time into its email alert threshold code, which–oh by the way–varies by product. And that means there are multiple tables involved. So you write a query that joins the Product table, the Requisition table (which contains replenishment orders), and another query that performs a weighted average of recent requisitions for that product to give a rolling estimated lead time (you're especially proud of that last part).

You roll into the Monday morning all-hands staff meeting and kick back in the nice chair, ready to bask in the glow of your inevitable accolades.

The universe has other plans.

Sales Guy walks in the door swiping left on his phone faster than a college guy with a fake profile photo on Tinder. "Looking for your next conquest?" you ask, proud of yourself for recognizing the game even though you've been out of it for decades.

"Nah, man," he grumbles. "I'm getting those low product inventory emails constantly all of a sudden. I can't delete them fast enough. What's that all about?"

You barely have time to start explaining the nuances of your oh-so-clever automatic lead time calculator and why his extra emails are a feature-not-a-bug when the shop foreman lumbers through the door, lays a meaty paw on the table in front of you, and says, "We need to talk.

"My wife thinks I'm cheating on her because my phone notifications keep going off. It's your emails, man. You're ruining my life!"

"Uh, can't you just show your wife the emails?"

"I tried, but she was like, 'There is no way that some little twerp at your job is sending you that many emails.'"

"Wait, she called me a 'little twerp'?"

He glares at you for a few more seconds, then breaks into a big grin. "I'm just messing with you, man. My wife doesn't really think I'm cheating on her because of some work emails."

"That's good," you say with a sigh of relief.

"The email thing is real, though. I got like 100 emails yesterday. Something ain't right with that program."

This can't be just about the lead time calculation change, you think to yourself. But what can it be?

"I don't know why you would be getting all those emails all of a sudden, but I'll figure it out. I'm just glad your marriage isn't falling apart!"

He claps you on the shoulder as he chuckles, "Oh no, that part's real. Something about finding her best friend's bra under our bed," he mentions casually.

"Yeah, that would do it."

"Plus my weekly bowling night cover story is probably blown since I found out they tore down the bowling alley six months ago. I might have known that if it was on the way to my job and not my wife's."

"Wow, you're not very good at this cheating stuff."

"Also, she found the 'Dating Apps' group on my phone–"

"Wait, you have so many dating apps you had to create a group for them?!"

"–with Tinder, OKCupid, Bumble, Match, Hinge, Grindr, Facebook Marketplace–"

"Whoa, I don't think that last one is a dating site," you say with genuine concern.

He stares off vacantly for a few seconds with an inscrutable expression on his face, as if he's pondering his life choices for the first time. And then, mid-epiphany and with no warning, he turns back to you and says, "Plus all those email notifications. Might have been the straw that broke the camel's back, ya know?"

He shrugs. Before he walks away to find a seat, he pauses, looks you square in the eye, and says, "I want you to know I don't blame you for your role in my crumbling marriage."

Well, that's a relief, you think sarcastically to yourself, as if any sane person could possibly blame–

He then stops, turns around, and whispers menacingly, "I also don't not blame you." He holds the icy stare for a few seconds before breaking into another wide grin.

As he finds a seat at the other end of the conference table, the other meeting attendees concentrate awkwardly on their reading materials, reeling from the bizarre exchange.

"Hey!" he yells across the table. "What we talked about? That's our little secret!"

You look around the table, but no one will meet your gaze. Unsure of what to do, you give a subtle nod in his direction and a simple thumbs up.

What a lunatic, you think, as your boss kicks off the meeting with a brand new graphic he worked on all last week. As he debuts the infographic, he shows the unexpected seasonal dominance of certain product colors. He drones on about how the company can boost profits through a combination of "dynamic season-based color pricing" and reduced inventory costs through "lowering of on-hand counts of seasonally unpopular product colors."

While you don't love these meetings, you do take some small pride in knowing that this graphic wouldn't have even been possible without you rewriting the report's underlying query to group products by color in addition to SKU and oh no that's why Sales Guy and Lunatic are getting so many emails! That query that I just subdivided into extra rows feeds the main product query which feeds the lead-time calculation query AND the inventory reduction query which in a somewhat recursive way results in a pseudo-cartesian join of the product table onto itself (maybe twice?) and would absolutely explain why a dozen emails a week suddenly became 100+ per day.

Welp, that answers that, you think to yourself, relieved that you finally know what went wrong. Now you just have to get back to your computer so you can see if anything else is impacted by that small change and oh no every new order placed will send out half a dozen or more emails to each customer and we have sales people entering orders right this minute and I can't sit here until this meeting is over or we'll be scheduling even more meetings to deal with the fallout...

As you bound from your seat and sprint out the door, your boss hardly manages to yell, "Hey, where are–" before you yell over your shoulder, "SIDE EFFECTS!!!" with no other explanation.

For the second time in the meeting, your coworkers share a stunned silence.

The shop foreman looks at the door, shakes his head, and utters a single word in the direction of your sudden egress,

"Lunatic."

And that's the trouble with side effects.*

*[Editor's note: You were warned about this sort of writing: "I plan to sprinkle those sorts of wacky, barely coherent bits of prose into as many of my articles as I can, so you know that what you are reading was written by a real well-adjusted human, and not some fancy probability output machine".]

All original code samples by Mike Wolfe are licensed under CC BY 4.0