Growing a codebase
One of the charming, clever, creative subscribers to my newsletter asked:
"How can I design code at the start of solving a problem... such that it's able to grow into a smart codebase as painlessly as possible... as the nature of the problem becomes better known, and the solution evolves and grows?"
A magnificent question.
The standard answer: "Knowing this comes with experience."
While true... that's not really a helpful answer, is it?
The person answering this way is really saying: "I don't know how to tell you".
And to be fair, it *is* hard to put into words. But one piece of the puzzle is to design parts of your program so they can be swapped out.
So you start writing the code, and give one sub-system a simple implementation... with its own interfaces to the rest of the code. And later, as you evolve the codebase, you can pull out the code for that sub-system, and put in something more powerful.
It's like taking the engine out of your car, and replacing it with a better one.
An example: I was writing a fairly complex application, which needed a data storage component. And at first, I just made it a simple in-memory data store.
Later, as I fleshed out the complex application... I took that whole sub-system, and swapped it out for a DIFFERENT data store... this one backed by a persistent database.
But there was one key, that made it all work: I wrote good unit tests along the way.
So when it was time to shove my grubby hands deep into this giant, complex application... ripping out its heaving heart... and plunging in a different one...
The units tests told me exactly what I needed to fix, to keep the application alive.
So the important thing is the mindset of designing your code with modularity, so that parts can be "swapped out" as you grow your codebase. And unit tests are what keep it working after the swap.
See how you can apply this to the next Python program you write.