Logotipo de ConstructiCat
CodeBust.
Explorar la sección ▾

Objeto todopoderoso.

Un objeto todopoderoso es un antipatrón: una sola clase que sabe o hace demasiado y concentra la mayor parte de los datos y el comportamiento.

En programación orientada a objetos, un objeto todopoderoso (en inglés God Object) es un objeto que conoce demasiado o hace demasiado. El objeto todopoderoso es un ejemplo de antipatrón.

Historia

La idea básica detrás de la Programación Estructurada es: un gran problema se divide en muchos pequeños problemas (estrategia Divide y Vencerás) y las soluciones son creadas para cada uno de ellos. Una vez que los pequeños problemas han sido resueltos, el gran problema ha sido resuelto como un todo. Así, un objeto que resuelve un problema pequeño solo necesita conocerse a sí mismo, y el único grupo de problemas que debe resolver son sus propios problemas.

El Código del Objeto todopoderoso no sigue esta regla. En su lugar, la funcionalidad entera del programa está codificada en un solo objeto que hace todo, el cual mantiene toda la información del programa entero y contiene todos los métodos y subrutinas para manipular los datos. Como el objeto contiene muchos datos y requiere muchos métodos, su rol en el programa se convierte en Objeto Todopoderoso (Abarca todo). En lugar de objetos comunicándose entre ellos directamente, los objetos en el programa se cuelgan del Objeto Todopoderoso para manejar su información e interacción. Como el Objeto Todopoderoso es referenciado por casi todo el código, el mantenimiento se vuelve mucho más difícil, que el diseño del código de un programa mejor dividido

El objeto todopoderoso es el análogo, en orientación a objetos, de no usar subrutinas en lenguajes procedurales o de usar demasiadas variables globales para almacenar información de estado.

Crear un Objeto todopoderoso es típicamente considerado una mala práctica de programación, esta técnica es usada ocasionalmente para entornos de programación ajustados, donde el aumento de rendimiento ligero y la centralización es más importante que el mantenimiento y la elegancia de programación.

Bibliografía

Enlaces externos

Ejemplo

La clase GameManager de este ejemplo en C++ es un objeto todopoderoso típico: gestiona los jugadores, lleva la lógica del juego, dibuja la pantalla, procesa la entrada y guarda la partida en disco.

import std;

using std::string;
using std::vector;

class GameManager {
private:
    vector<string> players;
    int score = 0;
    bool running = false;
public:
    GameManager() = default;
    ~GameManager() = default;

    void addPlayer(const string& name) {
        players.push_back(name);
        std::println("Added player: {}", name);
    }

    void listPlayers() const {
        std::println("Players:");
        for (const string& p : players) {
            std::println(" - {}", p);
        }
    }

    void startGame() {
        running = true;
        score = 0;
        std::println("Game started!");
    }

    void updateGame() {
        if (running) {
            score += 10;
            std::println("Score updated: {}", score);
        }
    }

    void endGame() {
        running = false;
        std::println("Game over! Final score: {}", score);
    }

    void draw() {
        std::println("[Rendering Game Screen]");
    }

    void handleInput(const string& input) {
        if (input == "quit") {
            endGame();
        } else if (input == "score") {
            std::println("Current score: {}", score);
        } else {
            std::println("Unknown input");
        }
    }

    void saveGame() {
        std::println("Saving game state to disk...");
    }

    void loadGame() {
        std::println("Loading game state from disk...");
    }

    void run() {
        // ...
    }
};

Es más adecuado repartir esas responsabilidades entre clases separadas:

import std;

using std::string;
using std::vector;

class PlayerManager {
private:
    vector<string> players;
public:
    PlayerManager() = default;
    ~PlayerManager() = default;

    void addPlayer(const string& name) {
        players.push_back(name);
        std::println("Added player: {}", name);
    }

    void listPlayers() const {
        std::println("Players:");
        for (const string& p : players) {
            std::println(" - {}", p);
        }
    }
};

class GameLogic {
private:
    int score = 0;
    bool running = false;
public:
    GameLogic() = default;
    ~GameLogic() = default;

    void startGame() {
        running = true;
        score = 0;
        std::println("Game started!");
    }

    void updateGame() {
        if (running) {
            score += 10;
            std::println("Score updated: {}", score);
        }
    }

    int getScore() const noexcept {
        return score;
    }

    void endGame() {
        running = false;
        std::println("Game over! Final score: {}", score);
    }
};

class Renderer {
public:
    Renderer() = default;
    ~Renderer() = default;

    void draw() {
        std::println("[Rendering Game Screen]");
    }
};

class InputHandler {
private:
    GameLogic& logic;
public:
    explicit InputHandler(GameLogic& logic):
        logic{logic} {}

    ~InputHandler() = default;

    void handleInput(const string& input) {
        if (input == "quit") {
            logic.endGame();
        } else if (input == "score") {
            std::println("Current score: {}", logic.getScore());
        } else {
            std::println("Unknown input");
        }
    }
};

class SaveSystem { 
public:
    SaveSystem() = default;
    ~SaveSystem() = default;

    void saveGame() {
        std::println("Saving game state to disk...");
    }

    void loadGame() {
        std::println("Loading game state from disk...");
    }
};

class GameManager {
private:
    PlayerManager players;
    GameLogic logic;
    Renderer renderer;
    InputHandler input{logic};
    SaveSystem saves;
public:
    GameManager() = default;
    ~GameManager() = default;

    void run() {
        // ...
    }
};

Ahora cada clase tiene un único motivo para cambiar y GameManager solo las conecta entre sí. Es el remedio habitual para una clase grande, aplicado con la refactorización Extraer clase.

Adaptado del artículo de Wikipedia “Objeto todopoderoso” (revisión 166493090), disponible bajo la licencia CC BY-SA 4.0; el texto ha sido editado y se han añadido ejemplos.