The best designs have both clean abstractions and small/simple implementations.
If you have a clean abstraction but a complicated implementation, then there are probably lots of moving parts and sub-steps that can go wrong. No user is completely isolated from implementation: take shell completions for example. Shell completions are this nice simple interface -- push "TAB" and the shell will help you out if it can. But because there is so much machinery going on in the background, a slow or unavailable NFS volume (for example) can make your completion suddenly grind to a halt, even if you don't care about that NFS volume right now.
What Richard is talking about in this example is having as little extraneous stuff going on as possible. The fewer moving parts, configuration files, commands you have to run, etc. the less there is to understand, the fewer states the entire system can be in, and the fewer sub-steps there are that can go wrong.
The hallmark of a truly great abstraction is that it gives you the functionality you need without getting in your way, and that higher-level abstractions can be layered on top without the lower-level abstraction getting in the way.
It is not widely known that you can have both clean abstractions with simple implementations.
At the Viewpoint Research Institute[1] (co-founded by Alan Kay), they are trying to have their cake, give it to everyone, and eat it too[2]. They already have some successes, with for instance a set of several programming languages that can implement itself, from bare-bones X86 to sky-high abstraction, in less than 1500 lines; a TCP stack that takes 200 more lines (a 50 fold reduction compared to a typical C implementation); and more.
Efficiency wasn't even the priority. But as it turned out, many optimizations were either very generic (across several languages), or plain unnecessary (some things are faster than anticipated, to the point of being good enough).
There is, ultimately, a direct conflict between abstraction and efficiency. Abstraction gets its power by using indirection: generalizations that stand in for specific cases. Making abstractions concrete involves a flattening of all these indirections. But there's a limit on our ability to automate the manipulation of symbols - we don't have Strong AI that is able to make the leaps of insight across abstraction levels necessary to do the dirty hackish work of low-level optimization. The fabled "sufficiently smart compiler" doesn't exist, and is unlikely to until we have Strong AI.
I'll further submit that a design that has clean abstractions and simple and small implementations either doesn't do much to the point that it's not very useful on its own, or if it is useful the complexity has moved somewhere else, perhaps in metadata or configuration or tooling. It's like there's a law of conservation of complexity; there is a certain amount of irreducible complexity in useful programs that cannot be removed, and remains after all accidental complexity has been eliminated.
Seeing http://vpri.org/html/work/ifnct.htm I think we have good reasons to believe that we currently are several orders of magnitude above that amount of irreducible complexity.
So, while I mostly agree with what you just said, I don't think we've hit the bottom yet. Silver bullet-like progress still look possible.
If you have a clean abstraction but a complicated implementation, then there are probably lots of moving parts and sub-steps that can go wrong. No user is completely isolated from implementation: take shell completions for example. Shell completions are this nice simple interface -- push "TAB" and the shell will help you out if it can. But because there is so much machinery going on in the background, a slow or unavailable NFS volume (for example) can make your completion suddenly grind to a halt, even if you don't care about that NFS volume right now.
What Richard is talking about in this example is having as little extraneous stuff going on as possible. The fewer moving parts, configuration files, commands you have to run, etc. the less there is to understand, the fewer states the entire system can be in, and the fewer sub-steps there are that can go wrong.
The hallmark of a truly great abstraction is that it gives you the functionality you need without getting in your way, and that higher-level abstractions can be layered on top without the lower-level abstraction getting in the way.