sábado, 17 de março de 2007

(Não) Usando POO em JME

Normalmente, os programadoes que dão seus primeiros passos no JME tendem a trazer velhas (e boas) práticas da programação do Java "convencional" (JSE e/ou JEE), principalmente a forte utilização da POO (Programação Orientada a Objetos) e a utilização de padrões de projeto (os famosos Design Patterns).

É indiscutivel que essas práticas trouxeram inúmeras vantagens em relação a se desenvolver sem utilizá-las. Porém sua utilização no JME deve ser bem entendida e usada com extrema cautela para que o ganho em produtividade e reaproveitamento de código não se tornem causa de perda de desempenho e aumento do tamanho ocupado em memória pela aplicação - lembrando que os dispositivos que usam JME são bem mais limitados do que os que se utilizam de JSE e/ou JEE.

Porém, a palavra "limitado" para caracterizar os dispositivos que implementam o JME não é exagero, pois eles realmente possuem limitações em memória, armazenamento e processamento. Por isso, qualquer ganho de desempenho e memória por menor que seja se torna significativo, principalmente quando levamos em conta os recursos que temos disponíveis no celular. A uma hora dessa você já deve estar perguntando: "Então quer dizer que devo diminuir a criação de novos objetos e classes porque isso custa muito caro ?"

Você não precisa necessariamente sacrificar suas idéias de orientação a objetos ou deixar de usar um determinado pattern. O que se deve fazer é analisar o cenário da sua aplicação e adaptar o que já existe para as limitações dos devices. Então, o que se deve levar em consideração sobre ao excesso uso de orientação objetos? Veja abaixo:

  • O overhead natural da linguagem Java que é adicionado na geração do byte code a CADA CLASSE.
  • O custo para se executar o carregamento de cada classe nova gerada quando é utilizada.
  • O custo gasto para se alocar/desalocar a memória heap da classe em questão.
  • O custo para a montagem da pilha de execução e montagem do escopo da classe e dos métodos.
  • Além de se aumentar o número de objetos que o garbage collector precisa inspecionar.
O que fazer então para que todos esses custos se tornem o minimo possível ?
Algumas medidas podem ser tomadas, como por exemplo:
  • Atribua/recupere os valores diretamente das variáveis. Os métodos get/set fazem sua aplicação perder tempo entrando em um método, montando a pilha de execução, definindo o escopo da execução, etc.
  • Tente reutilizar ao máximo suas variáveis e assim evitando a perda do tempo que a KVM leva para fazer o class loader.
  • Quando for criar uma nova classe derivada de outra análise ao máximo se realmente precisa criar uma classe nova ao invés de usar as classes já existentes adicionando a elas os componentes do JME.
  • Somente crie novas classes quando precisar realmente adicionar algum comportamente diferente ao já existente na classe. O tratamento de comando não precisa ser feito especificamente dentro do componente que possue o comando, PENSE NISSO!!
  • Projetar suas novas classes que tenham o máximo de caracteristicas para que sejam reaproveitadas ao máximo, por exemplo: Quando for criar uma classe nova de personagem para o seu jogo, tente fazê-la de modo que todos os personagens usem a mesma classe, mudando apenas os atributos.
As vezes, o que não parece elegante do ponto de vista de POO ou de algum design pattern pode ser a diferença entre o sucesso e a falha de sua aplicação, pois ela roda em um dispositivo que na maioria das vezes não é o computador principal do usuário e mesmo assim o usuário quer respostas rápidas e precisas!
Abaixo estão dois artigos nos quais me baseei para escrever essa minha pequena contribuição para o melhor desempenho da sua aplicação.

Por isso, como eu sempre digo: Don´t think BIG! Think MICRO! JME!!

Referências:


2 comentários:

Luis disse...

Grande Neto!
Parabéns pelo Blog! Se serve como adento: não é uma boa prática - nem performático rodar o System.gc() no JME também!

Adicionei seu Blog nos links do meu.

Abraço!
-- Luis

Daniel ABella disse...

Parabéns pelo blog!