In the second post of this series, The Software Triforce Part 2: The Power of Discipline, I covered some of the benefits my team gained by doing our stability work incrementally and without getting distracted, resulting in an encouragement to:
Have the discipline to focus on small, isolated, and specific stability-related tasks, one at a time.
We argue in this final post that using tried-and-true solutions is the single most important thing you can do to improve stability in your product. At this point, we have a clear stability goal and a disciplined approach to making progress towards this goal. But all this is for naught without actual, production-ready, stable code.
Use Tried-and-True Solutions
We all know that if there’s already a well-maintained library that does what you want to do, then you should seriously consider using it instead of starting all over from scratch. However, as my team and I went through our considerations of various libraries, methods, etc., we discovered:
The very process of digging through what was out there taught us to make implementation decisions more wisely.
What we learned in this process had a huge impact on both our efficiency going forward and on the amount of courage I had that our solutions would actually work.
We learned a 3 important lessons from this practice, so let me unpack them one at a time.
#1. Instability is infectious
The first thing we learned while looking for tried-and-true solutions is that instability in software is infectious. This idea can be put neatly by the following equations:
stable app + stable package = stable(app + package)
any app + unstable package = unstable(app + package)
unstable app + any package = unstable(app + package)
The point is that when seeking stability, any packages you use must be stable themselves, otherwise you risk undermining your own efforts.
This is one of the best arguments I’ve found against “rolling your own” version of whatever computer science primitive you need. Developers often are faced repeatedly with a problem that somebody else has already solved; don’t waste your time resolving it when you can pull a tried-and-true implementation off the shelf for already-stable performance. Chances are that the people who developed that implementation spent a lot of time getting it to where it is; all that time they spent is now time you’re not spending. (Assuming you don’t choose the “wrong” package, which we’ll deal with in the next section.)
Not only did this effect save my team time, but it imputed the trust I had in the tried-and-true package’s stability upon my app, which was quite encouraging. Once again, we found it was wiser to rely on solutions already known to be stable than it would have been to start from scratch and introduce the risk of new types of instability.
#2. It engages you with the community
Next, we learned that in order to figure out which solutions out there were “tried-and-true,” we had to engage with the community of developers using the same languages and frameworks that we were.
It’s super important to be engaged with your development community. I’m not saying that you need to go to all the meetups, be an active question-answerer on Stack Overflow, or make comments on the framework’s repo, although all of those are good. What I am saying is that you should have at least a general understanding about what is and isn’t valued by the community of developers in your language or framework. Does your community value functional programming paradigms? What about writing tests? How do they feel about object mutability?
Different programming communities are going to have different answers to questions like these, and that means that they’re also going to have different “tried-and-true” solutions for your given stability problem.
Staying in touch with the principles and paradigms of your development community will keep you in touch with what is and isn’t idiomatic, and it should inform your decision on which packages you use.
If you’re out of touch with your development community, then you might choose the “wrong” package. By this, I don’t mean that you would use a package that doesn’t work now. Rather, I’m talking about what would happen a month, a year, a few years down the road when a bad security vulnerability or bug behavior is discovered in that package you’ve chosen: will anyone still be around to fix it? If your package of choice is relegated to the abandonware graveyard by your development community, you could get stuck with an out-of-date, unstable, or worse, vulnerable dependency down the road. That’s why it’s important to consider your development community at large when choosing your dependencies:
If you don’t think it could ever get wide adoption, then you need to be prepared for it not to have readily available support.
Sometimes this is fine, and the package will still aid your efforts to achieve your stability goals. Especially if you’re not expecting your app to greatly change, or if you don’t expect the package you’re considering to introduce security problems, then sometimes it’s fine to stick with one version of the package and ignore any of its future problems. But it’s my guess that, more often than not, going with a poorly supported package would just be trading instability now for vulnerability later.
But when you know that you’re going with a solution that’s acclaimed by the majority of other programmers in your language, then you know that you’ve wisely chosen a proven, trustworthy aid to achieving stability.
#3. It saves you time
The final and most obvious effect of looking for tried-and-true solutions as you work on your app is that you’ll save yourself a boatload of time. The time it takes to install and start using a library is (almost) invariably shorter than the time it would take you to write your own version of that library. This should be old news, especially living in a world where almost 10% of all npm packages depend on lodash. People are quick to import the most popular libraries for a few reasons:
- It saves them time
- Popularity is at least somewhat an indicator of effectiveness
- There is generally a lot of information and help available for popular packages
Depending on tried-and-true solutions is a wise decision because it means a higher development velocity without the risk of hastily-written code, which in turn means you can reach your goals sooner.
Have any questions or comments? Feel free to reach out to us!
Interested in writing secure software? We’re hiring!