A lot of meta software design/architecture posts kind of just slide off my back; I've heard most of it before, and most of it falls into the "usually right, sometimes wrong" bucket. But occasionally I run across a post which really challenges me, even to the extent of haunting me in my daily work.
The mindless tyranny of 'what if it changes?' as a software design principle, is one of those posts.
Part of me wants to rationalize his points so they also fit into the "usually right, sometimes wrong" bucket. I've done quite a bit of work in areas where making backwards incompatible changes to an API is simply not an option. Either there's too many clients deployed which are never going to get updated, or the API is actually a library which can't break by its very nature, or there's too much existing code using tied to the old API that breaking it would be far more trouble than its worth.
Throughout this work I've built up a lot of mental heuristics, most that I can't quite put into words, for designing APIs in a way that is flexible to future requirements. A lot of it comes down to leaving room for optional fields.
But now I'm haunted. Everytime I feel one of these heuristics kick in, the ghost of Chris is at the window, watching me. Am I wasting my time, and making my code more unintelligible, for no good reason? All code is ephemeral, I know that, so maybe I should just embrace that attitude here too. Just run to the finish line, get the feature done in the most braindead way possible, if it's not compatible for some future feature just throw the API away and start fresh.
And then my past comes back to counter-haunt me. The entire premise of my v4 rewrite of the radix project was to design the perfect API. Something that is so perfectly aligned with the requirements of a redis driver that it could simultaneously be simple to use, extremely fast, and trivially extendable via its interfaces. Arguably that process started with v3, which got a lot of the way there but not quite. With v4 I think I got it right. There's no warts, no weird corner-cases where "actually that thing doesn't work with that other thing", no places where an internal implementation leaks behavior out of the interface.
For now anyway, time will tell.
So now what? Maybe what it comes down to is time. Truly future proofing an API requires time. Time to understand the problem space completely. Time to test different solutions. It requires others to have the time to try your attempts and give you feedback. It also requires a stable problem space in the first place, which is more attainable in something like a database driver. Most of all it requires a lot of patience to see the process through.
In most cases those hurdles will never be cleared, and trying to future-proof an API from the beginning is just complicating things for no eventual payoff. So just do the thing, throw it away later if it turns out to be not be right, keep the code dumb all the way through.
Until the next haunting post turns me upside-down again.