When Third-Party Libraries Add Technical Debt
Don’t reinvent the wheel. We’ve all heard the phrase at some point in our careers as software engineers. Often, this leads us to integrating third-party libraries in our applications for out-of-the-box functionality. While these have their place in speeding up development time, there are certain scenarios where creating your own libraries, modules, and patterns saves time for future development.
When should I create my own library?
If you’ve worked at a larger company before, you may already have incorporated their proprietary libraries and design patterns.
However, it’s not always the case that you would have had access to an existing design system or architectural stack. When you have to build a system from the ground up, there are some things to keep in mind.
Is there a custom design or functionality?
Developers often use a library as a base and then add features onto it. Sometimes, we end up “monkey patching” and creating overrides for functionality already included in the library. If done incorrectly, this could lead to future bugs — especially when the library is updated.
One particular case I’ve seen across teams is on the UI side, with CSS architecture getting out of hand. This is particularly true for libraries around Bootstrap or Google’s Material design system, since many event-driven components update the appearance using inline styling. That means that in order to implement your custom designs, you’ll need to use !important, which breaks specificity. If new developers come along, they may not realize this and end up implementing their own duplicate code somewhere else.
It’s not always about using !important, however. In addition to CSS selectors, you may find yourself breaking your team’s naming conventions (i.e., you use BEM, but the library uses Atomic). Your architecture will grow in complexity and be more difficult to maintain.
Do production applications depend on the library to provide native functionality?
This one is tricky as it relies more on context. I’ve found that this applies to hybrid mobile apps (Ionic for Angular) or mobile application frameworks (such as React Native) more than anything else.
Over the years, these libraries have become more robust, but it’s important to keep the following in mind:
- Updates to packages may break your code.
- Updates to browsers and operating systems have the potential to break the app faster than the maintainers can fix it.
- You’re no longer in control of your app; you’re dependent on the community or hacky refactoring.
This is not to say that these frameworks don’t have their place, but proceed with caution.
Are there requirements in place to meet ADA or cross-browser behavior?
It’s important to remember that just because a library is on Github doesn’t mean it’s been fully tested. Likewise, just because it’s recommended by other developers (whether through a blog post, stars on Github, or word of mouth) doesn’t mean it’s ADA compliant. If your project requires special attention to accessibility, it’s worth looking into building your own components.
So when should I use a third-party library?
Third-party libraries are not all bad! As mentioned earlier, there are reasons why a team would want to use them. These include:
Implementing a common design pattern, such as Google’s Material design library. If you’ll be following the same patterns as the library anyway, and the designs don’t call for any deviations from the default behavior, this is the way to go.
Quick prototypes. If you need to get something working to show a client or stakeholders, using an existing library helps speed up the process. Once you receive a sign-off, you can determine whether or not the library still meets your long-term needs.
Startups and small software engineering teams. Sometimes, we find ourselves as either the solo engineer or a part of a small team that needs to crank code out to meet deadlines quickly. This is especially true if your team consists of developers who have less experience. In this case, it might be more beneficial to use a third party library.
Skill level of the team. If your team has less experience and it will take longer to build a custom library than your deadline allows, it’s worth finding a stable third-party library as a stopgap. Additionally, if you anticipate that the team will continue to grow with lesser experienced developers, keeping them in mind is crucial to the health of the team.
It’s important to note, however, that once a library has been written, goes into maintenance mode, and includes thorough documentation, this won’t be such a pressing issue anymore.
My application requires customization, but I don’t have much time.
This situation comes up frequently. In order to support your case, there are some things you can do to make it easier on the team and ensure you deliver on time. If either of these concepts are a concern, talk about the benefits with your team and determine if it’s the right approach. Here are some things to consider:
Implement a design system / component library or modules.
If your team has the time and bandwidth, look into creating your own packages. Mid-sized and larger companies may find using a design system particularly useful as you can extend it across all company branded applications.
Once your design team has the patterns in place, the development team can create a component library. This works well for a single company, but if you need to white-label your application or create a component library that works across multiple clients, it’s beneficial to create a base library and extend it across applications. That way, you reap the benefits while still enabling the use of custom themes.
More work up front leads to saving time and money in the long run.
Management for lack of time and resources.
This is dependent on leadership being on board, but if your engineers are heads-down all day every day, it can be difficult to carve out time for further internal work. These are some concepts I’ve found useful.
The first concept is to dedicate a few hours a week for the team to swarm and contribute. There are different ways to do this:
- Working 40 hours up until noon on Friday, then taking the extra 4 hours on Friday afternoon to work on internal projects;
- Implementing an 80/20 rule of 80% daily work and 20% internal work;
- Or creating a hack night once a week or every two weeks for interested developers to stay after work and contribute.
Another concept is to incentivize the team with a bonus to put in extra time. This is my least favorite, but there are engineers who would prefer the additional pay over less hours worked. It depends on your team dynamics and company culture.
At the end of the day, the 80/20 rule is something I’ve found to be the most effective, since it allows the team to work without burning out. Take caution when asking the team to work additional hours, as this can disrupt work/life balance and can make some employees feel excluded or pressured.
Include custom services documentation in your onboarding.
One of the arguments for using a third-party library is around documentation. Your team should be creating documentation as standard practice, but this is especially important for a library or set of modules. In addition to documenting how it’s used along with examples, your team should make it visible and easily accessible.
Formalize structure around custom services contributions.
The downside to creating a custom library is maintaining it. This is true for third-party libraries on Github as well, although there’s a community there that can make pull requests to fix bugs. Since this will be an issue as to whether or not you roll your own code, it’s worth ensuring there is a process for contributing to keep moving forward.
- Is this component used in at least 2-3 places throughout the app?
- Have we written unit tests?
- Has it been peer-reviewed by at least two other developers?
- Have you updated the documentation?
- Do you have an example of the feature on an internal component library site?
These are just a few of the ways we can ensure our code quality.
In the end, choosing between a third-party library and one that is custom-built depends on your team’s business requirements, use cases, and dynamics. This decision is highly contextual, and requires discussion with the broader team as a whole.