How to Prevent Your Software’s Slow & Painful Death
I’m having a hard time finding the source, but I read somewhere that software is “done” the same way dishes are “done:” only if you never plan to use them again.
Among engineers, this is a controversial statement.
“You mean I can never put this project down and move on to the next thing?” they complain. Some might come up with obscure counterexamples, like, “What about cat or wc?” offering the names of extremely simple programs first written in the 70s. (Old as it is, wc received a bug fix just last February.)
Obscure counter-examples aside, the adage is true if you manage or build software applications. Over the course of a year, any number of things can erode the quality of your software — without changing the code at all:
- Security flaws are discovered and patches are released to fix them
- APIs can deprecate or remove features on which your software depends
- New devices are released, and your code may need changes to support them
- Users’ expectations change, raising the bar for what is considered essential in an app
We’ve encountered two slow deaths recently. In both cases, there were no longer any full-time engineers on the project. The business needs for the app had been met (or rather, the software reached a point of “good enough” and there was a decision to stop spending money on development). All was well, and we parted ways.
A couple of years later, the software required some seemingly small changes which, no surprise, ended up taking significantly longer than expected.
In one case, the android SDK had changed enough that we needed to update the app’s framework version, which turned into a number of small changes and chasing down bugs.
In the other case, a library used in the app had a security flaw serious enough that Heroku (our hosting platform) would not let us deploy until we fixed it.
What began as a way to save money and engineering resources turned into a slow and painful death. Reviving the software then became an expensive, time-consuming project.
As a product or business owner, what can you do about this eventual death? How can you keep your software’s code from degrading underneath you?
Write Integration Tests
Integration tests exercise your whole app, running it similarly to how it would run on a user’s device. You don’t need a ton of these, but a few useful ones are:
- New users can register an account
- Existing users can log in
- Users can edit/delete resources (posts, comments, projects, etc) that they own
- Users cannot access resources they don’t own
But writing integration tests isn’t enough. You also need to run your tests on every code change.
Tests represent guardrails around your app, but tests that aren’t run will be ignored. Make your tests difficult to ignore by setting up a Continuous Integration process to run them on every code change.
But running tests on every code change isn’t enough either. You also need to make code changes.
This may seem like strange advice — shouldn’t we change code only when necessary?
I’ve seen projects that did have automated integration tests, and they did run on every code change. But two years went by without any code changes.
Reduce the time it takes to get up and running. Carefully document your processes for setting up a new development environment and deploying changes.
This is true for new developers on a project, but also for developers coming back to a project after a hiatus. It is good to document how to set up the development environment, but also how to run tests, deploy to staging and production, and any other related tasks specific to the project environment.
A few dev shops I’ve worked with completely erase their development environment every couple of months and then recreate it according to the instructions. But if something goes wrong, the instructions need to be updated. At a minimum, introduce new engineers to your application and have them update the README.md as they go along to make sure it includes any “gotchas.”
The good news is that it isn’t difficult to find things to work on. Dependencies go out of date, customers find bugs, and product owners think of new features. While saving up a long list of these fixes might seem economical, I encourage you to spread them out for these main reasons:
- Prevents updates and bugs from compounding
- Ensures a solid user experience for the greatest amount of time
- Keeps the app top of mind, so your engineers don’t have to re-learn and re-discover the code’s characteristics
Our advice? Make sure there’s active work on your application every month. There’s almost always something to do (a minor tweak, a bug to fix), and working on it consistently will keep your app well-maintained by updating libraries, fixing failing tests, etc.
Having this post-deployment process will extend the life of your software and keep it functional, improving your ROI and keeping your users happy and engaged.