A heuristic we use at work is to not introduce an abstraction layer until there are at least two different implementations required.
That is if you think you'll probably need multiple implications, delay introducing an abstraction until you actually do.
Also, there are different ways of providing abstraction.
Perhaps you don't need to abstract the entire implementation but, as an example, rather change one parameter from passing a value to passing a function returning a value.
That is if you think you'll probably need multiple implications, delay introducing an abstraction until you actually do.
Also, there are different ways of providing abstraction.
Perhaps you don't need to abstract the entire implementation but, as an example, rather change one parameter from passing a value to passing a function returning a value.