Lately I’ve been working in Node, and that means I have access to all the open-source modules on npm. It is easy to add a dependency on any of them. But is it a good idea?
Not every library is production-grade.
Not every library (or service) is something that I want my production code to depend on.
The first thing I look at when a module comes up in an npm search is: how many weekly downloads does it have? This is a cheat. “It’s production grade if other people use it in production” is a reasonable heuristic, but it doesn’t tell us how code becomes worthy of extensive re-use.
What does it take to make a production-grade library?
Some static qualities:
- The code works as expected.
- It is fast enough.
- It has a well-designed API that lets me write readable code to call it.
- The documentation is accurate and complete enough.
We look at:
- What version is it on?
- When was the last commit?
- How many committers are there?
- How many answered questions about it are on StackOverflow?
These touch on something deeper: how does the library change?
When I build my software on top of a library (or runtime, framework, toolchain etc), I want that library to be solid — and I want it to become more solid over time. I don’t want it to shift under my feet!
I want to know:
- When there’s a security problem, a fix is released promptly.
- Useful features are added (but not too quickly).
- New features follow the pattern of existing APIs.
- When I upgrade, my code will continue to work.
For bonus points:
- Before I upgrade, I’ll still have access to the documentation for the version I use.
- There is advance notice of upcoming features.
- Someone from the core team responds to GitHub issues, StackOverflow questions, and tweets of despair.
I expect a production-grade library to practice responsible change.
Responsible change considers the larger world, all the people and software depending on the system that’s changing. It starts with backwards compatibility, regression testing, and careful API design. It continues with documentation, expectation-setting, and responsiveness to questions.
Very little of this happens in the code. Responsible change is a property of something larger. Whether in a company or a team of volunteers, a production-grade dependency is part of a symmathesy. Software resilience comes from people — people who have a mental model of how the software works. People who are actively involved in keeping it safe, and making it more appropriate for the shifting present.
That’s why we look for a team of committers, for recent attention, for a broad base of interest.
Most npm modules have a single author and haven’t changed in years. That’s fine! No open-source author is responsible to anyone for putting more work into that code than they darn well please. There are other ways to use this code than to depend on it.
If I can’t count on code to change responsibly, I don’t want it to change at all. I prefer to freeze the version of the library forever. If it needs to change, that’s my responsibility. I fork the library — or for similar effect, cut and paste the code into my project (with attribution).
This reduces the code that I have to write, but it does not reduce the code that my team is responsible for.
There are two kinds of open source: production-grade code with a community or company behind it, and code that I now own.
Next time you type “npm install,” make a guess as to which one you’re getting.