In SaaS, technical debt isn’t a bug, it’s a feature – it’s a feature of creativity and velocity.
People are writing more code to solve more problems than ever before. Of course, they are not all equally successful. It’s common to refer in the aggregate to code that doesn’t do so well as (squirm and wait for it ….) technical debt.
The term delivers on the visceral affect of regret. “If only some developers in the past had been more virtuous, frugal, expert, what have you, we could have… (“Closed that deal! Avoided infuriating that valued customer! Not spent all weekend debugging that broken RC build! Prevented that data breach! Defeated that dastardly competitor!”)
In modern software development, velocity is the intended outcome of distributed SaaS and cloud-native environments. It’s backed by a real explosion in the expressive power of code and data. Shouting “technical debt” might feel good. But perhaps it’s time to admit that the standalone epithet creates needless friction.
Technical debt isn’t a bug, it’s a feature – it’s a feature of creativity and velocity.
Looking for payback in technical debt
I’m not arguing that we dismiss technical debt; it’s too important. Rather, it’s that we understand where it comes from before we decide what to do about it (besides enjoying complaining about it). The most important source of technical debt is not what originates from your coding. It comes from your customers.
This doesn’t mean customers cause technical debt any more than one can blame developers. (Engineers do seem to like to blame technical debt on other engineers: more here). Neither are all developers equal. Some write better code, are more likely to get it right the first time, and are faster to find and fix problems – in the best cases, by a factor of ten.
What developers all universally lack is perfect, permanent omniscience. No developer always knows exactly what every customer will always want. For that matter, neither do customers. This is the true origin of technical debt. Any effort to translate a given customer want or need into code that always works exactly right the first time will always fall short.
When will your code your walk the talk?
The culprit for this gap? “It’s in the requirements, of course.” But that’s a fallacy that mature developers are quick to dispose of. There are no perfect requirements, any more than there are perfect programming languages.
“Although this may seem a paradox, all exact science is dominated by the idea of approximation”Bertrand Russell
Consider the classic contrast between Java and Javascript. Their similarities generally end with their respective names. One notorious difference is the typing of variables. Typing can lock in assumptions, which introduces important efficiencies. Java’s strong static typing constrains the descriptive versatility of its logic. You may have dogs and cats living together in the same pet store, but no amount love or money will get them to multiply.
Arguably, the various forms of dynamic typing languages arriving before and after JavaScript have contributed far more velocity than Java in the software industry. Some may sneer at their messiness. They encourage the proliferation of REST APIs everywhere. They foster the illusion that “big data” is the answer to anything. No matter: there is no denying that more people, in more places in more walks of life, gain access to the descriptive power of code than ever from JavaScript. Even if the precision of grammar leaves something to be desired.
Descriptive precision is a hard-fought achievement. “Although this may seem a paradox, all exact science is dominated by the idea of approximation,” to quote Bertrand Russell. Living with that paradox is critical to building and maintaining a successful, complete SaaS stack, and the technical debt that comes with it.
It takes time to tame the savage beast
Years ago, I heard Chris Hoff refer to the changes ahead for cloud software platforms as weapons of mass abstraction. All the power unleashed by putting data together with automated processes? It creates a ton of time pressure. It’s easy to miss the need for humility, and with it, the criticality of investment leveraging technical debt.
Mary Wollstonecraft Shelley wrote and published Frankenstein; or, The Modern Prometheus in 1818; she was 20 years old.
Though movies have diluted the story, Mary Shelley’s classic novel (which she published at age 20, the age of many a 21st-century coding prodigy) has much to teach about managing the risks of learning (heavily constrained by the properties of the hardware). When standing up a full-stack multi-tenancy SaaS architecture, choosing languages and environments that make sense in a time-constrained environment, mistakes will be made in the pursuit of knowledge.
Two centuries after Frankenstein, in the year 2020, hindsight is not a luxury, it’s a requirement. Ward Cunningham, who is credited with introducing technical debt into the vocabulary of programming, brings hindsight back to the real utility of the term:
“I’m never in favor of writing code poorly. But I am in favor of writing code to reflect your current understanding of a problem, even if that understanding is partial. It was important to me that we accumulate the learnings about the application over time, by modifying the program to look as if it had been as if we had known what we’re doing all along.
“The explanation I gave to my boss I called the debt metaphor, and that said that if we fail to make our program align with what we then understood, we were going to continually stumble over that disagreement. That would slow us down, which is like paying interest on a loan with borrowed money. You can do something sooner than you might otherwise, but then until you pay back that money, you’ll be paying interest.”
Technical debt expresses the relationship between time and money. It’s often said that paying down technical debt requires finding ways for customers to finance this cost. Of course, they’re reluctant to do so.
Fixed scope software projects often fall into this trap. They presuppose a complete understanding of a successful outcome. A happier ending allows for changes in scope as the project team learns what works, and what does not.
So what do you call it when the speed of customer-facing feature development is paid for by charging interest to infrastructure and cloud functions outside of the direct control of the application developers?
Frankencloud. In my next post, more about how to tame this beast.