The Theseus Paradox of Software
Recently I was listening to an episode of Malcolm Gladwell’s Revisionist History and learned of a philosopher’s paradox called the Ship of Theseus. It dawned on me that this paradox applies to legacy software, too. Software applications in the midst of a Ship of Theseus style transformation can serve users, add new features and be cleaned up all simultaneously.
In case you’re not as familiar with your ancient Greek history, here’s a brief refresher. Theseus was the mythical king and founder-hero (around 6th century BCE) of Athens. Upon his return from a heroic quest to save Athens, the Athenians vowed to send an annual tribute of gold to the island of Delos to honor the sun-god Apollo. Because the Athenians so revered Theseus, they sailed his ship every year for hundreds of years to conduct the annual pilgrimage. This is a recreation of the Argos, a ship from around the same time. Imagine this ship making the annual trip for hundreds of years.
You’d have to replace parts, and, over the course of time, would the boat be considered new? That’s the question that the Greek historian Plutarch documented in his philosophical paradox now known as the Ship of Theseus:
“The ship wherein Theseus and the youth of Athens returned from Crete had thirty oars, and was preserved by the Athenians down even to the time of Demetrius Phalereus, for they took away the old planks as they decayed, putting in new and stronger timber in their places, in so much that this ship became a standing example among the philosophers, for the logical question of things that grow; one side holding that the ship remained the same, and the other contending that it was not the same.” -Plutarch
In many ways the Ship of Theseus paradox is quite similar to software development. Is this app the same one it was five years ago? How about two? What about after the massive overhaul we just finished? If it still serves the same business users in the same capacity, but we rewrote it, does it matter?
I know I am not going to be the one to solve a paradox that eluded the likes of Aristotle, so let’s look at some of the aspects of the Ship as laid out by Plutarch and how they might apply to modern programming practices. I’d love to hear your thoughts in the comments below.
Do You Add More Than Thirty Oars?
Plutarch notes that the Ship of Theseus had thirty oars. Historical accounts of Hellenic galleys from the mid-6th century BCE to the mid-3rd century BCE demonstrate ships were getting bigger and badder. Alexander the Great built massive triremes. Dionysius I of Syracuse built galleys with six rows of oars. Ptolemy IV built titanic war vessels that wound up being completely impractical, a strategy that mirrors some lessons that recent founders in Silicon Valley learned the hard way.
All the while, the Athenians might have argued back and forth with the chant “You Ain’t Gonna Need It!” while they replaced plank and spar in the name of Theseus as yet another impressive but useless ship floundered in the harbor. Building new always affords for easy application of recent learnings or updated technologies, but the thirty-oar galley of Theseus still worked for the required job.
Could the ship safely sail the 200 kilometers to Delos? Yes.
Could the ship carry Athens’ religious delegation and a bag of gold? Yes.
Was a proud piece of mythology memorialized for future Athenians? Yes.
Sometimes it’s the same with software. Did the Ship of Theseus need to carry a catapult and squad of cavalry? Is a PySpark Hadoop Cluster needed for a small prototype? Bringing a catapult on a religious mission misses the mark just as much as over-engineering using a trendy new tech stack might. Build for the visible future — not the one you hope your business will scale to ten years from now.
Replacing Decaying Parts
While every new invention or method is supposed to save the world, the truth is that not every technology and technique will stand the test of time. Some of those experimental tools or patterns should be tested, but not to the detriment of the existing application.
Similarly, an organization’s operations evolve and change as external forces mold the business to new models or practices. When those operational practices decay, it’s important to remove them rather than “save them for later.”
A common recommendation we make in our Code Inspections is hunting for dead code and removing it. The reasoning is simple. Why spend energy refactoring code that doesn’t do anything?
Dead code in the codebase creates clutter, which makes it confusing for another developer to come in and work on the codebase. That dead code may also be an indication of unfinished or abandoned efforts. Left unchecked, it can be a big contributor to technical debt and reduces the overall value of the codebase.
Don’t be afraid of replacing decaying code, just as the Athenians didn’t allow a rotting plank to stay on their ship, lest it compromise the integrity of the vessel. Plus, if you’re using version control, the argument could be made that your code is always retrievable anyway.
Implement Improvements When It Makes Sense
New ideas, better workflows, and more resilient coding are always welcome additions to a codebase in staving off Father Time. Just because the design of Theseus’ ship was out of style doesn’t mean that new parts of the ship should also be made with outdated techniques. What if the Athenians came up with better techniques for forming or planing their wooden planks in the hundreds of years that passed? What if they sourced higher quality lumber? Couldn’t those be used on the Ship of Theseus?
Modern techniques and practices can be used on old codebases. We do it at Corgibytes all the time. Using new timber can go beyond replacing existing structures; it can strengthen them, just as Plutarch pointed out.
Keep the Ship Seaworthy
While the voyage only took place once a year, the vessel had to remain seaworthy for hundreds. If a ship can’t stay afloat, then it’s not really doing it’s most important job. While “drydocking” a boat to fix it is an option, it also shouldn’t be the standard practice for how changes are made. A ship that can’t be altered when it springs a small leak or even when a cannon ball passes through it is a lot of resources (and souls) wasted. Software that must be “drydocked” for every change indicates a brittle codebase.
Is it harder? Of course, but with tools like GitHub and practices like continuous integration it’s possible to get below the waterline of the code without running the application aground. Nothing is ever going to go perfectly, but having good carpenters (developers) was (and is) vital to keeping ships (and apps) afloat.
Whether the ship was the same or not might be irrelevant given the tasks needed of the ship. Athenians had made promises to deliver gold to Delos. Stay focused on your mission and remember “Craftsmanship in Context” (one of our core values).
Thoughts? Ideas? Questions? Keep the conversation going in the comments below.