- ...and that's ok!
Let's say you're at your job. You're a programmer, working for a company, and you need to design a solution to a problem. Maybe you need to store some data to be served to users, or compute some metrics across some stream of events. It doesn't matter what it is, because you've done this before and you're ready. You've read all the articles, consumed all the blogs, and watched all the tech talks. All the requirements from all the stakeholders have been gathered, signed off in triplicate, and carved into a granite countertop to ensure they cannot be changed.
And so work begins! You design your solution in a green field inside a clean room hyperbaric chamber. Every feature is documented to perfection, the code is organized sensibly and commented well, with total coverage by unit and integration tests. QA has gone over your staging deployment with a fine-toothed comb, and found no issues. You've done a dark launch to production, monitored all the graphs, checked all the logs. You dial up the traffic, your solution works perfectly.
And yet, probably no more than two weeks later, despite all the preparation, you ship the first bug fix. Or feature addition. Or performance enhancement. You didn't do it perfect the first time. It's not your fault though! Life is messy, circumstances change, and the correct thing yesterday becomes the wrong thing tomorrow. It doesn't matter how much process and automation and best practices are layered on top, the world will change and therefore so must the code. Ultimately everything we build is imperfect and perishable.
All code, immediately after being written.
I was once someone who would say they really cared about things like "code quality", "consistency", and "clarity". Things like how variables were named and SQL tables were laid out mattered a lot. Frameworks and languages could have correct and incorrect features. A codebase with mismatching and incompletely applied patterns would call me to a refactor like a moth to a fire.
I no longer care. Only two things matter.
Tests can be nice, frameworks can be nice, design patterns can be nice, language features can be nice, CI can be nice, linting can be nice, documentation can be nice. But really what they all are is a gamble that they will be more useful in the short term than their maintenance cost in the long term. In any case, the code will move on with or without them, often to everyone's benefit.
These days, most of my decisions are made on the basis of "does it work?" and "how easy will it be for someone else to come in and accidentally break it?". If I'm working on a solo project the second question might not even come up. The rest simply doesn't matter... the code is going to change soon anyway, and all past grievances can be shed for new ones.