It seems like the best way to design a codebase is to redesign (rewrite) it several times and then go with the most succinct design. For any given problem, it's unlikely you'll design the codebase properly on the first try. Also:
when one writes code, there are only real, present requirements. The future is pretty irrelevant
I'd disagree with this. The future of your codebase matters unless you're writing a throwaway prototype. And when you rewrite a codebase N times, you'll discover that there are ways of structuring it so that future tasks will become far easier. E.g. for Lisp you'd refactor common patterns into utility functions, and for C you'd carefully craft the interfaces between modules so that they're unlikely to be used improperly / unlikely to be surprising.
when one writes code, there are only real, present requirements. The future is pretty irrelevant
I'd disagree with this. The future of your codebase matters unless you're writing a throwaway prototype. And when you rewrite a codebase N times, you'll discover that there are ways of structuring it so that future tasks will become far easier. E.g. for Lisp you'd refactor common patterns into utility functions, and for C you'd carefully craft the interfaces between modules so that they're unlikely to be used improperly / unlikely to be surprising.