Software needs to be delivered. That’s a cliche, but it is a fact nonetheless. When implementing a new feature (described by a user story in my case), I have to consider quite some factors: acceptance criteria, the time at my disposal, quality of code, edge cases to watch out for and also possible future extensions of functionality.
The above is not breaking news either, but when I stop and think about all these things, coming up with a very good solution is not a trivial task. Most solutions I implement are good enough. They are good enough, because they solve well a problem at hand. I can try and anticipate all the possible future additions to the current funcionality, but that can be (paradoxically) counter-productive. Don’t get me wrong – I can to some degree predict, what will be needed in near future, but long-term prediction can feel more like playing fortune teller than anything.
Of course, such description does not fit all of the software development endeavours out there. Yet I have strong feeling, that my experience is not very unusual. Because of how the requirements can change over time, I had to accept the fact, that my solutions should be good enough. That does not mean completely abandoning any pursuit for quality or abstraction in the code, no. That means getting things to “just work” state with a reasonable (so objective measure!) code quality.
It also happens so, that I think of a better solution after implementing the first, “good enough”, one. And that’s why the boy scout’s rule is for – when I can, I improve existing code. And that’s also why I shouldn’t be afraid of writing code that’s not “perfect” – I can improve it, when a better time for that comes.