Subscribe:

About

quinta-feira, 23 de agosto de 2012

Desenvolvimento baseado em componentes

O desenvolvimento baseado em componentes é um paradigma dentro de engenharia de software que se preocupa principalmente com a separação de conceitos. Decidimos analisá-lo por ser uma tendência bem interessante no desenvolvimento de games.


O que é desenvolvimento baseado em componentes?


A proposta básica do desenvolvimento baseado em componentes é simples: modulação. Constrói-se o software a partir de vários módulos chamados de componentes, que encapsulam uma função ou conjunto de dados específico. Cada nova funcionalidade, seja cadastro de usuário, cálculo de despesas ou qualquer outra coisa, exige um novo componente.

Mas para que tudo isso? Essa metodologia visa uma maior reusabilidade de código, já que os componentes possuem um bom grau de independência tanto entre si quanto em relação ao contexto, permitindo sua utilização em sistemas distintos. Isso também pode acarretar em benefícios extras: flexibilização, uma vez que é possível adicionar, alterar e remover funcionalidades mais facilmente; maior facilidade de manutenção; maior facilidade de gerenciamento etc. Claro, tudo isso depende de uma boa implementação.

Diante das possibilidades cada vez maiores proporcionadas pelo avanço do hardware e devido à crescente exigência do consumidor, desenvolvedores de games decidiram incorporar essas ideias na forma de sistemas de entidades.

Sistemas de entidades?


Há algumas definições distintas, mas, de modo geral, um sistema de entidade é um subconjunto particular do desenvolvimento baseado em componentes. É importante frisar que, embora sistemas de entidades possam ser implementados através da orientação a objetos, trata-se de uma abordagem completamente diferente, com seus próprios paradigmas.

A principal diferença entre uma abordagem tradicional e a abordagem orientada a componentes é que a primeira baseia-se em uma arquitetura fortemente hierarquizada, e a segunda aposta na composição/agregação. Um exemplo prático de arquitetura tradicional e hierarquizada é a seguinte, supondo um game simples de plataforma:


Todos os itens do jogo herdam de GameObject e então acrescentam suas características próprias. Esse é um dos conceitos mais básicos de orientação a objetos e a maneira como estamos acostumados a pensar. Sem problemas, certo? Você começa a programar na maior tranquilidade, mas não demora muito até perceber que, para atender às constantes novas exigências do game design, algumas coisas são necessárias:

  • E se alguns dos elementos estáticos forem animados ao invés de completamente parados? Talvez você deva criar uma subclasse de Rigid que seja Animated.
  • E se algumas plataformas não forem estáticas, e sim movíveis? E se algumas plataformas forem estáticas e animadas? Talvez seja melhor refazer a arquitetura e deixar Platform apenas como um elemento colidível, que pode ou não incorporar movimento e/ou animação.
  • E se houver itens que alteram o estado do level de alguma forma? Talvez uma subclasse Item resolva, junto com uma nova classe chamada Level, que vai guardar as informações necessárias.

Perceba que, aos poucos, a complexidade aumenta progressivamente e uma única mudança pode provocar alterações profundas na arquitetura. No pior dos casos, o resultado final são classes sobrecarregadas, classes com pouca ou nenhuma função e diversas gambiarras, tornando o código absolutamente intocável e impossível de se atualizar para corresponder às expectativas.

Então qual é uma possível solução? Modulação. Separamos cada característica em componentes distintos, de modo que uma entidade seja um agregado de componentes específicos:

Player Enemy Platform MoveablePlatform
Movement X X X
Collision X X X X
Physics X X
Script X

Agora, se quisermos por exemplo uma plataforma inteligente, basta adicionarmos um módulo que possibilita a especificação de instruções através de scripts. Similarmente, é perfeitamente possível criar uma entidade de inimigo que não agregue o módulo de movimento, sendo portanto estático. Essa é a base dos sistemas de entidades.

Como implementar sistemas de entidades?


Não há uma única resposta para a pergunta de como implementar esta arquitetura, mas geralmente um sistema de entidades pode ser considerado fiel à proposta se for algo parecido com o seguinte:

Clique para ampliar.

Cada entidade é simplesmente uma label que agrega um conjunto específico de componentes. As características (os dados), portanto, estão todas nos componentes. Mas então onde é que está a lógica que vai dar sentido a esse emaranhado de dados e agregações? É aí que entram os sistemas, cada qual responsável por um aspecto específico dentro do jogo.

Este artigo fornece um bom exemplo de como as coisas funcionam na prática. Basicamente temos o seguinte:

  1. Uma entidade é representada por uma classe que serve unicamente para identificá-la dentro da aplicação.
  2. Um componente é representado por uma classe que serve unicamente para listar seus atributos (coordenadas, tamanho, quantidade etc.).
  3. Deve haver uma forma de mapear as entidades aos seus respectivos componentes. Em Java, a classe HashMap serve como um bom meio para tal.
  4. Os sistemas são chamados pelo loop principal do jogo e interagem com as entidades através desse mapeamento entidade-componentes. Por exemplo, o sistema de movimentação interage com todas as entidades que são movíveis, atualizando seus componentes "Posição".

Um sistema de entidades é para mim?


Antes de optar pela implementação ou não de um sistema de entidades, é preciso ponderar bem os custos e ganhos da abordagem.

Benefícios de sistemas de entidades


  • Reusabilidade: É a motivação básica do desenvolvimento baseado em componentes, como explicado no início.
  • Flexibilidade: Em games, principalmente os de larga escala, é fundamental manter uma arquitetura que possa ser alterada facilmente. Pode ser devido a mudanças no design ou mesmo após o lançamento do produto. Vemos isso na prática com pacotes de expansão, conteúdo extra disponível via download (DLC) e atualizações de games online.
  • Rapidez: Sistemas de entidades podem tornar mais rápidos os ciclos de desenvolvimento, compilação e testes, uma vez que temos unidades bem definidas e independentes.
  • Separação de lógica e dados: A lógica nos sistemas é relativamente independente dos dados nos componentes, o que permite ajustes rápidos sem precisar refatorar o código inteiro. Isso também contribui para a flexibilidade.

Problemas de sistemas de entidades


  • Mudança de paradigma: É muito difícil acostumar-se com essa abordagem, de modo que os programadores podem facilmente cair em algumas "armadilhas" e utilizar a abordagem tradicional disfarçada de sistemas de entidade. Esta arquitetura traz conceitos bem distintos que a princípio podem enfrentar dura resistência.
  • Dificuldade de adaptação: Justamente por ser uma abordagem distinta, se já houver algum código existente, fica muito complicado refatorar tudo e transformar em um sistema de entidades.
  • Requisitos de tecnologia: Não é qualquer linguagem e tecnologia que suportam sistemas de entidades, e as que suportam muitas vezes requerem conhecimentos específicos. Em Java, por exemplo, é preciso ter uma sólida base sobre como funcionam tipos genéricos.
  • Abstração: Codificar novas funcionalidades pode ser mais fácil, mas para que isso aconteça, o programador precisa se preocupar com vários detalhes antes mesmo de começar a aplicação: registrar entidades, mapear entidades aos componentes de forma eficiente, gerenciar os sistemas etc.
  • Alto custo de "setup": Como há muito trabalho empregado apenas para estabelecer um sistema de entidades, pode acabar gerando mais esforço do que a abordagem tradicional, tornando-o inviável em projetos pequenos.

Conclusões


Sistemas de entidades e o desenvolvimento baseado em componentes de forma geral são abordagens muito interessantes que podem ser estudadas como alternativas a determinados problemas. No entanto, é provável que não as utilizemos no desenvolvimento de Shadow Struggles porque o peso dos benefícios não parece compensar o peso dos problemas citados anteriormente. Trata-se de um projeto com um escopo relativamente pequeno e somos um grupo iniciante no desenvolvimento de games, então parece ser mais vantajoso nos mantermos no tradicional por enquanto.

Fontes


0 comentários:

Postar um comentário