
IFs demais...
Olá,
No post de hoje vou falar sobre o uso excessivo de “IF” e o uso de “SWITCH CASE” em orientação a objetos. Os programadores mais experientes sabem que essa prática é ruim e vai totalmente contra os princípios de POO.
O paradigma de orientação a objetos foi pensado de forma a permitir que os componentes respondam por si, pelo seu estado e que assumam características diferentes de acordo com sua implementação (polimorfismo).
Mas aí vem a pergunta: Quando devo usá-los então????
“Nunca”, talvez não seja a melhor resposta (para o uso do “switch case“ eu responderia nunca...), mas devemos usar com bom senso.
Vamos pensar na seguinte situação: Eu quero saber o nome de 5 crianças e a partir desses nomes comandar uma ação:
Pedro – Escovar os dentes;
Ana – Ir para a escola;
Marcelo – Pentear o cabelo;
Livia – Amarrar o tênis;
Taisa – Arrumar o quarto.
Se eu tivesse que resolver essa situação utilizando o IF, primeiro eu teria que perguntar quem é a criança, e em seguida comandar a ação:
Se você é o Pedro
Escove os dentes...
Se você não é o Pedro, mas é a Ana
Vá para a escola....
Se você não é a Ana nem o Pedro, mas é o Marcelo:
Penteie o cabelo...
E assim por diante...
Agora imagine-se diante das crianças se comportando dessa forma... fica estranho não acha? As próprias crianças iriam sugerir: “Você não quer saber o nosso nome, antes de nos dizer o que fazer?”... Isso vai economizar “TEMPO”.
E é exatamente esta a proposta da POO, facilitar as coisas para economizar tempo de processamento. Agora, usando POO, vamos resolver esta questão:
Primeiro eu sei que cada criança tem uma ação pré-definida, portanto, podemos criar uma classe abstrata “Crianca” e obrigar o programador a preencher essa ação:
abstract class Crianca { abstract void agir(); }
Agora, eu crio uma classe para cada criança, preenchendo a ação. Sempre que eu estender a classe “Crianca”, o compilador me obriga e preencher o método “agir()”.
public class Ana extends Crianca{ public void agir() { System.out.println("Ir para escola..."); } }
public class Marcelo extends Crianca { public void agir() { System.out.println("Pentear o cabelo..."); } }
Depois de criar todas as classes, incluímos as crianças em uma lista e executamos seu método agir():
public class Mapa { public static void main(String[] args) { ArrayList<Crianca> criancas = new ArrayList<Crianca>(); criancas.add(new Pedro()); criancas.add(new Ana()); criancas.add(new Marcelo()); criancas.add(new Livia()); criancas.add(new Taisa()); for (Crianca c : criancas) { c.agir(); } } }
Da mesma forma, eu poderia ter criado uma interface “Crianca” com o método agir e as classe com os nomes das crianças implementando essa classe.
Entenderam? Sem if, sem processamento desnecessário, só utilizando POO e fazendo com que os objetos façam aquilo que foi designado a eles na implementação dos seus métodos.
No post anterior, onde eu falo sobre animações em Android, eu propositalmente fiz uso de IFs para determinar qual animação seria adicionada à lista de animações. Perceba que, quando eu monto a ArrayList que vai ser enviada via intent, utilizo 4 IFs para terminar qual CheckBox foi selecionado e em seguida, mais 4 IFs para determinar qual animação veio do ArrayList para adicioná-las ao AnimatorSet.
Com isso, serão 8 IFs executados sempre que eu acionar o botão ANIMAR, e mais, sempre que eu quiser incluir na aplicação um CheckBox com mais um tipo de animação, terei que incluir um novo método na classe Animacao, um IF na classe MainActivity e mais um IF na classe AnimacaoActivity.
Esta solução está ruim pois dificulta a manutenção do código, sempre passa por todos os IFs mesmo que o usuário não selecione nenhum CheckBox e não utiliza os recursos de POO.
Vamos corrigir:
Primeiro, eu criei uma constante numérica para cada animação possível na minha classe Animacao:
public static int ANIM_ALPHA = 0; public static int ANIM_TRANSLATEX = 1; public static int ANIM_TRANSLATEY = 2; public static int ANIM_ROTATE = 3; public static int ANIM_SCALEX = 4; public static int ANIM_SCALEY = 5;
em seguida, apaguei todos os métodos add(), criei um HashMap animators para receber as possíveis animações e as incluí com método loadMap():
private void loadMap() { animators.put(ANIM_TRANSLATEX, ObjectAnimator.ofFloat(view, "x", 100f, 10f, 100f)); animators.put(ANIM_TRANSLATEY, ObjectAnimator.ofFloat(view, "y", 200f, 50f, 200f)); animators.put(ANIM_ALPHA, ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f)); animators.put(ANIM_SCALEX, ObjectAnimator.ofFloat(view, "scaleX", 1f, -1f, 1f)); animators.put(ANIM_SCALEY, ObjectAnimator.ofFloat(view, "scaleY", 1f, -1f, 1f)); animators.put(ANIM_ROTATE, ObjectAnimator.ofFloat(view, "rotation", 0f, 360f, 0f)); }
alterei o método executeAnimation(), para receber uma lista de inteiros indicando as animações escolhidas pelo usuário e executá-las:
public void executeAnimation(List<Integer> valores) { ArrayList<Animator> animacoes = new ArrayList<>(); for (int i = 0; i < valores.size(); i++) { animacoes.add(animators.get(valores.get(i))); } AnimatorSet animSet = new AnimatorSet(); animSet.playTogether(animacoes); animSet.setDuration(3000); animSet.start(); }
na classe MainActivity() mapeei os novos CheckBox e adicionei a todos eles um listener que preenche uma lista de inteiros que será enviada à classe AnimacaoActivity via intent.
Observem que foi utilizado um IF para determinar o estado do CheckBox e a partir deste estado incluir ou excluir um valor de animação da lista de inteiros. Neste caso, o IF será executado apenas 1 vez, caso o usuário marque ou desmarque o CheckBox, sem consumir processamento desnecessário:
private CompoundButton.OnCheckedChangeListener onCheckedChangeListener = new CheckBox.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) list.add((int) buttonView.getTag()); else list.remove(list.indexOf(buttonView.getTag())); } };
e por fim, na classe AnimacaoActivity, recebemos a lista de inteiros vinda do intent e passamos para o objeto animacao:
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_animacao); animacoes = getIntent().getIntegerArrayListExtra("animacoes"); img = (ImageView) findViewById(R.id.imageView); animaView(); } public void animaView() { Animacao animacao = new Animacao(img); animacao.executeAnimation(animacoes); }
Resolvido, sem IF, sem processamento desnecessário apenas com POO.
Para incluir uma animação, basta adicionar um novo CheckBox ao projeto, incluir uma constante para essa nova animação e adicioná-la ao mapa de animações da classe Animacao, tornando simples a manutenção do código.
Baixe o exemplo atualizado: Atualizado.7zip.
Baixe o exemplo das crianças para o Eclipse: Criancas.7zip
Por hoje é isso, até o próximo post.
Nenhum comentário:
Postar um comentário