Is introducing abstractions too early in a software project akin to "premature optimisation"?

Most software developers are aware of the trap of premature optimisation, and hopefully, most try to avoid it. The term is usually used with respect to the performance and efficiency of software, for example, optimising for a lower memory footprint sooner than necessary.

I think the introduction of abstractions too early in a software project can be similarly problematic.

In my own projects I tend to err against creating abstractions too quickly, especially at the prototype or MVP stage of a project. My early project code, when assessed by "clean code" standards or SOLID coding principles is often a nightmarish mess of large class files and "inappropriate" coupling.

But, in this form, it is loose, fluid, and easily changed according to early feedback. I've come to the realisation that introducing abstractions too quickly can be just as bad a practice as never introducing abstractions at all.  It can also lead to implementing the wrong abstraction, which not only prematurely fixes you in a particular direction, but can have big knock-on effects on how you start to reason about future changes, and even the system as a whole.

I have to catch myself though. The drive to refactor, abstract and deduplicate is strong, and it's immensely satisfying too. The smaller the project, or the clearer the scope, the easier it is to build in legitimate abstractions early on. But it's always worth being mindful about whether you're introducing them because its appropriate right now, or just because it's what you tend to do out of habit.

So if your initial working code looks horrendous, but works, you may actually be on the right track!

Test it. Deploy it. Get feedback. Iterate. Just remember to clean it up as you go.

See also: Shitty First Drafts