The earliest computers in the 1940s (ENIAC, Colossus) had no stored programs at all. To change what the machine did, you physically rewired it — rearranging cables and switches on plug boards. “Programming” meant people (often women, like the ENIAC programmers) standing in front of a wall of patch cables rerouting connections. Every new calculation meant a new wiring configuration. There was no concept of reusable anything — the program was the physical machine state.
Punch cards and stored programs (1950s–1960s)
The stored-program concept (von Neumann architecture) changed everything. Now instructions could be encoded on media — first punch cards, then magnetic tape — and fed into the machine. This was the birth of software as a distinct thing from hardware. Code reuse barely existed. Programs were written for specific machines, in machine code or assembly language. If you needed a sorting routine, you wrote one. If your colleague at another institution needed a sorting routine, they wrote their own.
Libraries and the compiler era (1960s–1970s)
As high-level languages emerged — FORTRAN (1957), COBOL (1959), C (1972) — compilers began shipping with standard libraries. FORTRAN’s mathematical subroutine libraries were among the first widely shared reusable code. The C standard library (libc) gave programmers a common set of functions for I/O, string handling, memory management. But “sharing” meant your compiler vendor included it, or your institution maintained an internal collection, or you literally mailed magnetic tapes to each other. There was no public registry, no dependency management, no automatic installation.
Unix and the culture of small tools (1970s–1980s)
Unix introduced a philosophy that shaped everything that followed: write small programs that do one thing well, and connect them together. This was component thinking applied to operating systems. But the components were command-line utilities and system libraries distributed with the OS itself. Code reuse existed, but it was curated — someone at Bell Labs, or your university, or your company decided what was available. If you wanted something that wasn’t included, you wrote it or you found someone who had and asked for a tape.
The shift to public sharing (1990s)
The internet changed the economics of sharing code. Suddenly distributing a library to a thousand people cost the same as distributing it to one.
- dpkg (1994) — Debian created the first true package manager for Linux, tracking which software components depend on which other components and installing them in the right order. The operating system itself was now assembled from managed parts.
- CPAN (1995) — Perl’s Comprehensive Perl Archive Network was a landmark. For the first time, any developer could upload a reusable module to a public registry and any other developer could discover and install it with a single command. This established the pattern that every language-specific registry would follow.
- RPM (1995) — Red Hat’s package manager, another approach to the same system-level dependency problem Debian was solving.
- apt (1999, Debian 2.1) — Built on dpkg, apt made dependency resolution and installation feel seamless at the system level. You typed one command and the system figured out everything that was needed, fetched it, and installed it in order. This was a key technical innovation that normalised the idea of automated dependency management.
Mass adoption (2000s–2010s)
The language-specific registries multiplied:
- RubyGems (2004)
- Maven Central (2004, Java)
- PyPI matured through the 2000s (Python)
- NuGet (2010, .NET)
- npm (2010, JavaScript)
npm was the tipping point. It didn’t invent the concept, but it made tiny, single-purpose, freely published packages the default culture for the largest developer community on earth. The dependency tree went from being something system administrators managed carefully to something that grew organically, automatically, and largely invisibly every time any JavaScript developer started a project. By the mid-2010s, it was normal for a simple web application to have hundreds or thousands of transitive dependencies.
The era of mass adoption and explosive growth had arrived.

