Smaller units are often helpful, as long as they are not coupled. But when you have tons of coupling, a big unit that knows about all the coupling will sometimes serve better. Trying to fracture a large, closely-coupled system will often end up with runtime performance that’s 10x slower because of the necessary indirection. When your application is intended to calculate quarterly reports for the back office of some enterprise, that’s a TOTALLY FINE choice – it’s more important it’s right, and the next developer who comes along can easily read and understand it, than whatever the code runtime is. For games, this is not so – gameplay code needs to deal with tons of special cases because of the inherent problem domain, and performance is absolutely crucial.
That doesn’t mean that every solution requires big, dense classes and files. Sometimes, breaking parts apart actually shows opportunities for optimization, and even parallelization. There are many cases where schedule, inertia, or inexperience means that people write bigger and denser code than they have to, and when you find those, taking a bit of time to make it better delivers value to all parts of the team. It’s just not the case that EVERY large, dense, piece of code can have this hammer applied to it. Sometimes, the problem is just complex, inherently.
The best solutions is in my opinion when you end up building a better vocabulary, typically at a higher level. For example, we don’t need to write a “rolling barrel simulation” and a “fixed rock simulation” and a “falling debris simulation” and then try to make them all talk together – we raise the level of abstraction to rigid bodies with algorithmically defined collision manifolds, and use a general solver for running “the simulation” where everything interacts. The draw-back is that you now have to think in terms of forces, torques, and contacts, rather than whatever features were important to your particular rolling barrel in the “rolling barrel simulation.” Higher layer of abstraction, more powerful primitives, ability to talk about higher-level concepts, ability to parallelize and optimize in the higer-layer domain – all good things and the reason we use a physics engine in most 3D games today.
In fact, that’s what the Unreal Engine is – it defines a Gameplay Framework that lets you talk about Actors, and Pawns, and Components, and Assets, rather than having to talk about structs and pointers and blocks of texture data.
I think there may be a higher-layer set of primitives that can help with gameplay/entity code, but it’s not at all clear what that looks like, and nobody has managed to invent and popularize it yet. If you can define and build it, you may be setting the stage for the next big engine for the 2030s