1. You build abstractions that are not useful in the future, or
2. Worse, you build abstractions that constrain you from making future changes.
Of course, either of these can happen anyway, but at least then you haven’t wasted a bunch of time refactoring before you know how your code base will grow.
I prefer this approach from The Grug Brained Developer:[1]
> next strategy very harder: break code base up properly (fancy word: "factor your code properly") here is hard give general advice because each system so different. however, one thing grug come to believe: not factor your application too early!
> early on in project everything very abstract and like water: very little solid holds for grug's struggling brain to hang on to. take time to develop "shape" of system and learn what even doing. grug try not to factor in early part of project and then, at some point, good cut-points emerge from code base
> …
> grug try watch patiently as cut points emerge from code and slowly refactor, with code base taking shape over time along with experience. no hard/ fast rule for this: grug know cut point when grug see cut point, just take time to build skill in seeing, patience
> sometimes grug go too early and get abstractions wrong, so grug bias towards waiting