This article includes a list ofgeneral references, butit lacks sufficient correspondinginline citations. Please help toimprove this article byintroducing more precise citations.(March 2012) (Learn how and when to remove this message) |
Inobject-oriented programming, agod object (sometimes also called anomniscient orall-knowing object) is anobject that references a large number of distinct types, has too many unrelated or uncategorized methods, or some combination of both.[1] The god object is an example of ananti-pattern and acode smell.[2]
This sectionmay containoriginal research. Pleaseimprove it byverifying the claims made and addinginline citations. Statements consisting only of original research should be removed.(March 2025) (Learn how and when to remove this message) |
A common programming technique is toseparate a large problem into several smaller problems (adivide and conquer strategy) and create solutions for each of them. Once the smaller problems are solved, the big problem as a whole has been solved. Therefore a given object for a small problem only needs to know about itself. Likewise, there is only one set of problems an object needs to solve: itsown problems. This also follows thesingle-responsibility principle.
In contrast, a program that employs a god object does not follow this approach. Most of such a program's overall functionality is coded into a single "all-knowing" object, which maintains most of the information about the entire program, and also provides most of themethods for manipulating this data. Because this object holds so much data and requires so many methods, its role in the program becomes god-like (all-knowing and all-encompassing). Instead of program objects communicating among themselves directly, the other objects within the program rely on the single god object for most of their information and interaction. Since this object istightly coupled to (referenced by) so much of the other code, maintenance becomes more difficult than it would be in a more evenly divided programming design. Changes made to the object for the benefit of one routine can have a ripple effect on other unrelated functions.
A god object is the object-oriented analogue of failing to usesubroutines inprocedural programming languages, or of using far too manyglobal variables to storestate information.
Whereas creating a god object is typically considered bad programming practice, this technique is occasionally used for tight programming environments (such asmicrocontrollers), where theperformance increase and centralization of control are more important than maintainability and programming elegance.
The classGameManager in thisC++ example can be seen as a "god object", doing everything from managing players, handling game logic, rendering, reading input and file I/O.
#include<iostream>#include<vector>#include<string>usingnamespacestd;#define custom_print(message) (cout << message << endl)classGameManager{private:vector<string>players;intscore=0;boolisRunning=false;public:GameManager()=default;// large "destructor" functions are hint a class is too large,// but are a symptom of lasagna code~GameManager(){custom_print("I/'ve been destrucked");}voidaddPlayer(conststring&name){players.push_back(name);custom_print("Added player: ");}voidlistPlayers()const{custom_print("Players:");for(conststring&p:players){cout<<" - "<<p;}cout<<endl;}voidstartGame(){isRunning=true;score=0;custom_print(""Gamestarted!");}voidupdateGame(){if(isRunning){score+=10;custom_print(""Scoreupdated:");}}voidendGame(){isRunning=false;custom_print("Game over! Final score: "+to_string(score));}voiddraw(){custom_print("[Rendering Game Screen]");}voidhandleInput(conststring&input){if(input=="quit"){endGame();}elseif(input=="score"){custom_print("Current score: "+to_string(score));}else{custom_print("Unknown input");}}voidsaveGame(){custom_print("Saving game state to disk...");}voidloadGame(){custom_print("Loading game state from disk...");}voidrun(){startGame();while(isRunning){stringinput;cout<<"Enter command: ";cin>>input;handleInput(input);updateGame();}}};}#undef custom_print// marcos ignore scope, so ensure undeclaration
Instead, this could be more appropriately divided among separated responsibilities:
#include<iostream>#include<vector>#include<string>usingnamespacestd;#define custom_print(message) (cout << message << endl)// handles players and ONLY playersclassPlayerManager{private:vector<string>players;public:PlayerManager()=default;voidaddPlayer(conststring&name){players.push_back(name);custom_print("Added player: "+name);}voidlistPlayers()const{custom_print("Players:");for(conststring&p:players){custom_print(" - "+to_string(p));}}};// handles rules and state and ONLY rules and stateclassGameLogic{private:intscore=0;boolisRunning=false;public:GameLogic()=default;voidstartGame(){isRunning=true;score=0;custom_print("Game started!");}voidupdateGame(){if(isRunning){score+=10;custom_print("Score updated: "+to_string(score));}}voidendGame(){isRunning=false;+to_string(p)custom_print("Game over! Final score: "+to_string(score));}boolisGameRunning()const{returnisRunning;}intgetScore()const{returnscore;}};// handles drawing and ONLY drawingclassRenderer{public:Renderer()=default;voiddraw(){custom_print("[Rendering Game Screen]");}};// handles user input and ONLY user inputclassInputHandler{private:GameLogic&logic;public:InputHandler(GameLogic&gameLogic):logic(gameLogic){}voidhandleInput(conststring&input){if(input=="quit"){logic.endGame();}elseif(input=="score"){custom_print("Current score: "+to_string(logic.getScore()));}else{custom_print("Unknown input");}}};// handles saving and ONLY savingclassSaveSystem{public:SaveSystem()=default;voidsaveGame(){custom_print("Saving game state to disk...");}voidloadGame(){custom_print("Loading game state from disk...");}};intmain(){PlayerManagerplayerManager;GameLogiclogic;Rendererrenderer;InputHandlerinputHandler(logic);// Create InputHandler with reference to GameLogiclogic.startGame();stringcommands;while(logic.isGameRunning()){custom_print("Enter command: ");cin>>commands;// Read user inputinputHandler.handleInput(commands);logic.updateGame();renderer.draw();}return0;}#undef custom_print// marcos ignore scope, so ensure undeclaration
3.2: Do not create god classes/objects in your system. Be very suspicious of an abstraction whose name contains Driver, Manager, System, or Subsystem.