How did "abstraction" and "hiding complexity" become perceived as such fundamental virtues in software development? There are actual virtues in that ballpark - reusable, reliable, flexible - but creating abstractions and hiding complexity does not necessarily lead to these virtues. Abstraction sounds no more virtuous to me than indirection.
>How did "abstraction" and "hiding complexity" become perceived as such fundamental virtues in software development?
They aren't just fundamental virtues in software development, they're the fundamental basis of all cognition. If I twiddled with every bit in my computer I'd never write a hello world program, if I wrestled with every atom in my coffee cup I'd never drink a sip of coffee.
Abstraction and information hiding is the only way we ever accomplish anything because the amount of information fitting in our heads is astonishingly small compared to the systems we build. Without systems of abstraction we would literally get nothing meaningful done.
Decades ago, when The Structure and Interpretation of Computer Programs taught us that programmers fundamentally do two things: abstraction and combination; and we are interested in programming languages insofar as they provide means to those two ends.
The two classic "hard problems" of computer science - cache invalidation and naming things - are both aspects of abstraction. Cache invalidation is a special case of making sure the abstraction does what it's supposed to, and naming is the most important part of causing the abstraction to have meaning.
Not parent, but I have a similar impression. Design patterns, clean code, and several of these well known tools were particularly useful during C++ and early Java eras, where footguns were abundant, and we had very little discussion about them - the Internet was a much smaller place back then. Most of the developer work was around building and maintaining huge code bases, be it desktop or server, monoliths were mostly the only game. And many initiatives grew trying to tame the inherent hazard.
I think that microservices (or at least, smaller services) and modern languages allow the code to stay more manageable, to the point where Java devs now are able to dismiss Spring and go for a much simpler Quarkus.
What languages do you work in? Would you be happier or more productive if you had to be aware of the quirks of every ISA and interrupt controller your code might run on?
Abstraction is good, in the way that leverage is good in the physical world: it is not always necessary, but people who are aware of the tool are vastly more capable than those who are not.
Part of it has to be that finding and defining abstractions is fun like a puzzle so programmers like doing it and finding ways to justify it after the fact
I disagree. There are base abstractions you can’t avoid, of course, like the machine code of your computer, or the syscalls presented by it. Using these is not abstraction, unless you choose to build up interfaces of reusable pieces. Abstraction is structure. You still have to actually write some code that can be organized into structure. You could write code using just those base abstractions if you wanted, or as many do, choose libc as your base abstraction. Watching a program through strace gives you basically this view, regardless of the abstractions the program actually used to achieve the result.
Some abstractions are so ingrained you don't even think of them as abstractions. A file is an abstraction. A socket is an abstraction. The modern terminal is an abstraction.