A History of Code Reuse

Rafael Medeiros
7 min readOct 27, 2020
Photo credit: nArchitects

When software first started to be commercialized, it was built and shipped as a commodity: A box with a set of floppy disks or CD-ROMs. If ordered by a company, it could even come with developers to code some customizations on site, but the software itself was essentially the same. Usually a flagship for a software house, it changed slowly, with releases once or twice per year. Code was already being reused in the form of libraries: A company or individuals developed some drivers or components to access some hardware, database, or display a custom visual controller, and licensed it for others to bundle in their applications. IDEs like Borland’s or Microsoft’s came with tons of them and were usually enough. It was a centralized model. The library’s author was the only one committed to detect bugs, think about new features, and deliver updates. There wasn’t much (if any) open source, and updates also took months or years.

Then, in the late 90s, a hype started promoting that code could be a living thing. That it could and should swiftly adapt to constant new necessities and evolve according to whatever goal it was meant to follow, like a natural selection. This hype was backed by Object Oriented Programming and the growing adoption of the internet.

Despite the fact that Simula already introduced objects in the 60s, and Edsger Dijkstra and David Parnas were already emphasizing that the structure of a software system matters and getting the structure right is critical, it took 40 years and some companies exploring software development commercially and loosing lots of money, for the code reuse penny to drop. Not that programmers didn’t reuse their code, they did! But not in a structured, conventional, and collective way. Every experienced programmer had his own assortment of utility functions and libraries collected or built individually during one’s career, and it followed a very subjective way of solving problems. Programming was more like a craftsmanship or artistry than actual engineering. Nobody wanted to touch another’s code, it felt invasive if you knew the guy, or abhorrent if you didn’t, like using somebody else’s toothbrush. More often than not these functions made sense just to the programmer who wrote it, and every time a new one had to give it maintenance, whole blocks of expensive caffeine-induced life-sucking work could be deleted from existence to make room for a brand new unproven unstable and possibly untested code, until of course the next guy to take up the baton arrived and restarted the cycle. This patching could only happen so much, until sooner or later the code became so messy that nobody could read it and rewrite all those features from scratch would be actually faster and easier than risk to break something. This unmaintainable state could even occur if the same original programmer had to work the code after some time away from it, because he couldn’t remember what or how he was thinking so long ago. I started my career in mid 90s, so I saw it all happening too many times.

If you’re not that old, know that in the beginning software was written mainly as structured control flow constructs of selection and repetition block structures, just like one would write an absurdly specific recipe. When drawn, this procedural thinking could resemble a quite schizophrenic circuitry. For instance, an algorithm to open a locked door would look like this: (1) get the key; (2) insert the key inside the lock; (3) repeat twice: turn the key clockwise; (4) remove the key; (5) if the door has a lever handler (….) else if the door has a knob handler (…), if outside push the door else pull the door X degrees… and so on and so forth. And it would work alright.

But simply by following the Four Principals of Object-Oriented Programming, programmers started to gradually evolve their way of thinking not as an abstract set of instructions, but as concrete objects relating to each other. The last paragraph’s example devised in an OO approach would give us the interfaces Key, Door, Handler and Lock. Key would have the methods insert and remove; Handler would have the method open. Lock would have the method turn accepting a parameter to indicate whether clockwise or counterclockwise. Door would have the methods open and close receiving a parameter indicating from which side. They would have properties too, like the lock’s turn state or the door’s opening angle, or anything else to declare how things are in each moment. Now, all these pieces could interact objectively to fulfill the task at hand. The Key, being an interface, could be instantiated by a concrete PunchedKey, or a DoubleBitKey, or a SerratedKey, the door could be any kind of door, and so on.

The code would obviously have more lines, more files, and possibly look absolutely obvious, but that’s exactly the goal! It would be easy to read not just whoever wrote it, but to anyone else no matter how new to the system. Everybody knows what a key is, what a door lock looks like, and how those objects are supposed to interact. If someone investigating a crash reads that the key is being inserted in the handle, it becomes obvious what’s wrong and what must be altered for the procedure to complete without error. That is what you achieve by using OO. Structured programming takes our code to an abstract world of our own; OO anchors our rationale to a shared reality where peers get to participate. As Martin Fowler said in 2008: “Any fool can write code that a computer can understand. Good programmers write code that humans can understand.”

From there to here things grew fast. Code could now be easily understood and shared, and people started to use the internet to collaborate around them. The Free Software Movement was established in the 80s but it’s in the turn of the century that we see communities thrive, not by coincidence, at the same time OO started to become commonplace. That locking mechanism from the previous example could now be packaged as a separate module and imported by other applications. Several parties using the same module would expose it to different scenarios and conditions. If a bug were discovered in one of them, every other application using the same module would benefit from its correction without having to experience the same bug. Software was evolving like living organisms and the term Software Ecosystem started to make sense. Eric S. Raymond said in 1999 what is today known as Linus’ Law: “Given enough eyeballs, all bugs are shallow”.

Large pieces of software also became shareable among applications. A set of small components designed to access databases could be bundle together to form a framework useful to anyone that needs to access a database. A set of components devised to serve an application over HTTP and dealing with all the performance and security challenges it requires could be bundled into another framework. And even these two frameworks could be merged into a single bundle and leave to the application developer only the business requirements, to be written over a structure as stable as only the collective contribution of a worldwide thriving community could deliver.

Some very old schoolers compressed their source code folder with a date or a number in the file name for versioning, then shared those files via mIRC, e-mail or FTP. CVS and SVN didn’t get much attention out of the corporate environment except by some very innovative communities. It wasn’t until 2008 that a one of a kind service was launched: GitHub. If you are reading this, I don’t think it’s necessary to explain why. The perfect environment for open source collaboration was erected, and the internet had a de facto location to meet, collaborate, discuss, and socialize around software. Git is distributed. So if you were using a component and discovered a bug, instead of opening an issue and waiting for it to be prioritized, you could just all by yourself synchronize the repository to your machine, fix it, and submit the altered code as a pull request to be revised and merged. And if the core committers took too long to respond or didn’t accept your request, you could just fork their repository into your Github account and maintain it from that point on. It has never been so practical to collaborate.

I can’t talk about code reuse without mention the book “Design Patterns: Elements of Reusable Object-Oriented Software” by GoF, published in 95. Now that anonymous programmers were massively collaborating throughout the internet, consensuses were bound to rise on how to deal with common recurrent problems, like handling user input, accessing outside data, etc. This book filled that gap, and others followed the lead. All kinds of design patterns were being naturally selected by popularity. Code written by different people looks very much alike, standardized, once the correct way of doing something is agreed.

Science is all about innovation. Engineering is all about standardization. As software programming started to consolidate from science to engineering, we started to take standards and best practices into account. Not necessarily because we think a given design pattern is the fastest, shortest or the best way to our specific case, but because we are actually writing code to be read and maintained by others. Even documentation shrank in size because the code itself were telling much of the story.

I like to think, as scientist Freeman Dyson once wrote, that "A good scientist is a person with original ideas. A good engineer is a person who makes a design that works with as few original ideas as possible. There are no prima donnas in engineering."

--

--

Rafael Medeiros

Language agnostic software engineer, ex-BearingPoint, ex-Deloitte, ex-IBM; started coding in mid 90's, and saw first hand all disruptions since then.