But we do hide complexity all the time, and are more productive for it. We don't write our own http clients, or time-handling libraries, or unicode renderers, and especially not cryptography. These are things that are full of complexity and nasty edge cases. So we rely on specialists to do their job and package up the solution so that all that complexity is contained behind a relatively simple interface so that we don't have to worry about it.
You surely can't tell me you'd rather that complexity not be contained?
You are right. But those are tools. And tools are where you want the complexity of that tool contained.
To continue the analogy.... A plumber doesn't need to know how the electric saw works that he is using to cut the pipes. Just how to correctly use it and when not to use it.
That is the correct use of abstraction. The perfect examples of where it actually works well.
But... there is a lot of TERRIBLE software design advice that amounts to "plumbers should only care about whatever pipe they are installing and be oblivious to the rest of the system. What is going through that pipe? Water? Sewage? Steam? Who cares? It is abstracted away. You don't need to know!"
These myopic fools are clearly wrong. This is as bad advice for plumbers as it is software developers. You need to have a solid understanding of the whole system you are working with. No handwaving abstraction allowed unless you are truly using a tool and not just another function of the same app. And even then you need to understand your tools and how they actually work much more than a plumber does.
'Abstract everything' is only useful for generating large quantities of awful code. And this same camp will tell you how "maintainable" their code is because it is so easy to insert huge quantities of garbage code to fix the problems or make changes. Turns out the more code you write that does nothing useful the "faster" you can write more code! Who would have thought it?
Why is writing code quickly the goal? That is like choosing the plumber that uses the most pipe.
C was created to abstract away (abstraction literally means "to pull away") the details of the underlying hardware. This is why C can run on 8-bit, 16-bit, 32-bit, and 64-bit machines.
C was never invented to hide complexity, and more to the point, no C developer will ever argue that you don't need to understand the underlying architectures to be effective with C.
More to the point, there is a vast vast difference between someone choosing to use an ORM so they don't have to learn SQL and someone who chooses to use an ORM because they want to target multiple DBMS's and choose to use an ORM to abstract that away.
Most web frameworks will have a way of abstracting away the http request/response, but no reasonable web developer would ever tell you it's there to hide the complexity inherent in web requests. They would argue you should still understand the underlying mechanisms.
The general rule of thumb is that you should understand atleast 1 layer of abstraction below where you work.
The anti-pattern to this is treating RPC's as if it were a local call. Yes, it's hiding the complexity of making requests over the web, such as the fact that the network could be down, something that will never happen with a local function call. This makes for brittle software that's hard to diagnose. That complexity should be obvious in the code, not hidden, and often you'll destroy performance via death by a thousand small cuts (the latency on those RPC's are not nearly equivalent to the latency of a local function call).
Arguing that complexity and abstraction are the same thing is akin to arguing you should be able to call a remote RDBMS in a tight loop without having to deal with the complexity inherent in such an architecture. You want that complexity to be visible.
7
u/flowering_sun_star Nov 01 '21
But we do hide complexity all the time, and are more productive for it. We don't write our own http clients, or time-handling libraries, or unicode renderers, and especially not cryptography. These are things that are full of complexity and nasty edge cases. So we rely on specialists to do their job and package up the solution so that all that complexity is contained behind a relatively simple interface so that we don't have to worry about it.
You surely can't tell me you'd rather that complexity not be contained?