Whenever I think of Entity Component Systems I think it as the furtherance of basing your game systems around singletons.
I prefer testing and so typically avoid singletons, but I do acknowledge the pros of thinking of games as a series of “managers” telling things how to behave. Enough to appreciate that thinking of a game as centralized set of manager systems is kinda the basis of ECS.
Throwing this out there in case anyone in this community has interesting thoughts on the subject!
I agree that having a pure function is better than one with internal state or which uses global variable. But if your problem requires global state, then there’s nothing you can do.
Games generally are inherently a complex system all interacting with a global state.
So whether you’re making a singleton class, a regular global variable, or averting your gaze while passing a massive state variable to every single function, you can’t escape it.
Ignoring the side effects of io, a main loop can be replaced by a recursive call that passes the new world state resulting from the time step back to the beginning. That world state can be expressed as an ecs, and the operations performed on a world state to produce a new one can be the systems, and still be pure functions. There is nothing in an ecs that requires imperative programming. Some of the benefits of an ECS are related to allowing granular copies to be as shallow as possible for such a world state, to allow for immutability. I'm not sure where a singleton would get used even if you were wanting to go imperative with an ecs.
You don’t even have to ignore io: input is a coeffect which is passed to your otherwise pure function as an argument and output is directly derived from your returned works state. That is, yes there’s some side effects happening before and after each iteration but it can be relatively cleanly separated. In my toy engine, I do this: input is fed in and rendering is driven by the output. My game logic isn’t a pure function (it’s a task graph that reads and writes from event queues and internally maintained task state, but input is fed into the start of the task graph and rendering is driven by tasks at the end), but it conceptually could be as all the statefulness is encapsulated and internal.
I prefer testing and so typically avoid singletons, but I do acknowledge the pros of thinking of games as a series of “managers” telling things how to behave. Enough to appreciate that thinking of a game as centralized set of manager systems is kinda the basis of ECS.
Throwing this out there in case anyone in this community has interesting thoughts on the subject!