20

Is the Entity Component System architecture object oriented, by definition? It seems more procedural or functional to me. My opinion is that it doesn't prevent you from implementing it in an OO language, but it would not be idiomatic to do so in a staunchly OO way.

It seems like ECS separates data (E & C) from behavior (S). As evidence:

The idea is to have no game methods embedded in the entity.

And:

The component consists of a minimal set of data needed for a specific purpose

Systems are single purpose functions that take a set of entities which have a specific component


I think this is not object oriented because a big part of being object oriented is combining your data and behavior together. As evidence:

In contrast, the object-oriented approach encourages the programmer to place data where it is not directly accessible by the rest of the program. Instead, the data is accessed by calling specially written functions, commonly called methods, which are bundled in with the data.

ECS, on the other hand, seems to be all about separating your data from your behavior.

21

Introduction


Entity–component systems are an object-oriented architectural technique.

There is no universal consensus of what the term means, same as object-oriented programming. However, it is clear that entity–component systems are specifically intended as an architectural alternative to inheritance. Inheritance hierarchies are natural for expressing what an object is, but in certain kinds of software (such as games), you would rather express what an object does.

It is a different object model than the “classes and inheritance” one to which you’re most likely accustomed from working in C++ or Java. Entities are as expressive as classes, just like prototypes as in JavaScript or Self—all of these systems can be implemented in terms of one another.

 

Examples


Let’s say that Player is an entity with Position, Velocity, and KeyboardControlled components, which do the obvious things.

entity Player:
  Position
  Velocity
  KeyboardControlled

We know Position must be affected by Velocity, and Velocity by KeyboardControlled. The question is how we would like to model those effects.

 

Entities, Components, and Systems


Suppose that components have no references to one another; an external Physics system traverses all Velocity components and updates the Position of the corresponding entity; an Input system traverses all KeyboardControlled components and updates the Velocity.

          Player
         +--------------------+
         | Position           | \
         |                    |  Physics
       / | Velocity           | /
  Input  |                    |
       \ | KeyboardControlled |
         +--------------------+

This satisfies the criteria:

  • No game/business logic is expressed by the entity.

  • Components store data describing behaviour.

The systems are now responsible for handling events and enacting the behaviour described by the components. They are also responsible for handling interactions between entities, such as collisions.

 

Entities and Components


However, suppose that components do have references to one another. Now the entity is simply a constructor which creates some components, binds them together, and manages their lifetimes:

class Player:
  construct():
    this.p = Position()
    this.v = Velocity(this.p)
    this.c = KeyboardControlled(this.v)

The entity might now dispatch input and update events directly to its components. Velocity would respond to updates, and KeyboardControlled would respond to input. This still satisfies our criteria:

  • The entity is a “dumb” container which only forwards events to components.

  • Each component enacts its own behaviour.

Here component interactions are explicit, not imposed from outside by a system. The data describing a behaviour (what is the amount of velocity?) and the code that enacts it (what is velocity?) are coupled, but in a natural fashion. The data can be viewed as parameters to the behaviour. And some components don’t act at all—a Position is the behaviour of being in a place.

Interactions can be handled at the level of the entity (“when a Player collides with an Enemy…”) or at the level of individual components (“when an entity with Life collides with an entity with Strength…”).

 

Components


What is the reason for the entity to exist? If it is merely a constructor, then we can replace it with a function returning a set of components. If we later want to query entities by their type, we can just as well have a Tag component which lets us do just that:

function Player():
  t = Tag("Player")
  p = Position()
  v = Velocity(p)
  c = KeyboardControlled(v)
  return {t, p, v, c}
  • Entities are as dumb as can be—they’re just sets of components.

  • Components respond directly to events as before.

Interactions must now be handled by abstract queries, completely decoupling events from entity types. There are no more entity types to query—arbitrary Tag data is probably better used for debugging than game logic.

 

Conclusion


Entities are not functions, rules, actors, or dataflow combinators. They are nouns which model concrete phenomena—in other words, they are objects. It is as Wikipedia says—entity–component systems are a software architecture pattern for modeling general objects.

  • 2
    The main alternative to class-based OO, prototype-based OO, also seems to couple data and behaviour. Actually, it seems to differ from ECS just as much as class-based OO does. So could you elaborate what you mean by OO? – user7043 Sep 17 '13 at 14:23
  • To add on to @delnan's question, are you disagreeing with the snippet of the OO wikipedia article I quoted? – Daniel Kaplan Sep 17 '13 at 16:32
  • @tieTYT: The Wikipedia quote is talking about encapsulation and information hiding. I don’t think it is evidence that data–behaviour coupling is required, only that it is common. – Jon Purdy Sep 17 '13 at 17:31
  • @delnan: I don’t mean anything by OO. Object-oriented programming, to me, is exactly what it says on the tin: programming with “objects” (as opposed to functions, rules, actors, dataflow combinators, etc.) where the particular definition of object is implementation-defined. – Jon Purdy Sep 17 '13 at 17:34
  • 1
    @tieTYT: I was just describing implementations I’ve seen in the wild, in order to convey that it’s a broad term—not contradictory to, but certainly broader than, the Wikipedia description. – Jon Purdy Sep 17 '13 at 19:38
19

NO. And I'm surprised how many people voted otherwise!

Paradigm

It's Data-Oriented a.k.a. Data-Driven because we are talking about the architecture and not the language it's written in. Architectures are realizations of programming styles or paradigms, which can usually be unadvisably worked around in a given language.


Functional?

Your comparison to Functional/Procedural programming is a relevant and meaningful comparison. Note, however, that a "Functional" language is different from the "Procedural" paradigm. And you can implement an ECS in a Functional language like Haskell, which people have done.


Where cohesion happens

Your observation is relevant and spot-on:

"...[ECS] doesn't prevent you from implementing it in an OO language, but it would not be idiomatic to do so in a staunchly OO way"


ECS/ES is not EC/CE

There is a difference between the component-based architectures, "Entity-Component" and "Entity-Component-System". Since this is an evolving design pattern, I have seen these definitions used interchangeably. "EC" or or "CE" or "Entity-Component" architectures put behavior in components, whereas "ES" or "ECS" architectures put behavior in systems. Here are some ECS articles, both of which use misleading nomenclature, but get the general idea across:

If you're trying to understand these terms in 2015, make sure someone's reference to "Entity Component System" doesn't mean "Entity-Component architecture".

  • 1
    This is the correct answer. ECS doesn't fit very well with OOP paradigms, because ECS is all about separating data and behavior, while OOP is about the opposite. – Nax May 31 '16 at 13:04
  • "while OOP is about the opposite" There is no accepted definition of what OOP is about, unless useless academic definitions such as SmallTalk's which never gets used in practice. – Jean-Michaël Celerier Aug 25 '16 at 13:11
10

Entity component systems (ECSs) can be programmed in an OOP or functional manner depending on how the system is defined.

OOP way:

I have worked on games where an entity was an object composed of various components. The entity has an update function which modifies the object in place by calling update on all its components in turn. This is clearly OOP in style - behaviour is linked to data, and the data is mutable. Entities are objects with constructors/destructors/updates.

More functional way:

An alternative is for the entity to be data without any methods. This entity may exist in its own right or simply be an id which is linked to various components. This way it is possible (but not commonly done) to be fully functional and have immutable entities and pure systems which generate new component states.

It seems (from personal experience) that the latter way is gaining more traction and for good reason. Separating entity data from behaviour results in more flexible and reusable code (imo). In particular, using systems to update components/entities in batches can be more performant, and completely avoids the complexities of inter-entity messaging which plague many OOP ECSs.

TLDR: You can do it either way, but I would argue that the benefits of good entity component systems derive from their more functional nature.

  • More traction especially since the whole point of components was to get away from intractable OOP hierarchies, good description of the benefit. – Patrick Hughes Jun 11 '14 at 5:50
3

I think of ECS as fundamentally distinct from OOP and tend to see it the same way you do, as closer to functional or especially procedural in nature with a very distinct separation of data from functionality. There's also some semblance to programming of a kind dealing with central databases. Of course I'm the worst person when it comes to formal definitions. I'm only concerned with how things tend to be, not what they're conceptually defined to be.

I'm assuming a kind of ECS where components aggregate data fields and make them publicly/globally accessible, entities aggregate components, and systems provide functionality/behavior on that data. That leads to radically difficult architectural characteristics from what we'd typically call an object-oriented codebase.

And of course there's some blurring of the boundaries in the way people design/implement an ECS, and there's debate about what exactly constitutes an ECS in the first place. Yet such boundaries are also blurred in code written in what we call functional or procedural languages. Among all this fuzziness, the fundamental constant of an ECS with a separation of data from functionality seems far closer to functional or procedural programming to me than OOP.

One of the main reasons I don't think it's helpful to consider ECS to belong in a class of OOP is that most of the SE practices associated with OOP revolve around public interface stability, with public interfaces modeling functions, not data. The fundamental idea is that the bulk of the public dependencies flow towards abstract functions, not to concrete data. And because of that, OOP tends to make it very costly to change fundamental design behaviors, while making it very cheap to change concrete details (like data and code required to implement the functionality).

ECS is radically different in this regard considering how things are coupled as the bulk of the public dependencies flow towards concrete data: from systems to components. As a result, any SE practices associated with ECS would revolve around data stability, because the most public and widely used interfaces (components) are actually just data.

As a result an ECS makes it very easy to do things like substitute an OpenGL rendering engine for a DirectX one, even if the two are implemented with radically different functionality and don't share the same designs whatsoever, provided both the DX and GL engine have access to the same stable data. Meanwhile it would be very expensive and require rewriting a bunch of systems to change, say, the data representation of a MotionComponent.

That's very opposite from what we traditionally associate with OOP, at least in terms of coupling characteristics and what constitutes "public interface" vs. "private implementation details". Of course in both cases "implementation details" are easy to change, but in ECS it's the design of data that's costly to change (data isn't an implementation detail in ECS), and in OOP it's the design of functionality that's costly to change (the design of functions isn't an implementation detail in OOP). So that's a very different idea of "implementation details", and one of the main appeals to me of an ECS from a maintenance perspective was that in my domain, the data required to do things was easier to stabilize and design correctly once and for all upfront than all the various things we could do with that data (which would change all the time as clients changed their minds and new user suggestions came flooding in). As a result, I found maintenance costs plummeting when we started directing dependencies away from abstract functions towards raw, central data (but still with care about which systems access which components to allow maintaining invariants to a sane degree in spite of all the data conceptually being globally accessible).

And in my case at least, the ECS SDK with the API and all the components are actually implemented in C and bears no resemblance of OOP. I've found C more than adequate for such a purpose given the inherent lack of OO in ECS architectures and the desire to have a plugin architecture which can be used by the widest range of languages and compilers. The systems are still implemented in C++ since C++ makes things very convenient there and the systems model the bulk of the complexity and there I find use for a lot of things that might be considered closer to OOP, but that's for implementation details. The architectural design itself still resembles very procedural C.

So I think it is somewhat confusing, at the very least, to try to say an ECS is OO by definition. At the very least the fundamentals do things that are a complete 180 degree turn from many of the fundamental principles generally associated with OOP, starting with encapsulation and maybe ending with what would be considered desired coupling characteristics.

2

Data-Oriented Entity Component Systems can coexist with Object-Oriented Paradigms: - Component Systems lend themselves to polymorphism. - Components can be both POD (plain old data) and ALSO Objects (with a Class and Methods), and the whole thing is still 'data oriented', provided that Component Class Methods only manipulate data owned by the local object.

If you choose this path, I recommend that you avoid using Virtual Methods, because if you have them, your component is no longer purely component data, plus those methods cost more to call - this is not COM. Keep your component classes clean of any references to external anything, as a rule.

Example would be vec2 or vec3, a data container with some methods to touch that data, and nothing more.

  • 2
    this post is rather hard to read (wall of text). Would you mind editing it into a better shape? Also, it would help if you explain to readers why they may find linked blog article useful and relevant to the question asked... – gnat Jul 5 '15 at 11:59
  • ...in case if you're somehow related to that blog (are you?), it would be also desirable to disclose affiliation – gnat Jul 5 '15 at 12:01
  • Yes, that is my blog, I am closely affiliated with my public blog, which discloses details of an object-oriented entity component system based on data oriented design principles, which I believe is relevant and possibly useful, I have nonetheless removed the link to remove any bias. – Homer Jul 22 '16 at 10:18

protected by gnat Jul 22 '16 at 10:19

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.