5 ms·
> Abstraction is the essential tool that allows us to create systems of arbitrary size and complexity. A beautifully designed abstraction is easy to understand
by jstimpfle 5y ago
> Abstraction is the essential tool that allows us to create systems of arbitrary size and complexity. A beautifully designed abstraction is easy to understand and use. It is so trustworthy that you don't feel any need to worry about how it is implemented. Finally, and most importantly, it enables you to reason with rigor and precision about the correctness of the code you are writing that makes use of it.
Heh, I don't think there are a lot of proven abstractions out there. And most so-called "abstractions" are in fact not. Let me explain using two popular abstractions, ones that are so low-key that they wouldn't even considered by most.
1) Function calling. This is an abstraction that abstracts away the logistics of setting the state in a process in the right way such that the next piece of code can continue. When that code finishes, it will leave a well-defined state as well (first, in terms of the call stack, but maybe a return value as well).
Now, I contend that function calls can be the wrong abstraction in many situations, at least more often than people think, and many many functions seen in the wild should never have been created. Functions remove a lot of control where values are stored, and the storage locations can't be shared across functions, which results in a lot of nested calls that tunnel through many of the received arguments - instead of just leaving them in a common, predefined place. Also, lots and lots of functions in practice tend to amass local state, and as it is with the tree-shaped nature of function calls, once you give up control, that state is gone, so you'd better clean up after yourself. This is in fact a great burden, and very complicated systems arise to "solve" this problem, like constructors/destructors, try/catch, functional unintelligible academic theory (Monads), and other resource tracking systems.
2) Streams. In my mind, they are arguably one of the most successful abstractions ever created. A stream abstracts one of the endpoints of a unidirectional connection (the read or write endpoint). You use it by just saying "read" or "write", and very little of the complexity of interacting with that other endpoint shines through - lossyness of the connection, flow control, packet size, error handling... streams don't provide access to most of these.
This can be a very unhappy situation to the point where the code that deals with that stream would be much better off just dealing with the underlying connection directly. A huge aspect of this is flow control and scheduling - we mostly act like transmission was an atomic operation, but there is a lot of logistics involved. To hide this, OSes invented blocking interfaces, putting your process to sleep until the operation is completed, or providing simplistic non-blocking interfaces. All of this is very bad for performance and predictability, especially blocking interfaces.