It's really hard to give a good example (because it's not an easy problem), but I really want to see a high-level procedure that describes (declares) every important thing that is going on (from a business standpoint). Then ideally, I only have to dive into each function once to get enough context on the main procedure. Any further dives are library/util-type calls (again, I'm talking super ideally here).
And even though I used the term "procedure" twice there, I'm talking about either FP or OO styles.
And of course (oh boy) the context can change everything.
I also feel that Local Reasoning is a very powerful capability in code. In fact, Martin Odersky the creator of Scala pointed to an article that headlined Local Reasoning as one of the clearest explanation of Why FP matters (https://twitter.com/odersky/status/1271182333467602945?lang=...).
Any abstraction (here I include complex types) is a trade-off against local reasoning. Anything that makes the reader of the code drift far away from what they're currently reading on the screen is a hit against local reasoning. So they've to be introduced judiciously.
Then it’s not declarative
> The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise. (Djikstra)
Maybe that is the juice that makes Java the 800lb enterprise gorilla that Java is, but that juice seems hardly worth the squeeze of stack traces that go on for multiple screens.
These leaks are usually performance related.
IO has not been following moores law. So you can see high level abstractions around IO leak like crazy.
And also, there is no "retiring" going on. Retiring something because of a bad abstraction almost never happens, whether it's because of performance or not.
The bad abstractions stay forever. You just don't notice it. You just master the abstraction and keep on using it.
Learning about the leaks and learning how to manipulate the high level abstractions to get around the leaks becomes an intrinsic part of the culture. It becomes so intrinsic that most people can't even wrap their mind around the flaw in the abstraction. They get defensive if you talk about it. It's invisible, but it's still there.
SQL is the most leaky abstraction I have ever seen (in terms of performance). Learning to deal with it and all it's leaks are the norm now. People don't even refer to a query planner as a leak. The technical debt is so entrenched within our culture that it's actually considered to be a great abstraction. And who knows? Maybe mastering SQL with leaks and all is not a bad way to go. But mastering SQL involves dealing with a declarative language and manipulating it in ways that leak into the underlying implementation. No amount of optimization has fixed this.
SQL isn't the only thing with this issue. For SQL the crappy abstraction is just performance related. But you see other abstractions continued to be used because simply it's too hard to retire them. Javascript, CSS, HTML, C++. Python2 (finally this has been retired). Basically it's everywhere.
Abstractions are rarely retired. Abstractions with leaky performance problems are also never retired.
(Actually I think 99% of micro optimisations are harmful, it’s the higher level algorithmic optimisation that gives the best gains.)
In that case, I'm with you, I'd rather see a pile of imperative code...
We should as an industry be teaching people how to build good abstractions, not avoiding them at all costs.
spreadsheets are a great abstraction on calculating values based on tabular data.
ORM is not such a great abstraction on top of SQL.
I agree wholeheartedly with that. I'm not sure that's the direction an ORM should be targeting the abstraction in the first place. It seems more productive to abstract the code away from the point of view of the database than to abstract the database away from the point of view of the code.
I think the database's query results should be exposed directly, so that the developer could control the DB properly and directly (such as get access to cursors, etc)
No, no, no! Do not do this because then I have to go read all of the abstractions to actually figure out what the hell my computer is actually doing.
It seems nice in theory, but I’ve spent way too many hours stepping through over-abstracted declarative code with my debugger, getting frustrated at the opacity of it all.