I think oop is easier to understand in small examples but gets really inscrutable as your code base grows so you only start questioning oop if you have worked on large code bases.
Also the lack of dod/ecs languages is a problem. I realized the other day that row polymorphism is the type theoretical concept that would make this work.
Partially, but DOD like in the article examples work great when you have a "rigid" architecture like a game where having a struct to contain vecs/arrays of player attributes makes sense. This can break down when your "objects" require more flexibility and are used in multiple different contexts where an aggregate `PlayerState` struct doesn't play nicely.
Not to say that DOD is bad, just that it shouldn't always be the go-to choice. Rust _does_ make this sort of design much nicer to work with because you can in many ways have your cake and eat it too using `from` and `into` and go back and forth from DOD to OOP type structures.
ECS style DOD arguably makes putting things together easier though, because instead of having to update your actual object when you want to make a change, you only have to add the right component that contains the functionality you need to the given entity ID.
And don't get me started once you have some hierarchies. Sometimes a object changes and you need to notify a parent of this change. OOP really sucks at this.
It seems like in these cases often at least in frame-based systems like games it makes sense to sort your data in a parent->child partial order, then visit in that (or reverse depending on which algo) order propagating changes, then do another pass later and so on. It's just nice that you can think about these things once you're in DoD-land.
Also the lack of dod/ecs languages is a problem. I realized the other day that row polymorphism is the type theoretical concept that would make this work.
https://en.wikipedia.org/wiki/Row_polymorphism