Come gestire le classi sovrapposte

2

Sto mettendo insieme un programma per provare a ricreare un gioco da tavolo. Il mio obiettivo era quello di mantenere le regole e le azioni effettivamente del gioco separate dalla sua presentazione, quindi sto creando una libreria che contiene gli oggetti e i metodi che definiscono ciò che puoi fare mentre giochi. Oltre alle classi che definiscono gli oggetti del gioco, stavo progettando di creare due classi per "frontare" il gioco. La prima classe GameRunner era la classe che il livello di presentazione avrebbe usato per chiamare azioni sul gioco come AddPlayer , TakeGems , BuildCard ecc. Quindi volevo una seconda classe per gestire lo stato del gioco, opportunamente chiamato GameState , che manterrà traccia dei giocatori e del loro campo, così come del mercato per il gioco. In GameState ho creato i metodi che influenzano lo stato del gioco per definire in che modo vengono aggiunti i giocatori e acquistate le carte.

Quello che ho notato è che tutta la logica di gioco è stata definita in GameState e GameRunner ora si sta essenzialmente trasformando in una classe passante, in altre parole, tutto ciò che fa è chiamare il metodo appropriato in GameState e restituisce l'oggetto stato:

public GameState AddPlayer(string name)
{
    gameState.AddPlayer(name);
    return gameState;
}

Questo mi sembra ripetitivo. Ha senso come design? Una separazione di preoccupazioni tra le azioni e cosa fanno? O dovrei semplicemente rendere GameState una classe che ha gli oggetti che rendono lo stato del gioco, e solo avere GameRunner invece di manipolare quei campi di stato dai suoi metodi. Esempio:

public GameState AddPlayer(string name)
{
    if(Players.Count < 4)
    {
        gameState.Players.Add(new Player(name))
        gameState.Success = true;
    }
    else
    {
        gameState.Success = false;
    }

    return gameState;
}
    
posta Evan Frisch 30.05.2015 - 02:28
fonte

1 risposta

2

Restituendo GameState dalle tue funzioni di GameRunner, stai rendendo il client di GameRunner dipendente anche da GameState. IE il client GameRunner conosce i dettagli dell'implementazione di GameRunner.

Penso che la delega di compiti al GameState (come nel primo esempio) sia la migliore delle due opzioni, quindi quando la logica di (in questo caso) l'aggiunta di un giocatore a un gioco cambia, è solo necessario essere aggiornato in un unico posto: lo stesso GameState.

Il GameRunner agisce come un livello anticorruzione che traduce tra le preoccupazioni del livello di presentazione e quello del motore del gioco. Come tale dovrebbe contenere la logica di presentazione e delegare le modifiche al gioco a GameState. Se anche il GameRunner fosse interessato alla logica del gioco, violerebbe il Principio di Responsabilità Unica. (Ci dovrebbe essere una sola ragione per cambiare modulo, classe o funzione). Dovrebbe ora cambiare se la logica di presentazione necessitava di un aggiornamento o se la logica di gioco doveva cambiare.

    
risposta data 30.05.2015 - 03:03
fonte

Leggi altre domande sui tag