Introducing technical debt

By Niels Matthijs

10 min read

Are you tired of seeing good websites go to waste? Do you want to keep your codebase clean, but you have no idea where to start? Ever wondered how a small change request or simple bugfix turned into an endless game of whack-a-mole? Monitoring technical debt can provide a way out.

Introducing technical debt
Authors

There are many holy grails in the web development community, but one of our boldest challenges is building websites that increase in quality over time. Too many projects have inexcusably short lifespans, as neither clients nor developers find themselves able to deal with the scrambled chaos websites inevitably become. Despite everybody's best intentions, websites are often on life support by the time they are effectively launched, which is a far stretch from the quality we aspire to deliver.

The good news is that influential people are starting to notice the absurdity of this situation, and slowly ideas and concepts are emerging that will help our industry take the necessary steps forward. Not too long ago I spotted a mention of The Ship of Theseus in an article on design systems, the rise of headless setups is helping us deal with architectural challenges and our own Dave Bitter wrote a very insightful article on some of the most common causes for code corruption.

Workflow improvements are essential and being aware of possible pitfalls is certainly a great help, but when reality hits, they will not safeguard our projects from imperfections and the inevitable decay. That's where the concept of technical debt comes into play. Technical debt won't necessarily prevent bad code, but it does help you deal with it.

Introducing: technical debt

Technical debt is an umbrella term for whatever suboptimal technical decision found its way into an application. It is something we face and deal with every day, only it is very hard to explain, let alone quantify to non-technical people. With experience, we develop a radar for it, but clients simply don't have time to worry about nondescript developer feelings. That's why the "debt" analogy is such a powerful one. Our clients are used to dealing with debt, and they're well aware of its implications. Technical problems are never just stationary or contained, when left unattended, they will grow into bigger problems.

The moment you introduce the concept of technical debt into a project, it can become part of an agenda. It can turn into a shield that blocks unsavory requests (more specifically, the answer to the question "Is it technically possible?" could change from "Yes" to "Yes, but technical debt"). It can be tracked and monitored as part of a project's health indicators, and it can be translated into actionables. Before digging deeper into its benefits though, let's figure out why so many of our projects spiral out of control.

Primary reasons for technical debt

Now, some developers might be worried that technical debt could become a measuring stick for the quality of their work. Rest assured, while we obviously carry some of the responsibility for the quality of our code, we aren't always the cause for things going sideways. Neither is technical debt always a bad thing, so let's look at some of the most common triggers that lead to unwieldy code.

Mid-development change requests from clients

You've built what the client asked for, your code is bug-free, clean, lean, and mean, everything works exactly as intended, and then a change request comes in that turns everything upside down. Someone, somewhere down the line had an epiphany, and now you're left wrangling your code against a deadline that is too tight.

Botched internal planning

Project managers are busy people, so once in a while, a bug ticket slips through the cracks, or an important remark goes missing from the briefing. Maybe your designer didn't quite find his mojo and is slaving away beyond his deadline. Parts of the functional analysis could be missing when we start work on a new piece of functionality, and of course, nobody remembered the 404 page so could we please whip something up ... the list of possible mishaps is endless. As developers, we're often caught between an immutable deadline and internal delays (i.e. "the sandwich"), and in the end, it's up to us to make it work.

Technological maturity

The quality of our code is only as robust as the capabilities of the language it is written in. Anyone familiar with front-end development knows that it can take a long time before new standards are agreed upon and are safe to use across a wide array of browsers. The first time I wrote about container queries was in 2012, only now are we seeing browsers implementing the idea. And for the past few years, I've been impatiently awaiting the moment to fully ditch oldskool JPGs & PNGs in favor of better image formats, but alas, these things take time.

Unnecessary complexity

A good developer is taught to write DRY ("don't repeat yourself") code, but abstractions introduce complexity, and unnecessary complexity doesn't come cheap. It's not always easy knowing what to abstract from the start, and overengineered code will come back to bite you. Sadly, KISS ("keep it simple, stupid") and DRY are two ideals that are very hard to balance, so when in doubt, choose KISS. It may just be better to wait until bits of code start repeating themselves before DRYing them, even though by then it might be too late to refractor on the fly.

By design

Technical debt can also be a solution rather than a problem. This may sound contradictory at first, but it's not that different from going to the bank and lending money to buy a house. There are times when it's more important to land a new feature as quickly as possible, so people can start using it right away. If your e-commerce site needs to be responsive, and you have to choose between a 15-day desktop-first responsive hackathon or a 160-day from-the-ground-up front-end rework, the choice isn't that hard.

Dev skills and mood swings

And yes, developers are only people too. We might have a bad day, maybe we're put on a project that's above our current skill level, sometimes we underestimate complexity because we haven't thought everything through, or we might be distracted by more interesting projects. It certainly wouldn't be the first time I think up a better solution the moment I walk out of the office, and I'm pretty certain it won't be the last. Just own up to those moments.

The most important thing to remember is that technical debt isn't about assigning blame, it's about tracking code imperfections that will invariably lead to problems down the road. Once you make that mental shift, a new world will open up.

Monitoring technical debt

The best place to anchor technical debt is in the actual code. Identifying and describing technical debt are additional tasks for developers that typically crop up when things aren't going too smoothly, so keeping friction minimal is vital. The system only works when developers are noting down these issues, so don't make it harder for them than necessary.

Of course, adding these notes is only half the work. Having code riddled with technical debt comments isn't going to magically fix anything. With a bit of extra tooling though, the actual monitoring work becomes trivial. It is easy to write a script that extracts all comments from code and dumps them in a place where developers, PMs, and clients can toy around with them. This is a one-time overhead, but it is definitely worth the effort, as it could mean the difference between success or failure.

Once you have that in place, you can think about adding extra metadata to your comments. A red flag and a description of the problem is all you need to get going, but a little extra context will help with grouping, planning, and prioritizing technical debt, so it can be taken care of properly. The context I usually provide is:

  • a priority level (from 1-5, but whatever works best for your team)
  • the component it relates to
  • the technology involved (HTML, CSS, JS, PHP, SQL, ...)
  • the area of impact (DRY, robustness, performance, security, UX, ...)
  • the reporter (so you can bug him for clarifications if needed)
  • a way to fix the problem (if possible)

This could then result in something like this:

@TODO-3-newsTeaser-html-performance-Niels: add AVIF support to the teaser image
@TODO-5-button-css-robustness-Niels: grid gaps and widths are based on media queries, should be container queries

I realize that doesn't look particularly sexy, but it doesn't have to be, as this is not client-facing. Just dress up the management interface, so things look clear and understandable there. Make it so you can filter out the CSS issues when you have a front-end resource available, look at the current problems before you start to rework an existing component. Set up budgets (f.e. no more than 5 priority 1 comments) or tackle performance issues when needed. You can even draw up monthly reports to keep clients posted on your progress and set up weekly emails to inform and confront developers and PMs. The sky's the limit.

Added benefits to the client relationship

Technical debt may sound like a very technology/developer-focused affair, but there are also clear benefits for the relationships we foster with our clients, transparency being one of the most crucial ones. Something like technical debt can take you out of the honeymoon phase, when everyone is still pretending they're perfect and nothing ever goes wrong, to a more mature stage in the relationship, where we can show a willingness to work through the hassle when issues arise.

It's also instrumental in clarifying the consequences of decisions that are being made along the way. Out of the blue, a deadline may become less pressing when a client hears a proposed technical solution is flawed and will cost them dearly later on. Or a post-launch follow-up phase can be added right away, to make sure any added debt gets dealt with right away. The debt analogy makes these kinds of conversations a lot easier, and it is sure to prevent future frustrations.

Ideally, technical debt becomes a project in its own right, as part of an SLA. A monthly budget, dedicated resources, and proper reporting can do wonders to the health of a long-running project. Developers will be happier working in a clean(er) code base, fewer unforeseen errors will pop up, fewer bugs will need to be reported, we can all spend time and effort on improving the website rather than covering our mistakes, and the overall cost of developing new functionality won't spiral out of control anymore. As long as the technical debt is kept under control that is.

Babysteps will get you there

If all of this sounds a little daunting, don't panic. The true beauty here is that tracking technical debt pays off on even the most basic level and that any developer can start doing it right away, without any kind of master plan in place. The next time you come across a piece of code that can be improved, simply add a comment and move along. Then tell your fellow developers to do the same. By the time PMs and clients are on board with the idea, rest assured you'll have amassed a big stack of issues to get rid of.

Of course, monitoring and balancing technical debt isn't a magical solution that will solve all problems in a flash. But if we ever want to turn our websites into ships of Theseus, it's a necessary first step to keep our projects from deteriorating before our very eyes.


Upcoming events

  • The Test Automation Meetup

    PLEASE RSVP SO THAT WE KNOW HOW MUCH FOOD WE WILL NEED Test automation is a cornerstone of effective software development. It's about creating robust, predictable test suites that enhance quality and reliability. By diving into automation, you're architecting systems that ensure consistency and catch issues early. This expertise not only improves the development process but also broadens your skillset, making you a more versatile team member. Whether you're a developer looking to enhance your testing skills or a QA professional aiming to dive deeper into automation, RSVP for an evening of learning, delicious food, and the fusion of coding and quality assurance! 🚀🚀 18:00 – 🚪 Doors open to the public 18:15 – 🍕 Let’s eat 19:00 – 📢 First round of Talks 19:45 – 🍹 Small break 20:00 – 📢 Second round of Talks 20:45 – 🍻 Drinks 21:00 – 🙋‍♀️ See you next time? First Round of Talks: The Power of Cross-browser Component Testing - Clarke Verdel, SR. Front-end Developer at iO How can you use Component Testing to ensure consistency cross-browser? Second Round of Talks: Omg who wrote this **** code!? - Erwin Heitzman, SR. Test Automation Engineer at Rabobank How can tests help you and your team? Beyond the Unit Test - Christian Würthner, SR. Android Developer at iO How can you do advanced automated testing for, for instance, biometrics? RSVP now to secure your spot, and let's explore the fascinating world of test automation together!

    | Coven of Wisdom - Amsterdam

    Go to page for The Test Automation Meetup
  • Coven of Wisdom - Herentals - Winter `24 edition

    Worstelen jij en je team met automated testing en performance? Kom naar onze meetup waar ervaren sprekers hun inzichten en ervaringen delen over het bouwen van robuuste en efficiënte applicaties. Schrijf je in voor een avond vol kennis, heerlijk eten en een mix van creativiteit en technologie! 🚀 18:00 – 🚪 Deuren open 18:15 – 🍕 Food & drinks 19:00 – 📢 Talk 1 20:00 – 🍹 Kleine pauze 20:15 – 📢 Talk 2 21:00 – 🙋‍♀️ Drinks 22:00 – 🍻 Tot de volgende keer? Tijdens deze meetup gaan we dieper in op automated testing en performance. Onze sprekers delen heel wat praktische inzichten en ervaringen. Ze vertellen je hoe je effectieve geautomatiseerde tests kunt schrijven en onderhouden, en hoe je de prestaties van je applicatie kunt optimaliseren. Houd onze updates in de gaten voor meer informatie over de sprekers en hun specifieke onderwerpen. Over iO Wij zijn iO: een groeiend team van experts die end-to-end-diensten aanbieden voor communicatie en digitale transformatie. We denken groot en werken lokaal. Aan strategie, creatie, content, marketing en technologie. In nauwe samenwerking met onze klanten om hun merken te versterken, hun digitale systemen te verbeteren en hun toekomstbestendige groei veilig te stellen. We helpen klanten niet alleen hun zakelijke doelen te bereiken. Samen verkennen en benutten we de eindeloze mogelijkheden die markten in constante verandering bieden. De springplank voor die visie is talent. Onze campus is onze broedplaats voor innovatie, die een omgeving creëert die talent de ruimte en stimulans geeft die het nodig heeft om te ontkiemen, te ontwikkelen en te floreren. Want werken aan de infinite opportunities van morgen, dat doen we vandaag.

    | Coven of Wisdom Herentals

    Go to page for Coven of Wisdom - Herentals - Winter `24 edition
  • Mastering Event-Driven Design

    PLEASE RSVP SO THAT WE KNOW HOW MUCH FOOD WE WILL NEED Are you and your team struggling with event-driven microservices? Join us for a meetup with Mehmet Akif Tütüncü, a senior software engineer, who has given multiple great talks so far and Allard Buijze founder of CTO and founder of AxonIQ, who built the fundaments of the Axon Framework. RSVP for an evening of learning, delicious food, and the fusion of creativity and tech! 🚀 18:00 – 🚪 Doors open to the public 18:15 – 🍕 Let’s eat 19:00 – 📢 Getting Your Axe On Event Sourcing with Axon Framework 20:00 – 🍹 Small break 20:15 – 📢 Event-Driven Microservices - Beyond the Fairy Tale 21:00 – 🙋‍♀️ drinks 22:00 – 🍻 See you next time? Details: Getting Your Axe On - Event Sourcing with Axon Framework In this presentation, we will explore the basics of event-driven architecture using Axon Framework. We'll start by explaining key concepts such as Event Sourcing and Command Query Responsibility Segregation (CQRS), and how they can improve the scalability and maintainability of modern applications. You will learn what Axon Framework is, how it simplifies implementing these patterns, and see hands-on examples of setting up a project with Axon Framework and Spring Boot. Whether you are new to these concepts or looking to understand them more, this session will provide practical insights and tools to help you build resilient and efficient applications. Event-Driven Microservices - Beyond the Fairy Tale Our applications need to be faster, better, bigger, smarter, and more enjoyable to meet our demanding end-users needs. In recent years, the way we build, run, and operate our software has changed significantly. We use scalable platforms to deploy and manage our applications. Instead of big monolithic deployment applications, we now deploy small, functionally consistent components as microservices. Problem. Solved. Right? Unfortunately, for most of us, microservices, and especially their event-driven variants, do not deliver on the beautiful, fairy-tale-like promises that surround them.In this session, Allard will share a different take on microservices. We will see that not much has changed in how we build software, which is why so many “microservices projects” fail nowadays. What lessons can we learn from concepts like DDD, CQRS, and Event Sourcing to help manage the complexity of our systems? He will also show how message-driven communication allows us to focus on finding the boundaries of functionally cohesive components, which we can evolve into microservices should the need arise.

    | Coven of Wisdom - Utrecht

    Go to page for Mastering Event-Driven Design

Share