Otimizar a programação de seus jogos, é uma preocupação constante de todo programador.
Pois, para que tudo funcione bem, é preciso sempre refatorar e polir nossos códigos, ao longo do desenvolvimento.
E existe um conceito que é extremamente importante para manter seu código, menos dependente possível.
O problema da dependência de Código
É comum acontecer de você alterar um script e ele quebrar totalmente a lógica em que seu jogo foi construído.
E chegando ao ponto de você precisar refazer diversos scripts para consertar algo simples, que não demandaria esse trabalho todo.
Se você é um programador, sem dúvidas já passou por essa situação, e um código dependente assim é um problema.
Pois, isso é um sinal que seu jogo pode ter diversos bugs, se algo falhar, todo o jogo quebra.
E existe um aglomerado de conceitos que juntos tratam justamente dessa alta dependência em códigos, conhecido como SOLID.
SOLID
O SOLID é um aglomerado de conceitos que nos ajuda a entender melhor como organizar a lógica de nossos códigos.
E cada um desses conceitos trata de algum ponto específico e importante para a estruturação da codificação.
Single-responsiblity principle — Princípio da responsabilidade única:
Este princípio nos diz que cada classe do nosso jogo precisa ter uma responsabilidade única, nos trazendo diversas vantagens.
Por exemplo, a classe fica bem menor e muito mais clara, fácil de dar manutenção, reduzindo a dependência de código.
E um exemplo seria: o script que monitora a vida e status do player, não pode causar dano também.
Pois, não é uma função dele, para isso, deveríamos criar uma classe inteiramente dedicada apenas para o sistema de Dano.
Open-closed principle — Princípio aberto-fechado:
Este princípio nos diz que as nossas classes podem permitir serem estendidas, mas nunca modificadas por outras classes.
Pois, cada classe tem sua responsabilidade e caso ela possa ser modificada de outros lugares, você terá problemas.
E no lugar de modificar diretamente outra classe, seria uma melhor prática herdar dela e sobrescrever seus métodos.
Por exemplo, um script Enemy, padrão para todos os inimigos, não pode ser modificado por qualquer outro script de inimigo.
Pois, se um único inimigo tem a necessidade de personalizar somente o ataque, então ele deve herdar do script padrão.
E sobrescrever apenas a função de ataque, assim resolvendo seu problema e mantendo o padrão para os demais inimigos.
Liskov substitution principle — Princípio da substituição de Liskov:
Este principio é um pouco mais complexo, pois, está diretamente ligado a detalhes específicos de nosso projeto.
Mas, basicamente ele nos diz que: Classes derivadas devem ser substituíveis por suas clases base, sem que o comportamento mude.
Por exemplo, em um sistema de bancos, podemos usar as funções de depositar dinheiro, transferir e fazer empréstimos.
E o cliente pode ter uma conta Poupança ou Corrente para poder usar essas funções (serviços), disponibilizados pelo banco.
Mas, se eu tentar transferir dinheiro ou fazer empréstimo com a conta Poupança, o sistema quebra e dá erro.
Porque a conta poupança só possui a função de Depósito, logo ela não está respeitando o princípio de substituição.
Então, isso significa que essa classe Poupança, deveria ter um sistema a parte para lidar com suas transações.
Interface segregation principle — Princípio da Segregação de interface:
Esse princípio nos diz que nenhuma classe deve ser obrigada a depender de Funções ou Interfaces que não precisam.
Por exemplo, em seu jogo você tem uma interface que gerencia os ataques de inimigos, com funções de ataques.
Mas, você criou um mago e implementou essa interface, obrigando ele a lidar com todos os ataques ali presente.
E aqui o ideal seria subdividir essa interface em magias, ataque corpo a corpo, armas de fogo, etc.
Pois, dessa forma um mago precisaria apenas da interface de magia, dispensando as demais que não são interessantes a ele.
Dependency Inversion Principle — Princípio da inversão de dependência:
Segundo esse princípio, classes de alto nível não podem depender de classes de baixo nível, mas ambas dependerem de abstrações.
Por exemplo, em seu jogo você cria um guerreiro, mas ele precisa de uma espada e um escudo.
E então na própria classe, você gera uma nova instância de objeto de espada e escudo, mas teremos um problema.
Pois, seu guerreiro não poderá ser criado sem esse escudo e espada, logo ele é dependente de uma outra classe.
E o ideal seria cada classe ser única e independente da outra, e se associarem através de Abstrações como interfaces.
E dessa forma seu guerreiro pode existir sem escudo, e pode até mesmo ter espadas diferentes.
Pois, ele pode ter uma espada e escudo ou nenhum, e podem ser de qualquer tipo também.
E por fim a classe escudo e espada que serão responsáveis por gerenciar seus próprios tipos.
Pois, com isso você tira a dependência uma da outra, mesmo as 3 classes podendo interagir.
O uso de SOLID está diretamente ligado ao uso das melhores práticas e orientação a objetos.
Por isso é de estrema importância estudar todas estas áreas para que ambas se complementem.
E você possa criar os seus códigos da maneira mais organizada e polida possível.
Seja o primeiro a comentar.