Skip to content

Data-Oriented Design & ECS

This course teaches how to choose data ownership and processing boundaries in C++, with Entity Component System (ECS) development as a later application. Start with a small simulation, compare designs under changing requirements, and test the results before discussing speed.

Start the Data-Oriented Design and ECS Course

The first seven chapters are available:

  1. Design boundaries: what Big OOPs asks us to reconsider.
  2. Build a plain C++ simulation with structs and loops.
  3. Compare inheritance and composition when requirements change.
  4. Track Entity identity with owner-scoped IDs.
  5. Build a minimal ECS with component stores and matching systems.
  6. Validate generational handles and safely reuse entity slots.
  7. Define execution order and defer structural changes.

These chapters include working source and tests. Chapter 5 introduces a minimal ECS with fixed component types and explicit systems, not a production engine. Chapter 6 adds slot reuse with generation checks and an explicit retirement policy. Chapter 7 defines a fixed frame order and a recoverable deferred command queue. The earlier chapters explain why we might introduce those boundaries.

What You Will Learn to Decide

  • Should a capability be a field, an owned value, a virtual operation, or data in a separate store?
  • Which subsystem owns a piece of state, and which operations may change it?
  • How do lifetime and processing order affect correctness?
  • When is a simple loop enough, and when is another representation worth its cost?

Data-oriented design is not a ban on classes, and ECS is not a synonym for data-oriented design. Storage and access patterns still need evaluation. Likewise, using std::optional inside each object is composition, not by itself an ECS.

Prerequisites and Environment

You should know C++ structs, functions, references, std::vector, std::unique_ptr, and basic RAII. The supplied project uses C++17, CMake, and the standard library only. No display, game engine, GPU, GPIO, or ECS library is required.

Raspberry Pi OS Desktop and Lite can both build the examples with a suitable C++17 compiler. The code does not depend on a particular Pi model or ARM instruction set. Local compiler tests are not a claim of Raspberry Pi hardware testing; hardware measurements belong to a later chapter.

For language preparation, use the Modern C++ course. For individual design techniques, use Design Patterns.

One Shared Simulation, Not Unrelated Examples

Our world contains bodies with a position and optional behaviour:

  • Movement changes position using velocity.
  • Visibility controls whether a body appears in a rendering snapshot.
  • Lifetime removes an expiring body after a step.

The same initial state and rules feed the baseline and its alternatives. Tests compare their observable results, so changing architecture cannot quietly change the problem being solved. Rendering initially produces data, not a window.

Read the simulation contract and build instructions before modifying the examples.

Roadmap After Deferred Commands

The following lessons are planned, not yet published:

Stage Design question
8. Storage When do simple stores, sparse sets, or archetypes fit the workload?
9. Raspberry Pi measurements How do we measure equivalent work without hiding costs?
10. Choosing an approach When should we use a library, our own code, or no ECS at all?

How to Read the Course

Each lesson follows requirements, a straightforward implementation, change pressure, alternatives, tests, and trade-offs. Keep a simple implementation if it still meets your requirements.

The Big OOPs transcript is a discussion starting point. It is not our implementation specification or a benchmark. The course's concrete decisions are explained and tested separately.

Begin with Chapter 1: Design Boundaries.

Donate