Estou pensando nisso há dias e ainda não tenho certeza do que fazer. Estou tentando refatorar um sistema de combate em PHP (... desculpe.) Aqui está o que existe até agora:
- Existem dois tipos (até agora) de entidades que podem participar de combate. Vamos chamá-los de jogadores e NPCs. Seus dados já estão escritos muito bem.
- Quando envolvidas em combate, essas entidades são envolvidas com outro objeto no banco de dados chamado a
Combatant
, que fornece informações sobre a luta em particular. Eles podem se envolver em vários combates ao mesmo tempo. - Estou tentando escrever o mecanismo lógico para o combate injetando combatentes nele.
- Quero poder zombar de tudo para testar.
Para separar lógica e dados, quero ter duas interfaces / classes base, uma sendo ICombatantData
a outra ICombatantLogic
. Os dois implementadores de dados serão um para os objetos reais armazenados no banco de dados e o outro para meus objetos simulados.
Agora estou tendo incertezas ao projetar o lado lógico das coisas. Posso ter um implementador para cada um dos jogadores e NPCs, mas tenho um problema. Um combatente precisa ser capaz de devolver a entidade que envolve. Esse método getter deve fazer parte da lógica ou dos dados? Sinto fortemente que deve estar nos dados, porque a parte lógica é usada para a execução de combate e não estará disponível se alguém estiver apenas procurando informações sobre uma luta futura. Mas as classes de dados separam apenas o mock do DB, não o player do NPC. Se eu tentar ter duas classes filho do implementador de dados do banco de dados, uma para cada tipo de entidade, como faço para arquitetar isso enquanto mantenho minhas zombarias no loop? Preciso de uma terceira interface como IEntityProvider
essa que injeto nas classes de dados?
Também com algumas das idéias que estive pensando, acho que vou ter que colocar verificações para garantir que você não descasque as coisas, como fazer a lógica para um NPC acidentalmente agrupar os dados para um jogador. Isso faz algum sentido? Essa é uma situação que seria possível se a arquitetura estivesse correta ou o design correto proibiria isso completamente para que eu não precisasse verificar?
Se alguém pudesse me ajudar a traçar um diagrama de classe ou algo para isso, isso me ajudaria muito. Obrigado.
editar
Também é útil notar que a classe de dados simulados realmente não precisa da Entity
, pois apenas especificarei todos os parâmetros como estatísticas de combate diretamente. Talvez isso afete o design correto.
fonte
Combatant.entity
não é usado durante o combate e, portanto, não deveria existir. Talvez você precise de outra classe, como aEntityVsEntityCombat
que envolve a lógica de combate, contémEntity <--> Combatant
mapeamentos e atualiza osEntity
estados após o término do combate? Talvez mais algumas informações sobre sua arquitetura atual possam ajudar.Respostas:
Parte da maneira como abordamos isso no passado é, em vez de ter representações completamente separadas para jogadores e NPCs, exigindo que ambos implementem uma interface comum, direcionando para a convergência de representação entre eles o máximo possível, como posso. subclassificando-os a partir de um
Character
modelo comum no qual pressiono tanto sobre eles quanto faz sentido generalizar. Isso ajuda a evitar problemas com a execução de operações de NPC nos jogadores, tornando as operações mais aplicáveis em geral, uma vez que há menos tendência natural para as representações divergirem do que se fossem implementações completamente independentes. A alavancagem básica do polimorfismo ajuda a lidar com os casos que precisam divergir (por exemplo, se você fez o seuCombatantLogic
responsável por lidar com o que acontece quando alguém morre, você teria que digitar para ter certeza de usar a lógica correta; então não faça, jogadores e NPCs implementemdie()
métodos separados e apropriados ).Concordo que você
Entity
faz parte dos dados. No entanto, com base no que eu estava dizendo, eu tenderia a remover ou limitar o seu papel aCombatantData
favor de fazer com que a lógica de combate extraísse valores diretamente dosEntity
, talvezCombatantData
apenas com o armazenamento de valores calculados caros e específicos de combate único. Seus modelos de teste seriam mais orientados a fornecerEntity
modelos falsos do que a preencherCombatantData
. (CombatantData
Duplicar muitas informaçõesEntity
me incomoda da mesma maneira que um banco de dados desnormalizado. No entanto, se você acredita na Lei de Deméter, que eu não gosto apaixonadamente, não vai querer fazer as coisas da maneira que eu Estou sugerindo. Claro, se você acredita na Lei de Demeter, não tenho certeza de queCombatantData
deve até fornecer acesso aoEntity
.)fonte