Building a Solid Foundation

There are a million ways to build something with code.

When you start, it’s like the sky’s the limit (and it is). Yet, starting with the langauge you choose, then the tool stack, then the initial architecture, all hopefully centered around the problem domain, you gradually build a foundation you have to build on top of, or tear up and rebuild altogether.

Usually it’s the former – rarely does the latter happen, and when it does, it’s usually way too late and it fails.

The foundation makes a big difference as to what you can build, what you may possibly build, and what you can’t build. It determines how easy or hard something is, among several other factors that play into whether or not something can, should, or will be built.

This should all be obvious, to any experienced enough dev. So why am I stating the obvious here?

Because I believe there are good ways and bad ways to build a foundation, and I’d like to move more towards the good ways of doing things.

What does this mean, exactly? For one, it means deferring decisions – every core decision paints you further into the corner of your foundation’s design. Every choice is locking your future self into a path that may or may not be beneficial to future problems.

So rather than trying to solve for all future problems, maybe I should defer decisions about that problem to when the time comes.

Of course, this method can lead down the wrong paths too. All paths here can lead to riches or ruin, and at any point you can change from one goal to the other, sometimes without even knowing it.

Most dev systems are rigid: Kanban, Scrum, and Agile all solve for being very conservative when it comes to taking risks, especially on your foundation – they are literally systems for deciding what you build, right?

Rather, we want a system that’s flexible enough to change course as needed, for as long as possible. But you have to build intentionally, with purpose, otherwise you run a heavy risk of building a “house of cards”-style infrastructure, deferring all your decisions that are possible to defer, letting the foundation grow organically.

This isn’t always a bad thing – if you’re just writing a script to scrape a site, and you want to get from A to B, great! Let it grow organically.

However, if you’re building a long-running system, something that needs to have years of longevity, you can’t possibly let your foundation grow organically – you run into the house of cards issue there.

This is all very abstract and I’m not giving specific examples, because for one, I don’t know you like that. But we can imagine a system where no architecture decisions are made, versus a system where all code changes are scrutinized intensely to make sure the pieces fit, to something in between where you defer unimportant decisions and make the calls that count, right now.

I tend towards a moderate approach, but it’s the hardest. It’s like trying to act in accordance with the Tao with every action, or for the less mystical of those among you, like trying to predict the weather with 100% accuracy every day. You can get a general sense by default, and of course, “don’t need a weatherman to know which way the wind blows”. But that’s not to say you can predict when a storm will come or where – that requires specialized equipment, training, skill, and practice.

I’m looking to build that skill, and practice. So here I am, ranting and raving about software development methodologies, in a super abstract way…at least this will help me better organize my thoughts on the whole rigmarole, all the tedium that comes with planning out a software project (or not).

I just don’t want to build houses of cards, is all. Or give birth to some organic growth creeping feature creature that consumes all it touches.

I just want to write good code comfortably. Is that so much to ask?