È una cattiva idea avere Game1 statico in XNA?


10

È davvero una cattiva idea avere la mia Game1classe come statica? Come al momento nella mia Game1classe, ho una classe chiamata TileHandlerche gestisce tutto a che fare con il mio attuale set di tessere e AnimalHandlerche gestisce tutti i miei animali (sorprendentemente).

Ora, se sono dentro AnimalHandlere voglio verificare se una piastrella è pedonabile da TileHandlerallora, ciò causa problemi o devo passare un elenco di tessere pedonabili AnimalHandler, cosa che preferirei non fare.

Sarebbe più semplice rendere Game1statico e poi AnimalHandlersemplicemente andare Game1._tileHandler.WalkableTile(position).

Ora non riesco a vedere nulla di sbagliato in questo o qualcosa che possa causare problemi, ma ho appena iniziato a utilizzare le classi statiche, quindi chiunque sia più esperto vede qualche motivo gigante per cui questa è una cattiva idea?

Risposte:


9

Ora non riesco a vedere nulla di sbagliato in questo o qualcosa che possa causare problemi, ma ho appena iniziato a utilizzare le classi statiche, quindi chiunque sia più esperto vede qualche motivo gigante per cui questa è una cattiva idea?

Quando hai un nuovo martello lucido, ogni problema sembra un chiodo.

In generale non c'è nulla di sbagliato nelle classi e / o metodi statici, se usato correttamente (per cose che non hanno o dipendono dallo stato per istanza). Tuttavia, nel tuo caso li stai abusando di nascondere una dipendenza per istanza, confondendo questo con la rimozione della dipendenza. Sembra anche che tu stia esponendo i dettagli dell'implementazione della Game1classe, che è anche generalmente negativa.

Ecco il punto cruciale del tuo problema:

... se sono dentro AnimalHandlere voglio verificare se una piastrella è pedonabile da TileHandlerallora, ciò causa problemi o devo passare un elenco di tessere pedonabili AnimalHandler, cosa che preferirei non fare.

Ignorare la possibilità che la AnimalHandlernecessità di queste tessere possa essere essa stessa un cattivo design (con i nomi che hai scelto è difficile dire i dettagli di queste classi) per il momento ... se ha AnimalHandlerbisogno di un elenco di tessere pedonabili, allora ha bisogno di un elenco di piastrelle calpestabili. In genere è meglio rendere le dipendenze più esplicite che meno , in quanto rende il codice più autocompattante. Passando la lista direttamente a AnimalHandler, si esplicita il fatto che ha bisogno di una tale lista. Se invece rendi tutto statico e pubblico in modo da poter accedere all'elenco statico contenuto altrove nel codice, tutto ciò che fai è nascondere la dipendenza senza risolverla o rimuoverla.

Per un piccolo gioco che non ha bisogno di essere ridimensionato, questo non sarà un problema di per sé, ma potrebbe condurti lungo il percorso di una cattiva abitudine, quindi potresti voler considerare di non farlo. Almeno tienilo a mente per il prossimo progetto su cui lavori.


Amen! Toccate un ottimo punto di cui non ho davvero parlato nella mia risposta.
Nate,

+1 nascondere le dipendenze e introdurre lo stato globale è davvero il problema qui
ashes999,

4

Il motivo per cui chiamare TileHandler in un contesto statico non è il miglior progetto possibile, è che accoppia componenti del tuo progetto che potrebbero altrimenti essere disaccoppiati.

Se scegli di avere più di un TileHandler in futuro, dovrai fare molto lavoro per adattarsi a questo cambiamento.

Se scegli di rimuovere TileHandler, dovrai fare molto lavoro per adattarsi a questa modifica.

Supponiamo che in futuro costruirai un livello / zona diverso, che gestirà le tessere in modo diverso dal tuo attuale TileHandler. Quindi devi avere un modo per specificare il metodo di gestione delle tessere da usare, oppure devi chiamare un gestore diverso.

Se il TileHandler è stato passato come parametro agli oggetti che lo usano, puoi semplicemente passarne uno diverso la prossima volta o impostare un gestore di piastrelle diverso sugli oggetti che lo usano in seguito.

Personalmente, accedo a molte cose nei miei giochi XNA da un contesto statico e presumo che non ne avrò mai più di uno.

Se vuoi essere in grado di riutilizzare il codice del motore di gioco nel tuo prossimo gioco, probabilmente dovrai riscrivere gran parte delle cose che attualmente hai scritto come statiche.

In breve:

A favore del non utilizzo del contesto statico:

Passare il più possibile gli oggetti come parametri disaccoppia gli elementi di gioco e ti consente di modificarli / riutilizzarli per i progetti attuali o futuri più facilmente. Ti permette anche di gestire un po 'più facilmente la complessità di grandi quantità di codice (pensa di avere centinaia di gestori statici nella tua classe di gioco, in un grande gioco).

A favore del contesto statico:

Dichiarare e accedere agli oggetti da un contesto statico semplifica la scrittura di piccoli giochi che non richiedono centinaia di gestori statici. Semplifica molti metodi e costruttori non richiedendo uno o più parametri extra a cui si accede invece staticamente.



2

Cose come TileHandler e AnimalHandler metterei un livello più alto in una schermata di gioco. La schermata del titolo deve accedere a TileHandler ed è inizializzata al primo caricamento del gioco? Probabilmente no.

Guarda l'esempio XNA State Management . Ha un sacco di codice lì dentro, ma fondamentalmente il gioco base inizializza solo una pila di stati (o schermate) di gioco. Ogni schermo è abbastanza indipendente dagli altri e funziona come una versione semplificata del gioco stesso. Il tuo PlayScreen potrebbe avere membri statici, quindi sono accessibili ai componenti PlayScreen.

Nel gioco di base, utilizzo alcune statiche, ma sono cose di livello molto basso come lettori InputHelper, Log o Config. Sono abbastanza standard in tutti i giochi, quindi il motore di base può essere portato rapidamente e facilmente. Le schermate sono dove avviene la logica di gioco reale. Quindi lunga risposta breve - no, non credo sia una cattiva idea in teoria, fai solo attenzione a ciò che fai statico. Una volta che vai avanti e fai qualcosa di statico, è una grande quantità di lavoro se cambi idea.


0

I punti sollevati qui sono tutti buoni. Nella mia esperienza (che, ammettendo, è più rivolta alle app aziendali che ai giochi), ci sono grandi usi per classi e membri statici e li ho usati molte volte. Ho scoperto che, man mano che crescono i requisiti e la complessità, finisco per riciclare quelle classi statiche e convertirle in classi di istanze e iniziare a trasmetterle.

Il punto che vorrei sottolineare è che, se l'uso di una classe statica ti aiuta a far uscire questo gioco, fallo, ma fai comunque le cose giuste: implementa un'interfaccia o una classe base in modo che sia più facile estrarla e convertirla in seguito a una classe di istanza.

Un'oncia di prevenzione merita una libbra di cura, quindi assicurati che la tua classe statica non ti leghi dentro che rende difficile cambiare. È abbastanza semplice riformattare un metodo usando una classe statica che implementa un'interfaccia, quindi accetta un nuovo parametro di interfaccia e usa quell'interfaccia invece del riferimento di classe statica.


0

Sì, generalmente è sempre una cattiva idea.

Trasformare oggetti contenenti dati che cambiano (ovvero qualsiasi cosa tranne le costanti di sola lettura e le tabelle di ricerca) in classi statiche è dove il buon design si tuffa.

  1. Promuove dipendenze casuali che uccidono la modularità e ostacolano il riutilizzo del codice. Supponiamo che tu volessi scrivere un editor per il tuo gioco: improvvisamente avresti un sacco di lezioni che piangevano per un Game1che non puoi facilmente spostare in una libreria condivisa.

  2. Il tuo codice diventa non verificabile. Il test unitario funziona isolando le singole classi dalle altre deridendo o simulando le loro dipendenze (che dovrebbero essere mantenute il più possibile minime). Qualsiasi classe statica è una responsabilità perché è possibile accedervi in ​​qualsiasi momento, riportare lo stato su più test o richiedere l'inizializzazione prima che i test possano avere esito positivo.

  3. Nasconde le dipendenze. Proprio come l'anti-pattern del fornitore di servizi (utilizzato anche da XNA, Game.Services), le tue classi possono scegliere dipendenze che non vedi all'esterno.

Questo approccio diventa particolarmente velenoso se si combinano le classi statiche con le chiamate dei treni merci (cose simili Game.Instance.ActorManager.Enemies.FindInRange(10)- così chiamate a causa dei simboli concatenati simili a quelli di un vagone), in cui i componenti improvvisamente non solo richiedono una Gameclasse, ma uno con una Instanceproprietà statica che restituisce qualcosa con una ActorManagerproprietà che ha una Enemiesproprietà che restituisce un oggetto con un FindInRange()metodo.

L'unica scusa che accetterei per scrivere classi statiche mutevoli sarebbe quella che sta ancora imparando e non ha la capacità di applicare coerentemente un buon design e un occhio addestrato per individuare ancora cattive scelte.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.