For all those little papers scattered across your desk
I stand for the Constitution, for due process, and for community that takes care of each other.
This is extracted from a document I wrote ~2 years ago about making it easy to find and assess-for-fit internal libraries. Some of these items are both an evaluation criterion and a suggestion for the production of high-quality libraries.
Also relevant is Linux Dev Time Episode 151.
The OpenSSF publishes additional guiding questions for assessing open-source software fit via the lens of security. Many of these questions apply to internal libraries, too.
Documentation for shared libraries serves at least 2 audiences: the first needs an example or two that they can run with no extra setup or hassle. We call this the “copy-paste-run” assessment: it answers questions like “Does the library work?” and “How easy is it to glue together with our system?” This audience also tends to be what Michelle Bu calls the “eager developer.” They often want to see code run quickly so they can save time and are typically going to need the least complex parts of the library.
The second audience, Bu’s “discerning developer,” needs to be able to see the full range of supported functionality. They should be able to absorb the essential vocabulary of the library by scanning documentation aimed at them. Documentation for this audience should answer the question “Is this library adaptable to my complex use-case?”
Thinking about these two audiences naturally leads us to 2 tiers of documentation:
Other useful principles for organizing documentation include the Diátaxis framework, in which “Getting Started” is often part of a “Tutorials” section. Diátaxis also incorporates how-to guides and explanation sections. Each section fulfills different reader needs. Example Diátaxis-style documentation can be found on [internal tool]. For developers assessing library usefulness, all four Diátaxis sections provide useful information.
Seeing real-world uses of the library in action aids understanding and assessing the library. Teams are able to break down how the library fits into typical software structures and use cases, and they have additional points of contact and reference for assessing fit. Consumers who come together around a library also spark community.
Libraries should document known consumers to help potential consumers assess fit. For example, the documentation may link to a pre-filled code search on GitHub that shows library use. Or the documentation may highlight top projects that use the library well, which allows the maintainers to control for the quality of recommended examples.
This is subtly different from the “Used by engineers from” taglines on project sites like httpie, which use brand-name recognition to persuade potential consumers of fit. The goal of linking to (curated) example consumers is to build community and to provide new directions of exploration for fit assessment.
Every library embodies values and principles from its contributing engineers2. Kate Gregory’s Emotional Code demonstrates that programmers leave behind traces of human emotion in their code. Similarly, we leave evidence of design tradeoffs, technical style, and domain language3 in the crystallization of our thoughts in the form of code.
Library consumers also need to be able to determine if the engineering principles embodied by the library are a match for their use case. For example, a core application for payment processing may not want to use a library that embodies experimental principles and that lives on the bleeding edge: it may prefer a library that emphasizes stability and security. On the other hand, a new data processing system prototype may find the experimental frontier exciting to help flesh out the cutting edge library’s design and implementation. Developers regularly assess engineering principles embodied by libraries fit and share these assessments among their peers.
Documenting these principles concisely, whether alongside other documentation or in a project’s README file, helps engineering teams quickly assess principle fit. These principles are often also found in Getting Started guides. For example, the Rust Programming Language makes its guiding principles prominently visible. “Empowering everyone to build reliable and efficient software” is explained by the further breakdown:
Why Rust?
- Performance: Fast and memory-efficient, suitable for critical services, embedded devices, and easily integrate with other languages.
- Reliability: Our rich type system and ownership model ensure memory and thread safety, reducing bugs at compile-time.
- Productivity: Comprehensive documentation, a compiler committed to providing great diagnostics, and advanced tooling including package manager and build tool (Cargo), auto-formatter (rustfmt), linter (Clippy) and editor support (rust-analyzer).
Rust makes clear what users can expect from it—if these principles do not align with a particular project, Rust may not be the right fit. Rust also uses these principles to guide RFCs and the direction of the language. Other projects leave these principles implicit, instead documenting overall design or providing a technical roadmap and direction.
Principles embody several facets of a library and its maintaining team (this list is non-exhaustive):
All projects fall somewhere on each of these spectra: articulating the principles embodied by each library enables potential consumers to make informed decisions about the tradeoffs of using a particular library. As with documentation, it also helps maintainers: having a clear set of principles helps teams decide which features, pull requests, or changes to accept and which to decline.
“Object” is used here in a generic sense (as in “artifact” or “widget”) rather than in the typical programming sense (as in “object orientation”). ↩
Ruha Benjamin argues that “social norms, ideologies, and practices are a constitutive part of technical design” (Race After Technology, 2019; p. 41). We cannot readily separate creators and creations. ↩
See Young et al 2023, Stretching the Glasgow Haskell Compiler: Nourishing GHC with Domain Driven Design, esp. §3.2 Design Principle: Use a Ubiquitous Language, and the accompanying talk. ↩