Sto tentando di modellare un gioco di carte in cui le carte hanno due serie importanti di funzioni:
Il primo è un effetto. Queste sono le modifiche allo stato del gioco che si verificano quando giochi la carta. L'interfaccia per l'effetto è la seguente:
boolean isPlayable(Player p, GameState gs);
void play(Player p, GameState gs);
E potresti considerare la carta giocabile se e solo se puoi far fronte al suo costo e tutti i suoi effetti sono giocabili. Mi piace così:
// in Card class
boolean isPlayable(Player p, GameState gs) {
if(p.resource < this.cost) return false;
for(Effect e : this.effects) {
if(!e.isPlayable(p,gs)) return false;
}
return true;
}
Ok, finora, piuttosto semplice.
L'altra serie di funzioni sulla carta sono abilità. Queste abilità sono modifiche allo stato del gioco che puoi attivare a volontà. Quando ho trovato l'interfaccia per questi, mi sono reso conto che avevano bisogno di un metodo per determinare se possono essere attivati o meno, e un metodo per implementare l'attivazione. Finisce per essere
boolean isActivatable(Player p, GameState gs);
void activate(Player p, GameState gs);
E mi rendo conto che con l'eccezione di chiamarlo "attiva" invece di "play", Ability
e Effect
hanno la stessa identica firma.
È una cosa brutta avere più interfacce con una firma identica? Dovrei semplicemente usarne uno e avere due set della stessa interfaccia? In questo modo:
Set<Effect> effects;
Set<Effect> abilities;
Se è così, quali passi refactoring dovrei prendere in mano se diventano non identici (come vengono rilasciate più funzioni), in particolare se sono divergenti (cioè entrambi guadagnano qualcosa l'altro non dovrebbe, al contrario di un solo guadagno e l'altro è un sottoinsieme completo)? Sono particolarmente preoccupato che la loro combinazione non sarà sostenibile non appena qualcosa cambierà.
La stampa fine:
Riconosco che questa domanda è generata dallo sviluppo del gioco, ma ritengo che sia il tipo di problema che potrebbe facilmente insinuarsi nello sviluppo non di gioco, in particolare quando si cerca di accogliere i modelli di business di più client in un'applicazione come succede con quasi tutti i progetti che ho mai fatto con più di un'influenza commerciale ... Inoltre, i frammenti utilizzati sono snippet Java, ma questo potrebbe facilmente applicarsi a una moltitudine di linguaggi orientati agli oggetti.