ECS for die-hard OO developers

Another attempt to explain Entity Component System

Maxim Zaks
Aug 13, 2018 · 3 min read

When you are a die-hard OO developer, I guess it is safe to assume you are familiar with concept of dependency injection. And I don’t mean a particular dependency injection framework, I mean the concept, which also some times called inversion of control, or the Hollywood Principle.

Dependency injection in OO is used primarily to decouple code and make it more accessible for unit testing and future evolutions. Most of the classes are not self sufficient (for multiple reasons) and therefore rely on other classes to hold data, or expose methods. Those other classes are called dependencies.

If a class creates instances of it’s dependencies by itself, it becomes opaque / non configurable. When we are following the dependency injection principal, we expose the dependencies of the class, making it transparent and configurable from the outside.

In order to reduce coupling to a certain class even further, it is considered best practice to define dependencies as an interface/protocol. This way different implementations can be provided to the class without big hassle. This technique increases, what I previously called accessibility for unit testing and future evolutions.


In canonical ECS we don’t think in terms of classes, we think in terms of entities and systems. An entity is a logical aggregation of components and a system is behaviour which transforms data / state. Systems follow the dependency injection principal, but in case of the system — dependency is data. A system describes which data it needs in order to achieve the data transformation.


For die-hard OO developers I need a die-hard OO example. Lets take the calculating area example. It is used in many tutorials about SOLID design principals.

In a typical OO fashion we would define a interface/protocol which will have a method. This method returns the computed result. Every class, which can be seen as a shape (e.g. Circle, Rectangle and Triangle). Implements and provides it’s own implementation of the method.

As I mentioned before in ECS we don’t think in terms of classes, we think in systems. A system performs a concrete transformation. There is no generic shape system. We need to have a look at the data at hand and figure out what kind of systems we need to introduce in order to calculate the area.

For an area of circle we need a radius. So a need to ask for all entities which have component.

asks for all entities which have and components. And needs all entities which have and components.

I like to say that in ECS we design bottom-up. We look at data and which behaviour depends on which data. In OO we design top-down, we search for abstractions and generic behaviours / definitions.


Now here is another twist you might not think of while being a die-hard OO developer. A system in ECS does not return values. In our OO solution, we defined a generic method which returns the computed value. Normally we don’t just compute values, we compute them so we can process them further. Meaning that the result of method call will be stored somewhere, or passed to another method.

In ECS, systems which compute an area, adds an component to the entity, they used to compute the area. This means that:

  • reads component and writes component
  • reads and and writes
  • reads and and writes

Say we want to compute the sum of all areas. In order to do this, we need to define a system . This systems gets all entities which have component and can sum them up, storing the result in a separate component, or producing a side effect like printing to screen, or sending the result over the network.


As you can see, with ECS we are able to avoid abstractions. is not dependent on an abstract which has a generic method. It is dependent on component (data). It does not care about the origin of the data. The Area value could be created due to a computation based on other components, or set directly based on user input, data received from network etc…

This is a high degree of decoupling business logic, which in terms leads to accessibility for unit testing and future evolutions.


Conclusion

The goals of ECS and dependency injection in OO are similar, with the difference that ECS goes bottom-up and OO goes top-down.

Maxim Zaks

Written by

Tells computers how to waste electricity. Hopefully in efficient, or at least useful way.