Ward Cunningham coined the term Technical Debt in 1996. Technical debt is a concept in software development that reflects the implied cost of additional rework caused by taking shortcuts or postponing work. Back in 2010, Philippe Kruchten introduced me to the concept in an engaging talk that always stayed with me. It sparked an interesting thought: what if we could quantify, in monetary terms, the cost of sloppy software? In other words, quantify the benefits of preventing or fixing flaws?
Issues at work
There are of course multiple issues at work. For one, there are the corners that deliberately got cut short under pressure of time (this was before the concept of a minimum viable product gained steam, by the way). There’s the choices an individual developer made while his knowledge of the domain was not complete. There are issues of simply not giving it enough attention under pressure of deadlines. Jumping in without preparation is another issue. Failing to bring the right people on board is yet another one.
There’s also something quite different going on: Time. Chris Sterling defined it as “the decay of component and intercomponent behaviour when the application functionality meets a minimum standard of satisfaction for the customer”. We all know that these minimum standards tend to mature over time. Technologies advance. Designs evolve. The need for rejuvenation is only a matter of time. Like a house that needs a lick of paint every now and then, software also needs a touch up occasionally.
“If I had to build it again, knowing what I’ve learned while building it, I would structure my code differently.” I know I’ve often said this to myself. I know, you cannot fight time. You can try to be ahead of your time, but in general this is not a viable strategy. So, the best you can do is design for any unknown future change. Making it flexible, open and easy to maintain. Taking care that your designs are up to date, unequivocal, and easy to understand. And these are exactly the kind of corners getting cut short under pressure of time. Technical debt generates more technical debt. It’s what nobody wants but it is just the way it is.
Over the lifetime of the product, debt tends to accrue, and may turn into a maintenance nightmare. There is a way to prevent it. At least, this is how frequent refactoring of code gets sold. Keeping your software fit for the changes that will inevitably come. If not, your debt will ultimately end in bankruptcy.
Today I argue this is not enough. We all know there is so much more than plain functionality to care about. Availability, performance, usability, privacy and price, for instance. The world has turned into a demanding place indeed. Are we certain that the system now in place, which might be working nicely, cannot be replaced by something cheaper, faster and better? Is your perception that your system is not broken a sufficient justification to not fix it? Product owners nowadays expect the highest quality at the lowest price at the fastest pace. The old way of thinking will not generate the outcomes this new reality demands for. That’s where our paradigms must shift, and that’s exactly what’s going on.
When paradigms shift, quick fixes will not help much. A facelift is a very superficial rejuvenation attempt. Like it or hate it, as an industry we are in the midst of a change that is challenging basically everything we’re used to. The new mantra is “Cloud Native”, favoring massively distributed, narrowly scoped microservices orchestrated as a cohesive network of interacting components. It is in many ways the next step in the transition from a data-centric to a digital mindset. This is where the new standards of quality, cost and pace of change are set, and this explains why so many traditional systems and services are now in architectural debt.
Liberate your mind
So, when I look back at my earlier work today, it is not as much my design that smells, but if I had to design it again, using todays’ technologies, I would definitely have made different tradeoffs. Virtualization is the magic wand that fuels this new paradigm. Every component can have its own virtual database without worrying about the actual data processing. I feel free to design a relational database for a service implementing a complex query, and an object database for a service that transforms an object from one model into another, and a key-value store for declaratively managed services, all as parts of a single super service. I wouldn’t have dreamed about such a design a couple of years ago, but actually, I find it quite liberating. I can simply choose the right tool for the job.
This is true for database technologies, but also for middleware technologies, for computationally intensive technologies such as machine learning, and for data distribution pipelines. As long as I can simply consume them as a service, and the barrier to adoption is low, there are no real drawbacks to heterogeneity. I just need to bring in the right people. That’s still a given. And yes, the team I have may constrain the design choices I make.
Embrace the cloud
Today’s main architectural debt typically lies in not using modern cloud native principles — Containers, Orchestration, Distribution, CI/CD, noSQL, Data Mesh, Service Mesh — and in unleashing the power of machine learning techniques for ever smarter solutions. Both are closely related. The cloud offers an opportunity to operate at a scale and speed previously unheard of, generating the kind of big data ready to be analysed in real-time. I know, it’s quite different for different organizations operating in different markets, but I yet have to come across an organization that doesn’t have a major potential to benefit from these technologies.
That brings me to another kind of debt. Inertia. It’s a well-known fact that people tend to keep doing things the way they’ve always done them. They don’t give using a relational database a second thought. They might think of using a container, but just as a lightweight virtual machine they’re used to. They might consider providing an API, but just as a wrap around an existing interface. While Inertia seems like it can do no harm, in the long term, Inertia can be costly. In a way, the more technology luddite you are, the more potential you have to unleash.
Settle your Architectural Debt
I believe that software architects should lead the way to settle architectural debt. I believe software architects should be the first to pinpoint the hidden potential of the cloud. I believe that software architects should be knowledgeable about shifting paradigms, understanding that different tradeoffs make sense today. Whether you can quantify it or not, modernisation will bring value.
Perhaps you’re not the kind of person to fight at the frontlines of emerging technologies. That’s okay. But it doesn’t mean you can simply lean back. It just means your timing is different. To help me with my timing, I like to categorize new technologies in three priority groups:
- Time to stare, technology adoption sometime out. Get an understanding of the potential impact.
- Time to be aware, technology that is going to mature or become feasible. Get ready to evaluate the technology.
- Time to prepare. Get ready to adopt the technology
I can highly recommend the practice of actively managing your technology radar. This simple tool will help you to stay on top of change – hence stay relevant as a software architect.
So, if you haven’t done so already, invest some time into getting your head around the new paradigm. Start studying the Design Principles for Cloud Native Applications. Think it through. Then read it again. Dive a bit deeper. It’s a radically different way of thinking which promises better solutions at a faster pace and at a lower cost. It’s widely proven. It’s sound. There is no alternative on my radar. And you can benefit too.
Call to action
At this point you must have a basic idea on your debt position. You may not be able to quantify it in monetary terms, but there’s no denying there’s serious money at stake. The time is due to settle your architectural debt. Go start an experiment and build traction. Stop making the same mistakes over again. Do leave the old paradigm behind when designing new solutions. Learn, grow, and prosper.
You don’t have to travel all alone. We’re here to help you along your way. We know how to micro. Now Go!
Through the MicroScope is a blog series of indefinite length, focusing on designing resilient, distributed, cloud-native architectures. Every edition will shine a different light on the microsphere. Read also the other blogs in this series.