C
C#2y ago
lukkasz323

✅ Help me understand what a "God" class is and why/how should I avoid it.

I'm specifically referencing to this: https://en.wikipedia.org/wiki/God_object The first example is how my current game project is structured. The second is a different example that is my other theory how a "God" class might look like. Which of these are God classes? Both? Neither? Why is this even considered a problem? How an alternative could look like?
God object
In object-oriented programming, a god object (sometimes also called an omniscient or all-knowing object) is an object that references a large number of distinct types, has too many unrelated or uncategorized methods, or some combination of both. The god object is an example of an anti-pattern and a code smell. A common programming technique is t...
26 Replies
khamas
khamas2y ago
from reading the description you basically need to put the code in the class it belongs not make a code noodle soup
lukkasz323
lukkasz3232y ago
What about the " all-knowing object" description? The "Game" class has access to every part of the program through it's members.
khamas
khamas2y ago
well it's just an object that references others nothing special really if you need to access the objects you can ask the god class I guess
ChucklesTheBeard
1st, it's a very, very good idea to learn about this. 2nd: in game design, performance is god and many good enterprise design practices are sacrificed at the altar of performance, possibly including "never use god objects". A "god class" is a class that knows too much; it knows that Processors need to update Entities, but some Entities have to talk to a Processor and check for collisions with non-entity objects in this Scene but not that Scene, and that UpdateSystem needs to run part 1 before part 2 and EntityManager can only have 4 objects at a time because... WHOA WHOA WHOA, this is supposed to be a high-level class, we are way too deep into the weeds, there are too many levels of abstraction are mixed together... this class is trying to do everything. If you want to add a new Entity you may need to update 40 lines of code scattered throughout the god class to make it work. A SOLID class is only responsible for exactly one thing; if you want to add an Entity, you define the new behaviors in one 40 line chunk, then update maybe one or two lines in directly adjacent classes, to call the new behavior. Of the two example diagrams, the 2nd is much more likely to be a god class than the 1st
lukkasz323
lukkasz3232y ago
Now that I think about it, I made every member in my composition public, only now I see how much nested access it has.
lukkasz323
lukkasz3232y ago
I think only tried to limit child -> parent access, but not the other way around. and didn't even succeed at that lol
ChucklesTheBeard
child -> parent and parent -> child can be ok... the problem becomes more obvious when you have parent->child->grandchild->greatgrandchild->...
lukkasz323
lukkasz3232y ago
I see
ChucklesTheBeard
if greatgrandchild needs a change, you don't want to have to modify all 3 other classes
lukkasz323
lukkasz3232y ago
I feel like I get confused sometimes with names when talking about composition of objects. Are you refering to inheritance here?
ChucklesTheBeard
Layers of abstraction Program (yep, I'm running it on a computer) -> Game (needs to know how to be a game) -> Scene (particular collection of behaviors; here's how the update loop runs in the "pause menu" scene or whatever) -> EntityManager -> Entities (perhaps including the "save & quit" button)... Program should never ever need to know the damnedest thing about a save and quit button, frankly neither should Game or probably even Scene
lukkasz323
lukkasz3232y ago
I understand. What do you think about a situation when the "save & quit" button has access to other intermediate objects like for example Entity creator, or a list of sound files that can be played?
ChucklesTheBeard
Those requirements should be gathered elsewhere and handed to the button, the button itself shouldn't know the details of how they were assembled.
class SaveAndQuitButton : Entity
{
var _listOfSoundFiles;
public SaveAndQuitButton(List<SoundFiles> injected){
_listOfSoundFiles = injected;
}
}
class SaveAndQuitButton : Entity
{
var _listOfSoundFiles;
public SaveAndQuitButton(List<SoundFiles> injected){
_listOfSoundFiles = injected;
}
}
, not
class SaveAndQuitButton : Entity
{
var _listOfSoundFiles;
public SaveAndQuitButton(TightlyCoupledParent p){
_listOfSoundFiles = p.SoundFilesListCreator.Create();
}
}
class SaveAndQuitButton : Entity
{
var _listOfSoundFiles;
public SaveAndQuitButton(TightlyCoupledParent p){
_listOfSoundFiles = p.SoundFilesListCreator.Create();
}
}
lukkasz323
lukkasz3232y ago
I see, thanks, that's very helpful.
ChucklesTheBeard
This is called dependency injection, there are other approaches that operate on the same principle (like, passing in a kinda godlike "dependancy manager" object) but that's the simplest I think
Scratch
Scratch2y ago
In terms of responsibility, each class should have a single responsibility. A god class has many. A common thing I see new game devs make is a "GameManager" class that just does everything
FusedQyou
FusedQyou2y ago
There's nothing wrong with a God class
lukkasz323
lukkasz3232y ago
I feel like "single responsibility" is very poorly defined. One could say that "Managing the game" is the responsibility of the "GameManager" class and there are no other things the class must do, so therefore it follows that principle.
FusedQyou
FusedQyou2y ago
People just decide to throw unnecessary shit in a God class It's perfectly reasonable to create a God class if it's an entrypoint to the main behaviour of something. Like with a game, being able to start/stop it or adjust certain rules without going into the dependencies that hold the main logic for them A God class is also a very good place to apply main communication between dependencies that rely on eachother, without making them communicate directly. This is a very good way to scale I made a console for Unity yesterday doing exactly this and it's very easy to use, adjust and read in general
lukkasz323
lukkasz3232y ago
And that person would be right from a logical standpoint. I'd be surprised If I was the only one that doesn't really understand the scope of this principle.
tippy
tippy2y ago
if you have a class called SomethingManager that's quite a yellow flag to begin with
lukkasz323
lukkasz3232y ago
So you mean that there should be no classes that manage other things?
tippy
tippy2y ago
exactly, it shouldn't "manage", it should do something specific if it's called Manager then you have no idea what it really should do it has... all the responsibilities? which goes against previous said principle
lukkasz323
lukkasz3232y ago
I see, this makes more sense
Scratch
Scratch2y ago
I read Clean Code. Uncle Bob says that functions should be operating at a single "level of abstraction". A "manager" can be fine if the way it's interacting with other objects is at a very high level. But if it starts getting deep into messing with other objects it'll quickly become a mess and way too many responsilbilities.
Accord
Accord2y ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.