I write code for a living. I also write code in my spare time. Code written in my spare time has turned out to be much more valuable than code I write “on the job”.
Rare is it the case that I get to touch a pristine greenfield project. The reality of the day job is that there is a daily expectation to take ownership and infiltrate a dangerously illegible foreign jungle authored by at least a dozen developers with vastly differing opinions on how to code. Venturing into a legacy codebase where your survival depends on navigating hidden twists, turns, and dead-ends (without google maps), ends up looking more like a horror movie than coding.
But everybody plays the fool sometimes, getting caught in their own hubris when starting in fresh earnestness on their own “greenfield” project. In trying to build something from scratch that is “better than legacy”, one often ironically builds something akin to legacy code (or worse than it!). The painful lessons from building legacy from our own greenfield are invaluable, as they ultimately sharpen skills critical to surviving a range of conditions in the deep wilderness of “others’ legacy”. To embrace the humbling realization that all legacy code was once greenfield, grounds us as we empathize with the hostile jungle we are lucky to at least get paid to explore.
In the pursuit of better product, better software is a prerequisite; but as in all things in this world, there are trade-offs to be made. When you start small, the trade-offs are incremental and almost entirely reversible. Both great things for a small team with a small budget. Architecture is a big word thrown around in software development that is fancy for describing “setting boundaries with your code”. There are a lot of opinions aka “best practices” on where, how, and when to set those boundaries. Just like in relationships, setting boundaries is a healthy practice. The problem lies in how to go about doing so.
Tech changes, problems evolve, and valedictorian systems following reasonable design patterns break. One solution today may not fare well tomorrow, hence the thrill of working in tech. Things move fast, and so it’s important to realize the code written today is a stepping stone to something better tomorrow. The following is my recommendation in this increasingly chaotic ecosystem of changing APIs we affectionately call “the web”:
- Start small – build lego pieces that are easily understandable and have a tiny surface area (they only do 1 thing well)
- Stay small – quickly it’s tempting to grow things, just like you regularly clip your toenails or get a haircut, sand down your lego pieces to keep them from becoming a play dough nightmare.
- Refactor – being able to quickly reorganize the structure of your codebase without breaking it’s functionality despite the growth of the product is a sign of healthy code. Do it regularly as a “spring cleaning” exercise to check the vitals and test the clarity of your system (without 1. it becomes increasingly hard to do this step). Tests become your best friends here (stay small with them too).
- Adapt – it’s simple to respond to changing requirements when you’ve started and stayed small, and refactored consistently to test your code, so discipline and structure actually pay off in being flexible later in the game of development.
- Fun – coding is supposed to be an intellectual blast. Keep these things top-of-mind and everyone will want to befriend your codebase.
Although the above is applied to how I think about coding, it’s also influenced how I think about other aspects in life like relationships and money. In starting small, you can afford to make mistakes and learn from them by keeping risk low (low risk, high reward).
“Do not be afraid of making mistakes, be afraid of not having made one for too long”