Abstraction barriers in real life

How abstractions at the right level help us more easily get things done

Programmers today spend a lot of their time defining, creating, and manipulating various levels of abstraction. That’s part of the reason that you don’t see anyone writing 0’s and 1’s directly into their text editor— on the binary level, not only is it impossible to get anything done within a reasonable amount of time, but it’s incredibly hard to get anything done at all. Thankfully, over the years, abstractions have been designed and implemented that allow for a much faster translation between the ideas that people have, and the code that will actually implement those ideas.

In the field of human-computer interaction, this has helped reduce the gulf of execution, which is how much effort must be made to translate a goal ..

I want to create a webpage

..into a concrete series of actions ..

I need to create a document. I need to add the appropriate syntax. I need to upload it to the server

Dennis Ritchie, one of the originators of the C programming language and of the Unix operating system, put in place many of the abstractions to the programming world. We’ve gone from binary and assembly to C, Unix, and a plethora of compiled and scripting languages.

What’s interesting about having a layer of abstraction, is that there has to be some kind of promise of reliability at the lower levels. Abstractions and the interfaces between them are a promise to “keep secret” the essential details of how something lower-level works. If I’m writing HTML and I still have to think about how the bits are being moved around, then I’m not really gaining anything. In fact, the complexity of the task increases because you’ve lost some transparency between what you do and what happens. Butler Lampson and Edsger Djikstra explain this nicely: (from Hints for Computer System Design )

“In other words, they [implementations behind abstractions] are things that can change; the interface defines the things that cannot change (without simultaneous changes to both implementation and client). Obviously, it is easier to program and modify a system if its parts make fewer assumptions about each other. On the other hand, the system may not be easier to design—it’s hard to design a good interface. And there is a tension with the desire not to hide power.”

“An efficient program is an exercise in logical brinkmanship.” (E. Dijkstra)

This isn’t restricted to the world of computing, however. As a concrete example, let’s look at a breakdown of an abstraction barrier in the real world, courtesy of a menu from a nearby place called Chirping Chicken. When you’re ordering takeout food, you have two goals:

  1. Selecting the food, based on price, taste, your hunger, etc
  2. Figuring out when to expect the delivery

But observe how broken their delivery abstraction is:

chirping chicken menu

The interface that consititutes knowing when your food will arrive doesn’t exist. There is no functional abstraction. You, the person holding the menu, are presented with all of the variables involved — knowing what the weather is, knowing how far away you are from the place, knowing the time of day, knowing whether your order is large or not, even unknowable things like how many other people are ordering at that time. The burden of evaluating the meaning of everything is shifted to you. Just imagine if instead of naming the individual dishes, they just listed the recipes instead! Compare this to an efficient abstraction of the same interface:

“Please allow at least 30 minutes for the delivery of your food. We only deliver in the upper west side.”

Much simpler, and it hides the complexity of the lower levels while still providing a useful service. These kinds of abstractions and breakdowns of abstractions are everywhere: takeout menus, software, tax forms, furniture assembly instructions, etc. Keep an eye out for them.

Of the computationally-enabled people I’ve met, the smartest and most impactful people are those who can use their intuition to understand what level of abstraction is required for a particuar problem. Not more abstraction than is neccesary, but just enough to enable achieving a goal without distracting low-level details.