02:27:33
This talk dissects the history of a prevalent software architecture pattern—compile-time hierarchies that mirror the domain model—and argues that its widespread adoption, despite early evidence of a superior alternative, represents a significant 35-year mistake in software design.
The central argument is that the encapsulation boundaries in object-oriented programming (OOP) were often placed incorrectly. The popular model drew boundaries around objects (like a 'Mech' class) to encapsulate all their data and behavior. However, a more powerful approach, first demonstrated in the 1963 program Sketchpad and later in the 1998 game Thief: The Dark Project, is to draw boundaries around systems (like a 'Physics' or 'Combat' system).
This alternative architecture, now often called an Entity Component System (ECS), prioritizes system-level logic and data locality over object-level inheritance, leading to more flexible and performant designs, particularly for complex, interactive software like games and simulations.
The story begins with Looking Glass Studios, an influential game developer known for titles like Ultima Underworld and System Shock. For years, their approach to in-game entities used what the speaker calls "fat structs": large, singular data structures containing data for many types of entities, differentiated by type fields or flags.
During the development of Thief: The Dark Project (1998), they radically changed their approach. Instead of fat structs or the then-popular deep inheritance hierarchies, they created a system where an entity was merely an ID. This ID was used to look up and aggregate data from discrete, system-specific data stores (e.g., a Physics system, a Combat system).
This was arguably the first commercially released Entity Component System (ECS). The crucial difference was the placement of encapsulation boundaries: not around domain-model objects, but around architectural systems.
In contrast, the dominant OOP style encouraged a direct translation of the domain model into a compile-time inheritance hierarchy. A classic example, used in early papers by Bjarne Stroustrup and others, is a Shape class with derived classes like Circle and Triangle.
The speaker clarifies that the critique is not of OOP as a whole, but specifically of this practice of building deep, compile-time inheritance trees that tightly couple the software's architecture to its domain model. This model makes certain types of changes and system-level optimizations difficult.
To understand how the hierarchy model became dominant, the talk delves into its origins:
Nygaard and Dahl credited their subclassing idea to a 1966 paper by Tony Hoare (of Quicksort fame) on "record handling." Hoare's paper proposed a solution for working with records (structs) that could be of different types. He suggested using a tagged (or discriminated) union—a struct with a type field and a union of possible sub-types.
To use this structure safely, Hoare proposed a conditional statement (a switch on the type field) that would allow the compiler to know which part of the union was in use within each branch, ensuring type safety. This is a powerful and often preferable alternative to inheritance-based polymorphism.
Simula 67 originally included this concept (an inspect
statement), but it was lost when the language's concepts were translated into C++. The talk argues that we ended up with a less effective version of what Hoare had already described.
The history goes back even further to the work of Douglas T. Ross at MIT's Servo Mechanisms Laboratory in the 1950s. Ross was working on early Computer-Aided Design (CAD) and manufacturing systems.
He invented the "plex," a sophisticated data structure that was a precursor to modern structs/records. A plex could contain:
Ross's plex was a "fat struct" that could be processed by system routines. This idea directly influenced Ivan Sutherland, creator of the groundbreaking Sketchpad system (1963), often called the origin of interactive computer graphics and CAD.
Sutherland used a plex-like structure to represent drawings. The revolutionary insight was that constraints (e.g., "these lines are perpendicular") were implemented by system-level solvers that operated across the data components of multiple objects. The architecture was not built around encapsulating objects but around systems that could introspect and manipulate the entire data graph. This is the true forerunner of the ECS architecture.
Despite the existence of this powerful alternative, the compile-time hierarchy model prevailed. The talk suggests several reasons:
The resulting "35-year mistake" was the promotion of an architectural model that simplifies the problem space rather than engaging with the hardest architectural challenges of complex software.
The speaker illustrates the practical impact with a personal story from 1997. While building a metaball-based level editor, they encountered the limitations of the hierarchy model when trying to create a unified interaction system for multi-selected objects. The solution involved creating a parallel hierarchy of callback objects, which was complex and brittle.
Years later, they realized this was an accidental, poorly-implemented version of an ECS. The better solution was the same one Sutherland used in 1963: a system-centric architecture where properties are stored in systems and queried by entity ID.
The talk concludes by arguing that the key to good software architecture is the intentional placement of encapsulation boundaries. The mistake was not OOP itself, but the procrustean application of a single, domain-model-bound hierarchy to all problems.
The powerful alternative, evident in Sketchpad and modern ECS, is to place boundaries around systems. This approach offers greater flexibility, performance, and is better suited for solving complex computational problems. The goal for developers should be to understand these architectural choices deeply rather than following a single, prescribed model.