<i>> a bad one turns every small bug into an excavation.</i><p>I find that I need to debug my abstractions frequently, <i>while I’m first writing my code</i>, then I never need to dig into them, ever again, or they do their job, and let me deal with adding/removing functionality, in the future, while not touching most of the code.<p>That’s why I use them. That’s what they are supposed to do.<p>Because they are abstractions, this initial debugging is often a lot harder than it might be for “straight-through” code, but is made easier, because the code architecture is still fresh in my mind; where it would be quite challenging, coming at it without that knowledge.<p>If I decide it’s a “bad abstraction,” because of that initial debugging, and destroy or perforate it, then what happens after, is my own fault.<p>I’ve been using layers, modules, and abstractions, for decades.<p>Just today, I released an update to a shipping app, that adds some <i>huge</i> changes, while barely affecting the user experience (except maybe, making it better).<p>I had to spend a great deal of time testing (and addressing small issues, far above the abstractions), but implementing the major changes was insanely easy. I swapped out an entire server SDK for the “killer feature” of the app.