The game I am working on is starting to have an increasing number of god classes, most about 1000-2000 lines but some going higher.
They are mainly actors and components.
How do you break them up while keeping them exposed to be customizable with blueprints but also allowing them to be properly tested?
Lets say I have a component that exposes some data to blueprint and I decide to break it into 3 classes.
Some of these classes have references to each other and now parts of the data exposed to blueprint are needed in different classes.
One solution would be to have a class being made into a component, expose all the data needed for all of them and create the other classes.
This makes it difficult to test the logic of only the component because it instanciates the objects.
Another solution would be to make all three classes into components, each exposing the data each needs and having references to each other.
The actor would be responsible to wire them.
This allow the logic to be independently tested but has the overhead of more components in the actor.
Optionally you could have each component also implement an interface and have the other classes depend on the interface to reduce coupling, again with the actor wiring them.
This would make the actor now hard to test independently.
And there is no easy way to remove the wiring from the actors because it is Unreal who creates them originally when the level starts and Unreal does not do the wiring for you.
If it is not the actor, you would need a callback after level creation to initialize the actors, but then you might as well create a dependency injection framework for Unreal and it is not priority right now.
The only way I see to reduce actor responsibility is to create more component classes to execute the logic and have the actors being merely delegators to these components.
To allow more flexibility perhaps you could instead of creating the components in the actor, have the components be BlueprintSpawnableComponent and create them in blueprint.
Inside BeginPlay you could use one of the GetComponentsBy methods to retrieve the components needed to do the wiring.
This would increase the overhead of creating the actor.
How do you keep class responsibility low in your projects while still interfacing with blueprints?
Refactoring these classes might not be done now but would be nice to have these options in mind when introducing new code.