Being pulled into the garage to help my father work on cars was a constant threat throughout my childhood. During these sessions, I was subjected to countless automotive adages, none of which resonated more than this:

The car was designed to be built on an assembly line.

Once this idea is internalized, all kinds of oddities underneath the hood start to make sense. It builds the instinct to keep that 10mm wrench within reach because the factory would have prioritized tooling costs over using more appropriately sized bolts for the wire harness. It delivers that “a-ha” realization to remove the front-left wheel to service the battery. Truth be told, if it weren’t for this adage, I wouldn’t have been able to keep my temper under control when I had to rip out the entire dashboard just to replace the heater core in my beloved Ford Thunderbird!

Many of the Fords I worked on owe their market success to W. Edwards Deming, an electrical engineer turned process-management guru. A pragmatist, Deming believed that without theory, there is no learning. To illustrate his point, he told a story about a rooster:

The barnyard rooster Chanticleer had a theory. He crowed every morning, putting forth all his energy, flapped his wings. The sun came up.

The connexion [sic] was clear: His crowing caused the sun to come up; there was no question about his importance. There came a snag. He forgot one morning to crow. The sun came up anyhow. Crestfallen, he saw his theory in need of revision. [1]

But we’re not rummaging for faulty gaskets (or contemplating orbital mechanics). Management has pulled us – not into a garage, but a “war room,” tasking us with closing an incident ticket for an unfamiliar codebase. Our mindset is one of survival. I missed so many car lessons throughout the years because of this attitude – let’s not repeat my mistake despite these similar conditions!

Instead of solely focusing on patching and getting back to our routine, let’s approach this unfamiliar codebase with some theories. If our predictions are correct, we’ll find the bug faster and put out a more comprehensive fix. If wrong, our egos may be bruised, but we’ll learn. Even if the lessons themselves aren’t relevant to our projects, at least we’ll have better theories for the next time management yanks us back into that war room.

While car engineers must make concessions for quick assembly, they also tailor the factories doing the manufacturing. Thanks to predictive planning, Subaru employees know everything each step needs, not just the tools and raw materials, but also the amount of time. This knowledge gives Subaru management the framework required to set deadlines throughout the company, keeping things flowing from procurement to delivery. Unfortunately, when the managers of software engineers habitually apply predictive planning to the world of software, everything falls apart:

Predictive planning requires known duration tasks. This means that the more unknown duration tasks there are in a work flow, the more predictive planning breaks down. Software projects have a high percentage of unknown duration tasks in the form of research tasks. These research tasks are often left unfinished due to the the team being focused on delivering Something™ by the predictive planning calculated date, rather than delivering valuable software when it is ready. [2]

Because modern business is built on deadlines, I’d like to recommend an adage when approaching unfamiliar codebases:

The source code evolved to survive its environment.

Once internalized, all kinds of horrors become relatable. It suggests that the tuples map is duplicated because the developer didn’t have the time to ensure memory-safe concurrency. It delivers that “a-ha!” moment when we see that all config values are injected via environmental variables, and that the yaml file is a long-abandoned scrap of good intentions. And it helps us maintain sanity when an entire god class requires refactoring just to change the behavior of a single button.

To set ourselves up for success, let’s take a few moments to ask some questions and build theories on top of this adage before diving into the problematic codebase!

Was the team’s manager a Java developer at one point in their career? Maybe the manager got involved in technical decisions, resulting in the use of that antiquated ORM library in a greenfield project.

Did the top sales rep want a customized theme used in every pitch? Maybe that’s why the theme system suffers from the inner-platform effect, and the CSS attributes are stored in a relational database.

Was the inventory microservice originally meant to validate orders? Maybe that’s why the customer microservice has to pass along a shipping address to check if an item is in stock!

We can count on the consequences of predictive planning and the echos of work conditions to be lurking in the code. A few extra moments spent digging into the project’s history can give us the base we need to propose theories. When our theories are correct, we’ll produce better fixes, and when they’re wrong, we can learn lessons to both course-correct and apply to our projects.

References