Let's design a system that allows us to run virtual computers on a single hardware platform. In some part of this system we need to map real hardware addresses to virtual ones in order to isolate the different virtual computers.
Now you might need a way to take a real, logical address to a memory location on this machine and get a virtual address. You might have to run this system on many different hardware platforms and you only know the platforms you will run on today (or the next few months). Almost without thinking about it you might choose to use a virtual method on a class to define a function signature for this operation. That way folks implementing this system for different hardware platforms can create a sub-class and fill in a concrete definition of the virtual method. Now users of the system can translate an address and don't have to think about the underlying hardware platform they're running on! Abstraction!
Only it's not an abstraction.
If you attempt to formalize what it means to map a hardware address to the virtual address you will find it quite difficult because your interface provides no information about hardware addresses. In other words the virtual method does not put in all of the details of the concrete implementation and so we cannot maintain an invariant in our specifications that would ensure that we only translate valid addresses, or that translation is deterministic -- properties that would be important for users of the abstraction to truly be able to ignore the underlying complex domain. If we could write such a specification for this virtual method though, it would be very complicated, and that is a good sign this is not a good abstraction.
Abstractions are often separate from the code because they're much more general than a single program. If we came up with a better abstraction in a formal logic like separation logic or using Hoare logic -- we might be able to prove that the properties we care about hold and therefore any program that implements this specification will have the same properties. And there might be several such programs!
So what industry programmers are often saying when they are talking about "abstraction" is "indirection and vagueness." What this article is trying to show is that we can give precise definitions to our abstractions so that we can build new _semantic_ layers that have precise meaning: when I translate a hardware address I get a valid, deterministic virtual address and nothing else.
These are very useful properties to have. And I rather use an abstraction where these properties hold, rather than one that just takes care of some plumbing. There is a qualitative difference here.
Let's design a system that allows us to run virtual computers on a single hardware platform. In some part of this system we need to map real hardware addresses to virtual ones in order to isolate the different virtual computers.
Now you might need a way to take a real, logical address to a memory location on this machine and get a virtual address. You might have to run this system on many different hardware platforms and you only know the platforms you will run on today (or the next few months). Almost without thinking about it you might choose to use a virtual method on a class to define a function signature for this operation. That way folks implementing this system for different hardware platforms can create a sub-class and fill in a concrete definition of the virtual method. Now users of the system can translate an address and don't have to think about the underlying hardware platform they're running on! Abstraction!
Only it's not an abstraction.
If you attempt to formalize what it means to map a hardware address to the virtual address you will find it quite difficult because your interface provides no information about hardware addresses. In other words the virtual method does not put in all of the details of the concrete implementation and so we cannot maintain an invariant in our specifications that would ensure that we only translate valid addresses, or that translation is deterministic -- properties that would be important for users of the abstraction to truly be able to ignore the underlying complex domain. If we could write such a specification for this virtual method though, it would be very complicated, and that is a good sign this is not a good abstraction.
Abstractions are often separate from the code because they're much more general than a single program. If we came up with a better abstraction in a formal logic like separation logic or using Hoare logic -- we might be able to prove that the properties we care about hold and therefore any program that implements this specification will have the same properties. And there might be several such programs!
So what industry programmers are often saying when they are talking about "abstraction" is "indirection and vagueness." What this article is trying to show is that we can give precise definitions to our abstractions so that we can build new _semantic_ layers that have precise meaning: when I translate a hardware address I get a valid, deterministic virtual address and nothing else.