Unpacking Technical Debt: Why People Problems Drive Engineering Challenges
Explore how technical debt and engineering challenges often stem from human factors like resistance to change, communication gaps, and misaligned incentives. Learn why addressing the 'people problems' is crucial for successful software projects.
The premise that most technical problems are fundamentally human problems has a rich history, echoed by figures like Jeff Atwood in 2008, Bruce Eckel in 2007, and Gerald Weinberg as far back as 1985. This enduring insight highlights a critical aspect of software development and engineering.
I recall an experience at a company grappling with immense technical debt: millions of lines of untested code built on frameworks over a decade old. On one project, a market demand required migrating Windows-only modules to Linux. Instead of cross-compiling, another team opted for a straightforward copy-paste of hundreds of thousands of lines of code, simply swapping Windows-specific components for Linux ones. For those less technical, this creates a monumental issue: two divergent codebases. Any future feature or bug fix would require parallel implementation in both, leading to inevitable divergence and increased maintenance overhead. As a younger, more naive engineer, I was determined to rectify this.
The Human Element in Technical Challenges
Initiating projects aimed at addressing technical debt is inherently challenging, especially when advocating to management. Even if flawlessly executed, such projects often result in the software merely performing as it did before, without immediately visible new features. This particular project was no exception, and its optics were not favorable. Like many engineers, I initially "ignored the politics," focused solely on the technical work, and completed the task. However, the project extended beyond its timeline, and I consequently lost management's trust during the process.
It was then I realized I was attempting to solve a people problem with a purely technical solution. Many developers at the company were content maintaining the status quo, doing today what they had done yesterday, and for the past five years. As Andrew Harmel-Law aptly observes, code often mirrors the personalities of its creators. Individuals resistant to change tend not to design systems with future adaptability in mind.
Indeed, most technical problems originate as human problems. Consider the roots of technical debt: insufficient clarification of requirements, sales teams setting unrealistic deadlines, developers opting for familiar but outdated technologies, management prematurely canceling projects, or individual egos hindering the adoption of superior methods. The core impediment to our refactoring project was the implicit admission that acknowledging the need for change also meant confronting the company's flawed software development practices and the obsolescence of individual skillsets. While my small team worked to improve one module, other developers continued coding as they had for decades. One developer explicitly stated, "I don't want to learn anything new." This made it clear: you will never eliminate technical debt faster than others create it. It's akin to triage in an emergency room; you must first stop the bleeding before addressing the underlying issues.
Beyond the Engineering Ideal
This experience also disabused me of the common engineering ideal: a world where problems can be solved in isolation, devoid of "politics," where work speaks for itself, and where deadlines and even customers are distant concerns. Such an ideal rarely exists. The vast majority of projects involve non-technical stakeholders, and simply stating "trust us; we're working on it" is insufficient. I learned that the perception of your team's progress is just as crucial as the actual work accomplished.
Non-technical individuals often lack an intuitive understanding of the effort required for technical debt cleanup or its inherent value. Engineering teams must communicate this effectively through initial estimates and ongoing project updates. Unless leadership possesses an engineering background, the value of technical debt remediation must be quantified and framed in terms of its tangible business impact.
Cultivating "Heads Up" Engineers
These insights perhaps serve as preparation for more senior roles. In my view, anyone progressing beyond a senior engineer level requires strong cross-functional collaboration skills, regardless of whether they pursue a technical or management path. Educational institutions teach computer science; they typically don't teach how to navigate diverse personalities, egos, and personal blind spots.
I've had the privilege of working with exceptionally talented engineers, possessing profound technical knowledge across a multitude of technologies. Earlier in my career, I aspired to be this "engineer's engineer." However, I now recognize that my own personality doesn't align with a completely "heads-down" approach; I thrive with more varied engagement. While these intensely focused engineers possess considerable strengths and can be incredibly productive individual contributors, they may struggle with larger initiatives due to their singular focus—a single processor core has its limits. Equally valuable, perhaps, is the "heads-up coder": an individual who is deeply technical but also capable of stepping back, identifying project risks (both technical and non-technical), and adeptly guiding the team through them.