First, what is technical debt and why is addressing it important?
Technical debt is a concept in software development that reflects the implied cost of additional rework caused by choosing a limited, often ‘easy’ solution over a more durable and complex approach that would take longer or have higher development costs.
It is not always easy to clearly show a client how spending their time and money to keep technical debt down benefits them. New features, functions, and designs are obvious, but structure and other items, not visible to anyone outside of the development team, are also important and come into play later in the life cycle of the application. Left unchecked, it can end up costing more and adding development time when future features are needed.
To try to make this a little clearer, let’s use the analogy of building a house. If you have a house and want to add an extension or another level, you have engineering considerations around your foundations and load bearing walls. Will they be able to hold the extra weight? You need to know that your wiring and services meet current standards or you may run into trouble.
But fixing your foundations or re-wiring the house won’t make your house look any different. However it is necessary work to ensure you can move forward with your home expansion plans. Software is the same.
Then there is the matter of wear and tear on your building. Over time, materials can deteriorate or get damaged and this can compromise the structure of your building. This is also true of software — older software may contain vulnerabilities which can be exploited or it may use code that simply does not work with your new features.
So, when developing new features, a developer should perform routine maintenance to keep an application up-to-date and functioning well. This includes writing tests to ensure new features don’t break existing features, updating the framework to the latest version, and ensuring security updates are kept current, etc.
As an example, upgrading your application Rails version to the most current version will not bring a visible benefits to the business in the short term. But updates often address security issues, which can prevent the awkward event of being hacked or coping a lawsuit because data wasn’t kept secure. After all, if you’ve been negligent in updating your software against known or published issues, you are vulnerable and ultimately responsible for any data loss.
Indirect cost of technical debt
There is an indirect cost to be paid for allowing technical debt to accumulate. This accumulation will very likely hit your back pocket even if you don’t see it on a balance sheet.
Just like financial debt, if left for longer periods of time, technical debt will accumulate ‘interest’ making it harder (more expensive in time and money) to implement mandatory changes. Feature development becomes increasingly difficult or even impossible. And the codebase can become a mine-field of undocumented errors, held together with twine.
When building an application, smart development includes ensuring adequate resources are allocated to write sufficient tests, perform software version updates, performance refactoring and the like. All in addition to new feature development. If this is not invested in, the new feature development is likely to create future issues with the maintainability of your application and increase your technical debt. A small technical debt might be tolerable but letting it grow can make your application malfunction in the future and cause the loss of precious data and/or customers. We see it happen all too frequently.
At reinteractive, we aim to maintain a balance of features and maintenance, to ensure we reduce technical debt while building out new features. Our standard process is to fully test new features as they are implemented and refactor processes when necessary. The continuity of this process ensures the project’s maintainability and stability, avoiding dead ends and expensive full code rewrites (an unfortunate by-product of other processes). And through the process of developing your new features, we also provide feedback on any other key issues with your application.
Even so, occasionally accruing technical debt is inevitable. For example, the Ruby language keeps evolving. New versions are released and it’s not always possible, or viable, to upgrade immediately without major overheads or code re-writes.
Other examples that come to mind are older applications. Sometimes clients come to us with older applications, where code maintenance has been neglected for years. Old software versions can become dated and, when past its use-by date, could become dangerous to use. Security vulnerabilities are sometimes found and need patching.
When approaching new feature development, which is generally what the product owner wants to prioritise, outstanding technical debt may cause the budget for creating new features to blow out. This occurs because of things like vulnerable software packages, an incomplete test suite, or other refactoring that is required for optimal performance. Keeping your application healthy is crucial for success.
Specifically with Ruby on Rails, every new version provides performance improvements and feature updates that improve development speed. Time invested upgrading Ruby and Rails versions will ultimately decrease development resources needed for future feature development.
Handling Technical Debt:
To properly address technical debt, it’s crucial to first understand the amount of debt in your application. Tools like brakeman or bundler-audit can give a quick overview of security vulnerabilities in your Ruby version, Rails versions and your gems.
Running skylight.io on your rails application can give insights into controllers or database queries that are breaking or taking an abnormally long time to run. Codeclimate is one of many tools that can give good insights into your test coverage and overall code quality.
These tools (and there are many others) allow you to get an understanding of your technical debt. Knowing and fully understanding the problem is the first step to resolving it. You can most definitely do the work yourself to understand the state of your application code, but if you need a second set of eyes on it, we offer all of the above along with a complete report on what we find in our Ruby on Rails Application Review Service.
A good approach to resolving technical debt comes from devoting a set amount of hours every week or month to updating your application. Like setting aside every Friday afternoon to patch any vulnerabilities, increase your test coverage or upgrade versions. At reinteractive, we created our CodeCare to accommodate teams that don’t have the in-house resources to carry out this maintenance. It includes monthly scheduled hours to apply all security updates and to optimising the application or carry out updates and feature requests for our clients.
You are better off knowing and understanding what technical debt lies within your application and addressing it before you find it’s gotten out of hand. And in the worst case scenario where it has gone rampant, requiring a re-write of the entire application codebase.