Abstraction is a question of less over more. But is it also a question of high over low? It turns out that the common way of describing abstractions in terms of high-level and low-level hides a number of assumptions, some of which suggest that we often look at abstraction the wrong way up (or down).
When those involved in software development are accused of not living in the real world, there may actually be a case to answer. There are many things about software and its development that appear to be back to front or inside out or the wrong way up. Take, for example, the case of the common tree. We have hierarchies for directories, for method calls and for class inheritance. We refer to these structures as trees. And where is the root? Highly visible and at the top. The leaves proliferate at the bottom, often obscured and hidden from immediate view. Never mind the colour, this orientation is not exactly tree-like.
Like the classic experiment where subjects are asked to wear prism glasses that invert their view of the world, we adjust. What used to appear upside down now appears normal. We cease to notice the difference. In the case of trees this is not really a problem: the properties of the abstraction are more useful to us than perfect fidelity against the metaphor. The inversion is simple enough not to be confusing and it is rarely misleading.
Which leads us neatly to the concept of abstraction and the way it is often used. This flipped view of the world is not always so free of problems.
Consider first of all what abstraction is: the act of omitting or taking away. We can consider problems, solutions, models of problems, models of solutions and so on without becoming lost in unnecessary detail — detail that has been abstracted. Different abstractions take different points of view, omitting certain kinds of detail in order to emphasise others — "The ability to simplify means to eliminate the unnecessary so that the necessary may speak" (Hans Hofmann).
While the practice of abstraction is intrinsically neither good nor bad, we can judge the outcome: a good abstraction is a simplification that allows us to reason about a concept or work with a design more effectively; a poor abstraction is one that misleads us either by omitting necessary detail or by including unnecessary detail. It is often mismatched abstraction that leads us astray: using a crowded class diagram beset with operation and attribute minutiae where a sketched package diagram would have been more useful; using a programming language designed for science and engineering to do systems programming; using the London Underground map as a guide to London's overground geography.
So, what is so upside down about abstraction? In constructing a system we often stack different abstractions on one another as appropriate, leading to a layering of abstractions. The issue arises when we shift from speaking about layers of abstractions to levels of abstraction. These two expressions are not synonymous and have quite different implications. The latter implies there is an intrinsic ordering to abstraction, which in one sense is true: a perspective that leaves more out than another perspective can be considered more abstract. It might be better to refer to this property as degree of abstraction. One other aspect that might be ordered is granularity. Sometimes when people speak of levels of abstraction they are actually referring to granularity of abstraction, which is the more precise term.
In many cases there is no obvious ordering, but people nonetheless impose one, often by implication. For example, some might argue that FORTRAN 77 is a higher-level language than C because it is organised around arrays and operations on arrays, useful for many science and engineering applications, and it doesn't have a model of memory locations and management. On the other hand, some might argue that C is a higher-level language than FORTRAN 77 because it supports structured control flow, user-defined data types, data abstraction and dynamic memory management. The benefits afforded by each language's abstraction choices are almost entirely complementary in nature, which makes any kind of total ordering between the two languages highly contextual and personal. I know where my personal preference lies, but that's not relevant here: what is relevant is that I can say from personal experience that attempting to use FORTRAN 77 for systems programming is a tedious and awkward experience, a painful experience in misaligned abstractions.
The problems in discussing and reasoning about layers of abstractions are compounded by a perception of altitude, the tendency to talk about higher and lower, with an implied judgement that higher level equates with better and lower level equates with worse. It is in this sense that the inverted view of the world becomes noticeable. People often speak of domain-specific languages or analysis models as higher-level abstractions that are closer to the domain of the user than lower-level abstractions, such as bits and bytes, and so therefore better for working closely with users. The stated goal is that we should be thinking more in terms of the problem domain — high level — than the solution domain — low level.
Wait a minute. If this is the goal, it's something of an own goal. While the intent is well founded, the terminology is the wrong way up.
Talking about the problem domain as being at a high-level of abstraction and the machine domain at a low-level reveals an ingrained bias. What is the nature of the abstraction? What is it that is being left out? Machine-level details, the bits and the bytes, the programming language types, etc. Techies might never question this but, from the point of view of users, the world in which they carry out their business is significantly more concrete than the abstract realm of software. Talking about the user domain in terms of concepts familiar to users involves, from the user perspective, little or no abstraction. The further you go into the domain of software the less real and more abstract things become. It is the real world and associated problem domain that are gradually omitted.
We need to be more careful with the assumptions entrenched within common terminology. If you consider the world of the machine as the concrete starting point, the world of the customer is more abstract. If you consider the world of the customer as your concrete starting point, the world of the machine is more abstract. So, if you're trying to come across as genuinely customer-focused, user-centric and domain-driven, you need to be low-level rather than high-level. Abstraction is not so much a question of altitude as a matter of starting point and distance from it.
This blog is a revised version of an article that first appeared in ObjectiveView in 2006.