Estou tentando modelar um jogo de cartas em que as cartas têm dois conjuntos importantes de recursos:
O primeiro é um efeito. Essas são as alterações no estado do jogo que acontecem quando você joga a carta. A interface para efeito é a seguinte:
boolean isPlayable(Player p, GameState gs);
void play(Player p, GameState gs);
E você pode considerar que a carta é jogável se, e somente se, você puder atingir o custo e todos os efeitos jogáveis. Igual a:
// 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, até agora, muito simples.
O outro conjunto de recursos do cartão são habilidades. Essas habilidades são alterações no estado do jogo que você pode ativar à vontade. Ao criar a interface para eles, percebi que eles precisavam de um método para determinar se eles podem ser ativados ou não, e um método para implementar a ativação. Acaba sendo
boolean isActivatable(Player p, GameState gs);
void activate(Player p, GameState gs);
E eu percebo que, com exceção de chamá-lo "activar" em vez de "play", Ability
e Effect
tem exatamente a mesma assinatura.
É ruim ter várias interfaces com uma assinatura idêntica? Devo simplesmente usar um e ter dois conjuntos da mesma interface? Assim:
Set<Effect> effects;
Set<Effect> abilities;
Em caso afirmativo, que medidas de refatoração devo seguir adiante se elas se tornarem idênticas (à medida que mais recursos forem lançados), principalmente se forem divergentes (ou seja, ambas ganham algo que a outra não deveria, em oposição a apenas uma) e o outro sendo um subconjunto completo)? Estou particularmente preocupado que combiná-los não seja sustentável assim que algo mudar.
A boa impressão:
Reconheço que esta questão é gerada pelo desenvolvimento de jogos, mas acho que é o tipo de problema que poderia surgir com a mesma facilidade no desenvolvimento não relacionado a jogos, principalmente ao tentar acomodar os modelos de negócios de vários clientes em um aplicativo, como acontece com quase todos os projetos que já fiz com mais de uma influência nos negócios ... Além disso, os trechos usados são trechos de Java, mas isso poderia ser aplicado facilmente a uma infinidade de linguagens orientadas a objetos.