It's funny you mention that. I'm often surprised how little literature there is out there on Quality in general, and how often I have to depart from Software in general and head into manufacturing/metrology to get any new/useful insight on Quality Control methodologies for software. There is, however, more to the story than Moore's Law at work.

#1 In the early days, you had very little between you and the executing machine. Your programs were more ways of doing things to ensure a particular machine would get you a reasonable answer, and it was far easier to communicate the totality of the stack, software+hardware combined.

#2 Compare the picture of the 60's-90's programmer to the programmer of today. You had to know the hardware, and do cartwheels to decompose your problem to be solvable within the constraints of the machine which you had to run it on. You were a professional optimization problem solver+a studious cross-referencer (libraries and dependency management were not as mature as they are now, nor were there as many Virtual Machine constructs to foster write once, run anywhere.

#3 Libraries were a case of build it yourself, or you ported something else by figuring out the toolchain + operating in a much smaller network of professionals to reach out to for guidance.

#4 There weren't many if any concessions to programmer "comfort" (IDE's), less static analysis (as far as I'm aware), and good luck finding documentation without paying for it.

Now:
>Many programmers are blissfully unaware of cache coherency, memory hierarchy, or the quirks of the hardware/filesystems they run on. The hardware is "the compiler writer's job" or "those driver writer's problem" (smh?), the filesystem is Someone Else's Problem...

>More and more, the solution looks more and more like "throw more hardware" at the problem to create more abstraction, which requires more intermediate steps, which takes more compute...

If for no other reason, software is disgustingly hard to Quality Control for because nowadays, it's more about having access to development talent to make the core system architecture, no matter how inefficient or bloated, maintain it, and extend it rather than boiling things down to least computtational overhead.

When you've got a thing built on a constantly shifting Tower of Babel, where your artisan knows less than a 10th of what their total set of dependencies are doing, and oftentimes are selected for their willingness to sit down, crank out the requirements, and not balk; it truly is a miracle when Quality software actually happens. Test coverage alone isn't it. Nor is refactorability, or readability. You have to have the right Software for the right people, at the right time, for the right costs, to bring about the right constellation of jobs done, to create value. None of that value, in modern thinking, should be intrinsically tied to the people making it. In fact, I have a theory that the market is trying to get away from that by favoring designs where everything you need is in the automation code itself, as it obviates the concept of the "heroic wizard coder" as we know it. Part of this Quality too, is you have to actually care about the people you are implementing for. Any programmer can create a program that works (painfully). It takes a sharp one to make something intuitive, quick to learn, and a pleasure to work with without being godawful slow.

I'd say Quality software is not something you set out to build (at least the way the Market driven ecosystem we have today works), but a happy accident when you combine all the right factors to get the job done you set out to do and keep it that way. But the roadmap to getting there is the hard part.

If anyone ever wrote a dynamic code generator that worked like a database optimizer (imagine Select implementation FROM C Where INPUTS(x1,..,xn) AND OUTPUTS (y1,...,yn) WITH CONSTRAINTS (z1,...,zn)), we'd all be out of a job, possibly all the healthier for it.

Who am I kidding, we'd all just be query writers and optimization engine babysitters for it.