The back-end for the game I'm working on is using an Entity Component System architecture.
ECS is essentially a data oriented architecture where Entities are treated like data, and Systems process them based on their Components.
ECS consist of
The nomenclature can be a bit confusing at first because 'entities', systems' and 'components' generally meaning something else in other software architectures.
Here's a mental translation that I like to use.
Example for a game
A 'Movement' system would operate on the coordinates component of every object that has coordinates, and ensure it is moved to the correct location based on velocity component. A 'Death' system would process every object that has Health to ensure that if its health is below 0, it 'dies' and should be removed from the game world.
ECS provides for incredible flexibility - any object can have any behaviour.
For example - a 'coordinate' component can be added to any object and the 'movement' system will pick it up and move that object in the same way it moves any other object that has coordinates and velocity.
If there were a new object named 'Ball' and we wanted it to be able to have motion, just add Coordinates and Velocty to it, and the Movement system will pick it up and do its job without affecting any other logic for the Ball or needing changes to the Movement system.
ECS allows for isolation of logic and reduces dependency across the architecture.
Systems should only know or care about the components that they operate on. It shouldnt care what entity it is. This follows the single responsibility principle - each system only does one thing uniformly to all entities.
This also promotes scalability as multiple systems can be split out to operate independently of each other or in parallel. This promotes parallel processing or scaling horizontally.
Of course there's trade-offs in any architecture.
Mental model When you have a variety of entities, components, and systems in a game - it takes a lot of effort to keep track of it all. Components can be assigned all over the place and its easy to lose track of what entity has what components. Also what systems act on what components.
Sequencing considerations Depending on the architecture / framework, there may be a concern of what order different systems operate in. E.g. should combat occur before movement? If so what happens if a unit moves out of range of the another one.
Parallel processing If Systems are running in parallel you have to ensure they appropriately lock the resources they're modifying and the timing makes sense for the game.
Shared data complexity The separation of concerns that this imposes also increases the complexity of sharing information across Systems.
Shared resources tend to throw things off. For example the concept of a world map. A pathfinding system needs this. A combat targetting system needs this. This can be implemented in each system taking up memory and processing cycles, or it can be a shared resource that crosses multiple systems. Shared resources then affect the scalability or parallel processing capability.
The more shared resources you start throwing into it the more coupled systems start getting.
Another big thing for me was getting my brain around this new paradigm. I'm still figuring out best practices through trial and error as I go - but I do love the separation of concerns aspect of it.
I've outlined the logical breakdown of my game into ECS with this post
Here is a simple Node.js framework for ECS that I really liked. Its simple enough that it keeps things easy to follow and understand. I've based my own code off this approach.