Abstraction, the Basis of Computing (Part 1)

The word “abstraction” has many applications in the realm of computer science and software engineering. One immediate sort of abstraction you might think of is the graphical design of user interfaces on computers and other devices. The earliest trends in graphical user interface design embraced a skeuomorphic language of visual (and verbal!) metaphor, where actions or objects on the computer were represented as real world things. For example, the desktop metaphor interprets the computer screen as a literal desktop where you store and access files. The copy/cut/paste functions evoke the literal actions of cutting paper and pasting it onto something else, and so they were represented as such in name and in visual representation. The most common 'save' icon is a picture of a floppy disk. Above are some icons that were used on old Macintosh computers in the eighties and nineties, by seminal graphic designer Susan Kare [1]. Each icon is a metaphor mapping a digital function to an image of the real world, or an abstraction thereof.

However, that is only the tip of the iceberg for how abstraction informs nearly every aspect of computing. The graphics on the screen are not only considered abstractions of real life things or actions, but they are also abstractions of electronic data processed by the device. A text file appears to the user as a couple lines of text, but to the computer it is really an array of ones and zeros (“bits”) stored somewhere on the hard drive. When the user opens a text file, the computer reads the file bit by bit, and translates this data into human-readable text; then it translates this into visual data which it sends to the display monitor to be read by the user. For example, the string 01000001 is translated by the computer as an “A”, and then the computer tells the monitor to draw the shape of an “A”. Already there are two layers of abstraction on top of a physical store of data, and each layer is basically blind to the translation done by the layer on top of it.

Abstraction also exists as a way of interfacing between different software programs on a device. In fact, this sort of abstraction is what enable computers to be easily (re)programmable by human beings. Most programs are not written in machine code, which is composed of instructions given in ones and zeros that tell the computer how to store and process data. The layer immediately above machine code is called assembly language, and although it is human-readable, it is basically a one-to-one translation of machine code into English words. This means that the programmer still has to deal with things like memory storage and temporary memory on a literal level, using addresses on the hard drive and a couple quick-access ‘temporary’ memory spaces called registers.  Besides this being simply difficult to work with, assembly languages also tend to be specific to particular machines, so assembly programs are not easily ‘portable’ since you can’t use a program written in one assembly language on a machine that uses a different assembly language. The solution to both these problems is using a higher level language that each machine can then translate or compile into its own particular assembly code; this also has the benefit that, rather than always deal with literal addresses on a hard drive, the programmer can invent ‘variables’ with names and values, which the machine then assigns to its own memory without manual effort or oversight.

Finally, abstraction also exists even within a singular software program to facilitate the processing and representation of data. One common type of (high level) programming language is called object-oriented programming, where the programmer models types of objects and codes for their various interactions. By itself, this is already a form of abstraction since the object logic of the programs made (e.g. “only cat-type objects can meow”) exists only as a self-inflicted restriction for the programmer. The computer, especially on the lower levels, does not see cats and dogs but only arrays of ones and zeros with instructions for how to process them on the level of physical circuitry.

What interests me, however, is what is often called an ‘interface’ (as per the Java and C# programming languages, or in OOP theory in general). Unlike an object class which defines concrete behavior for objects of that class, interfaces are considered wholly abstract: they do not define concrete implementation, but only expected functionality that is to be implemented by concrete types. You might consider, for example, an interface for two-dimensional shapes: all shape objects are expected to have an area, but how that area is calculated depends on what type of shape it is (e.g. square, circle, triangle). An interface for shapes would specify that all concrete types of shapes should have a formula for area, while each shape type defines in certain terms what its particular formula is. Interfaces are thus as much of a backbone of object-oriented programming as object classes are, since they facilitate the abstraction of various different classes into one abstract ‘class’ that can then be interacted with on one common set of terms.

Although all these cases represent very different applications of the broad principle we call abstraction, there are certain common denominators that spring up and thereby help us better understand what exactly abstraction is. There is the translation of a thing into an symbolic model external to itself. Graphical abstraction recalls on one hand basic semiotics, where we map signifiers to signifieds. Yet the same thing happens when we map strings of ones and zeros to Latin letters, or when we code in a high level language that can then be translated into machine-readable assembly code (the former being an abstraction of the latter).

There is also the subsequent isolation of information in each layer of abstraction. Ideally, when using the principle of abstraction in object-oriented programming, you don’t want an object on one level to interact with an object on a lower level. Through proper abstraction, i.e. by restricting and translating data across layers, you can make it so that each layer is self-contained and thus easier to work with using its own internal logic. Using the example from before, we can ask for the area of a bunch of shapes without knowing or caring which ones are circles or squares or triangles.

I think these two properties of abstraction are really two sides of the same coin. We are dealing with the translation of a thing external to some symbolic system of meaning (i.e. a language) into that system. The resultant symbolic object is wholly integrated into its host system, and the external thing on the lower level can only interface with the symbolic system by means of its own symbolic representation—not by itself.


[1] Read more here: https://99percentinvisible.org/article/designed-with-kare-influential-macintosh-graphics-of-early-apple-computers/


  1. Abstraction is one of the things I find most engaging as a software engineer! It's cool to see this post :).

    1. thank you, and same here!! 😄 i think figuring out how to model/design software in terms of how things interact and how to restrict information flow (idk how else to put it? just abstracting?) is always a fun and interesting challenge :)

      i'm glad you liked the post! i was worried that other devs would find my use of language a bit sloppy, with how abstraction tends to be distinguished from polymorphism and inheritance etc., but i feel like the underlying principle is abstraction in a broad sense

    2. I am admittedly somewhat sloppy with my technical language as well sometimes so no worries :p.

  2. ░░░░░░░░░░░░░░░░░░░░░▄▀░░▌


Post a Comment

Popular posts from this blog

Plagiarism in Unconquered (2022)

OSR Rules Families

Bite-Sized Dungeons