“Shipping first-time code is like going into debt. A little debt speeds development so long as it is paid back promptly with refactoring. The danger occurs when the debt is not repaid. Every minute spent on code that is not quite right for the programming task of the moment counts as interest on that debt.”
—“Introduction to the Technical Debt Concept”. reviewed by Ward Cunningham
Agile software development guru Ward Cunningham coined the term “technical debt” at a time when Microsoft Windows 3.0 (1990) was enjoying its first commercial success. Netscape Navigator (1994) was still a few years in the future, never mind Internet Explorer (1995). Those were Wild West years for personal computing and the internet, and Cunningham’s technical debt concept embodied principles gaining traction at that time, especially “early and continuous delivery of valuable software.” Software needed to ship fast, even if it wasn’t 100% complete, then deliver high-value updates at a pace that kept users happy.
But doing business by these principles is easier said than done. To be competitive, agile software teams must ship when a product is “good enough,” but the gap between good enough and perfect must be filled in eventually. It is a “debt” owed to the buyer. If that debt isn’t paid, it accrues interest over the short term. Too much interest accumulation will eventually kill a project, allowing competitors to crush it in the market and forcing its developers to deprecate (abandon) it. On the other hand, debt can be a very positive tool when used to build strong, high-growth assets.
To illustrate the concept, Microsoft faced a technical debt problem in 1991 (the same year Cunningham first used the term) with its Word product. According to Microsoft software engineer Rick Schaut, Word 5.0 for Mac was glorious, but the concurrent Word for Windows 2.0 had more features, and WordPerfect had even more features than that. The Mac audience clamored for at least parity. However, the Mac and Windows versions used different code bases, both of which had become “crusty.” In its efforts to ship quickly, Microsoft had established technical debt and saw two ways to pay that debt: either rebuild both applications from a new, common code base or rebuild Word for Mac from the Windows version’s codebase. The former solution would have yielded a technically superior product but taken much more work and time. Microsoft felt it didn’t have that time and picked the second option. It was good enough. Five years later, the company had driven every competing word processor into oblivion.
Some might argue that Microsoft’s decision led to years of code bloat, often called cruft. Cruft begets more complexity, potentially leading to unneeded redundancy, and incurs its own technical debt. It also means developers must address prior projects’ debt while working on other new projects, which increases time demands, stress, and even resentment if staff feel that debt could have been avoided. Excessive or poorly managed technical debt can become a demoralizing force that limits organizational growth.
Technical debt is relevant to all software types, but few application types feel it with more strength and speed than real-time voice and video. If you want your real-time communication applications to function reliably and in ways that minimize technical debt, now is the time to plan accordingly.
Avoiding Technical Debt
Coding methodology will make or break a project, and cruft can kill. The example above from Microsoft’s early Word dilemma should be edifying. Microsoft prioritized taking the shortest path to an acceptable product and thereby not allowing technical debt to accumulate. A unified code base promotes simplicity, and, as the agile software principles indicate, simplicity is “the art of maximizing the amount of work not done.” However, simplicity is best implemented early, and Microsoft was too late in the game. Sometimes, there’s no choice but to incur technical debt, and businesses must choose between the lesser of two evils. Developers can pursue unified code by being diligent in their efforts to streamline and scrub out cruft, especially in the early stages of a project. This includes non-essential additions and unmaintained plugins.
The Real Time Communication (RTC) space moves particularly quickly. You will always have to walk on the edge between conservative “use what’s proven and works” and riskier “get in front and have an advantage” approaches. One way to strike this balance is by basing your work on well-maintained industry standards. For example, using WebRTC media channels will alleviate some of the build and support headaches you might encounter with a lesser standard, such as WebSockets for audio handling.
In a similar vein, established operating system implementations may not provide cutting-edge functionality, but using them will help cut down on time-sucking integration and troubleshooting. In fact, commercial products may not even need external services. Avoiding such dependencies whenever possible may pay dividends when it’s time to deploy on a short schedule, especially if those external services have been modified or deprecated. Keep your dependencies as simple and narrowly scoped as possible by staying aware and informed of the implementation ecosystem. The more you can stay abreast of alternatives, the more able you’ll be to make the right choices to minimize technical debt. The last thing you want to do is commit to RTC projects that were deprecated because a better solution appeared and you were among the last to notice. Standing still encourages technical debt of its own.
Solid documentation and processes can prevent vast amounts of debt. As with all kinds of history, those who don’t track their mistakes are bound to repeat them. If your developers can work in sync on different tasks and project phases, you can minimize overlap, maintain workflow clarity, and reduce misunderstandings that can morph into bad code.
While this may sound obvious, be rigorous in your testing, especially when you’re working under agile deadlines. it can be tempting to cut quality control corners, especially if the paradigm of “good enough” has fostered some complacency. But RTC applications have little room for error, including with how they operate across the surrounding network. Is trunking optimized? How do the applications work with various session border controller configurations? What impact do various TURN server locations and distances have on client streams? Some users will want the protection of firewalls, but what impact will they have on communication latency? Video and VoIP are notoriously intolerant of lag increases, and it may take an excessively cumbersome amount of coding to mitigate the effects of some of these delays.
This leads us to one of the stealthiest vectors for technical debt creep: avoiding pain. Between the idea of “good enough” and a keen desire to keep performance high, it can be tempting to pursue options that deliver the “best bang for the buck” yet may not adhere to industry standards or have strong developer backing. We can fool ourselves into thinking that simple trumps thorough. The reality is that you need both.
It’s a Trap! (Beyond Best Practices)
The concepts described above should always be kept in mind, but there’s much more to avoiding technical debt with RTC applications. The following suggestions might be considered more advanced.
Even if applications somehow magically didn’t change, devices still would. Thus, you always need to examine the mix of codecs and other capabilities on devices. For example, there was a period in which Apple didn’t support a range of codecs. Shim libraries serve as useful tools in such situations, filling in bits of functionality and making it easier to code across platforms. However, shims also must be kept up to date, and you run the risk of device updates rendering your solution outdated (incurring technical debt). If your RTC application has been optimized for Product Generation 5 and the manufacturer suddenly releases Generation 6 with a superior native RTC implementation, you’re already in deep debt.
This device debt trap is particularly insidious in the mobile space, as avoiding it requires examining all the different types of devices that must be supported. Different devices will likely have different codecs, and these varying codecs will have their own implementations for hardware acceleration. As a result, your RTC implementation may perform beautifully on one device and stutter hopelessly on another due to low compute resources. Also, keep in mind that poorly accelerated RTC software can result in massive battery consumption. This article offers a stellar example of H.265 implementation for WebRTC and may help you avoid several technical debt traps in your mobile implementations.
Another common debt trap is the use of non-native implementations. There may be situations in which non-native implementation options seem to have every advantage. However, nothing is ever free. Even when these implementations seem to excel in every functional or performance measure, keep in mind that the platform developer will devote its resources only to maintaining the native implementation. If you go with non-native, you become responsible for that maintenance. Which party is more likely to test on a broader range of hardware and with more parameters assessed? This is a good reminder of the maxim “keep it simple.” Don’t implement what isn’t necessary.
Similarly, embrace open standards whenever possible. GlobalTURN is a great example because there is a simple, open, widely supported version. A few organizations implement their own alternative implementation. One of the benefits of this approach is having only a single-line config change during implementation. There is no technical debt trap and no getting stuck with someone’s walled garden platform.
How Subspace Can Help
At Subspace, we come from long, varied tech backgrounds, and all of us are keenly aware of the costs of technical debt. We strive to take every opportunity to reduce technical debt internally and make sure our customers face the fewest possible debt liabilities. We work to reduce their debt burdens in many ways.
With Subspace PacketAccelerator, RTC traffic scales easily without performance loss, thereby dodging another technical debt risk. Customers enjoy reduced jitter and packet loss of up to 99 percent.
And, arguably the best of all Subspace’s debt-avoidance benefits for RTC - GlobalTURN.
GlobalTURN offers a serverless, worldwide TURN environment, easily configured into your RTC app and network. Plug it in, and let us do the maintenance. If you're running a monster TURN environment, it's time to eliminate that technical debt once and for all.
Try Subspace GlobalTURN today and use that extra free time to innovate instead of maintain.