One of the favorite topics my friend Bob Daly and I like to discuss is the concept of the software “stack”. It’s pretty standard practice by those who build software systems to think about the different parts of a system in terms of their relative positions within the layers of the vertical “stack”.

Starting at the hardware, and working all the way up to the end user, the stack includes all the software components that implement general capabilities. This practice of thinking in stack terms helps one stay mentally organized when making software component selections for a system, and it helps when communicating about and integrating such components.
The stack metaphor makes a lot of sense in the world of software, in which one man’s abstraction is another man’s implementation. One of the most common patterns in software engineering (and many other fields) is to implement generically useful components that other developers can integrate into their systems. And, this integration generally follows a “black-box” approach, in which only the abstraction (or interface) must be understood in order to use the component. The implementation under the covers need not be understood. In this sense, the interface provided by a software component identifies its effective position on the stack, relative to other software components.
Interestingly, the stack metaphor also reflects the history of software in general. We can think about the evolution of software from the early days when the only software a computer had installed was the OS… to the advent of the GUI… to the standardization and success of the database… and all the way to present day in which we have standardized components present at several different levels. These stages of history roughly correspond to the stack layers. As time passes, the stack grows taller and denser.
I think it’s safe to say that most software developers find it useful to think about software components in terms of “stack position”. This way of thinking comes naturally, since it reflects the current state of the evolution of software. The stack provides a frame of reference that enables one to ask questions like “what other options do we have at this layer?”, or “where does this component fit into our stack?”.
So, having given a little rundown of the concept of a software “stack”, this brings me to the point of this post. How do we identify the generic layers of the software stack that could be universally accepted? This is an exercise in high level software categorization. To start, we need to ask the question what is the definition of a layer on the stack? I will propose my definition:
A layer of the software stack represents a generic capability that is commonly present within software systems, and usually drives the creation of community-defined standards.
So, firstly, the stack layer corresponds to some general capability that software systems typically have. Of course, not all systems must employ software components from all layers of the stack… the design of some systems may exclude certain layers. Rather, the stack is a frame of reference that describes the generic layers which a system could employ. Secondly, each layer is centered around a suite of standards. These standards are defined by the community of developers and other stakeholders in an effort to support interoperability across implementations. So, as time passes and the software world evolves, a solid stack layer becomes more mature, standards are defined, various implementation alternatives are created, and ultimately a set of commodity components emerge.
Back to the main question of this post - how do we define a set of stack layers that would loosely represent the breadth of the software world? I’ll take a stab at it. This is the set of canonical stack layers we came up with:
Packaged App
UI
Middleware
Data
System
Yea, I know - this is too simple… What’s the point, right? Well, the point is that you have to keep it this high level in order to make it universally acceptable. And once you have this high level frame of reference, you can then drill down to the next level of granularity. Pretty much any software component could be assigned into this simple stack. It’s generic enough to do this. And even if a component is not exactly matched to a specific layer (as most won’t be), you could assign it above or below a stack layer. In fact, this is the only reliable way a universally accepted stack can work… that is, to think of the stack as a set of “way points” (as Bob puts it), and then assign the software component to some relative position along the stack. This way, you get the benefit of classifying a component into the stack without getting hung up in unending debates about exactly where it goes. The net result is that you can assign a component a stack index value, which would be relative to the way points. For example, I’d assign the java object relation mapping (ORM) framework Hibernate a stack position above the Data layer, but a little below the Middleware layer.
Try it. Think of a software component, and where it would go in this stack. Are there any components that could not be assigned? Probably not. Please shoot me a tip if you can think of any. The goal of this post is to work toward a high level software stack that could be universally accepted. I’ll be coming back to this concept in later posts, and providing more context. Thanks for reading.