Refatoração de Código: Unificar Interfaces

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes! Você receberá um email de confirmação. Somente depois de confirma-lo é que eu poderei lhe enviar os conteúdos semanais exclusivos. Os artigos em PDF são entregues somente para os inscritos na lista.

Email inválido.
Blog /Android /Refatoração de Código: Unificar Interfaces

Refatoração de Código: Unificar Interfaces

Vinícius Thiengo
(1853)
Go-ahead
"O método consciente de tentativa e erro é mais bem-sucedido que o planejamento de um gênio isolado."
Peter Skillman
Prototipagem Android
Capa do curso Prototipagem Profissional de Aplicativos
TítuloAndroid: Prototipagem Profissional de Aplicativos
CategoriasAndroid, Design, Protótipo
AutorVinícius Thiengo
Vídeo aulas186
Tempo15 horas
ExercíciosSim
CertificadoSim
Acessar Curso
Quer aprender a programar para Android? Acesse abaixo o curso gratuito no Blog.
Lendo
TítuloTest-Driven Development: Teste e Design no Mundo Real
CategoriaEngenharia de Software
Autor(es)Mauricio Aniche
EditoraCasa do Código
Edição1
Ano2012
Páginas194
Conteúdo Exclusivo
Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba gratuitamente conteúdos Android sem precedentes!
Email inválido

Opa, blz?

Nesse artigo continuamos com a série Refatoração de Código para se tornar um developer de alto desempenho, dessa vez abordando o método de refatoração Unificar Interfaces.

Já lhe adianto que se em alguma outra refatoração foi informado que ela era a menor, na verdade, essa é a menor.

Antes de prosseguir informo que no final do artigo tem os links de todos os outros métodos de refatoração já apresentados até aqui, nessa série, e que eles podem ser utilizados em qualquer linguagem que seja possível trabalhar no paradigma orientado a objetos. Alguns métodos podem ser utilizados até mesmo no paradigma procedural.

Tópicos presentes no artigo:

Motivação

Em seu código há uma hierarquia de classes onde a superclasse, apesar de ter implementado nela alguns métodos e atributos comuns as subclasses, ainda não trabalha de forma polimórfica, pois as subclasses ainda têm trechos com as próprias implementações. Trabalhar com polimorfismo é também ter a mesma interface (métodos e atributos públicos) das subclasses.

Note que interface aqui implica em métodos e atributos com tipo de acesso public e não a Interface estrutura de linguagem.

Código de exemplo

O código desse artigo é uma simples hierarquia do mundo animal. Para permitir que parte da lógica do projeto seja alterada para trabalhar com o polimorfismo, vamos aplicar o método de refatoração na superclasse a seguir:

public abstract class Animal {
public abstract void andar();

public abstract void comer();
}

 

Abaixo a classe Formiga que herda de Animal e implementa os métodos obrigatórios:

public class Formiga extends Animal {

@Override
public void andar() {
...
}

@Override
public void comer() {
...
}

public double forcaGancho(){
...
}
}

 

E ainda temos a classe Cachorro que também herda de Animal:

public class Cachorro extends Animal {
@Override
public void andar() {
...
}

@Override
public void comer() {
...
}

public void latir(){
...
}
}

 

Nosso objetivo é permitir que a classe Animal tenha uma interface comum quanto as suas subclasses para que seja possível em um array de Animal, por exemplo, realizar o processamento polimórfico das instâncias sem necessidade de identificação de tipo, independente dos métodos invocados.

Mecânica

O método de refatoração proposto aqui, como já informado: é bem simples. Temos apenas um passo a ser implementado. Pode acreditar.

Vamos buscar métodos públicos, nas subclasses, que estejam ausentes em na superclasse sendo refatorada. Na hierarquia do projeto de exemplo temos os métodos forcaGancho() que está em Formiga e latir() que está em Cachorro.

Esses métodos ausentes terão cópias nulas (ou conteúdo vazio) em nossa superclasse Animal.

Cópias nulas?

Sim, eles não terão comportamento definido, serão vazios, pois com o objetivo de ter uma interface comum e sabendo que eles não são comuns na hierarquia de classes, não devemos forçar uma implementação comum as subclasses, dessa forma apenas deixamos os métodos vazios. Caso algum deles tenha retorno, apenas retornamos o dado padrão para o tipo de retorno, por exemplo: null para String e 0 para int.

Segue nova versão de Animal, depois de realizar a cópia de forcaGancho():

public abstract class Animal {
public abstract void andar();

public abstract void comer();

public double forcaGancho(){
return( 0 );
}
}

 

Perceba que como retorno do método colocamos o valor 0, pois em nosso caso a implementação é em Java, e para tipos primitivos numéricos o 0 é o valor padrão. Lembrando que esse retorno de valor padrão, para um método que tem retorno, é equivalente a uma implementação vazia.

Note que, antes do código acima, foi informado que realizamos uma "cópia" e não uma remoção, pois a classe Formiga mantém a implementação de forcaGancho().

Esse foi o primeiro e único passo. O que devemos fazer agora é aplicar o mesmo para todos os outros métodos públicos encontrados nas subclasses e que não têm uma referência na superclasse. Logo, ainda temos que aplicar o mesmo passo de refatoração para o método latir() de Cachorro:

public abstract class Animal {
public abstract void andar();

public abstract void comer();

public double forcaGancho(){
return( 0 );
}

public void latir(){}
}

 

Como latir() não tem retorno, literalmente não precisamos fazer nada no conteúdo dele.

Dessa forma, um código cliente que utiliza uma coleção de animais poderia seguramente trabalhar com a classe Animal e chamar todos os métodos sem necessidade de identificação de tipo de classe para saber se pode ou não invocar determinado método:

...
Animal[] animais = new Animal[2];

animais[0] = new Cachorro();
animais[1] = new Formiga();

for( Animal animal : animais ){
animal.andar();
animal.comer();
animal.latir();
animal.forcaGancho();
}
...

 

Com isso finalizamos o método de refatoração proposto aqui.

Você provavelmente deve estar se perguntando: somente vamos utilizá-lo quando for necessária a aplicação de polimorfismo?

Não. Quando for necessário que uma classe tenha uma interface única em relação a outras classes (não necessariamente subclasses) é que se aplica o método de refatoração Unificar Interfaces.

Somente com classes (superclasses) conseguimos essa interface unificada?

Não. O método pode ser aplicado para Interfaces também, mas no caso de Interface a implementação por parte das classes concretas será inevitável.

Conclusão

Polimorfismo via herança tem suas vantagens (e desvantagens), a principal delas é deixar o código limpo quando a herança é aplicada corretamente, ou seja, entre classes relacionadas.

Apesar de alguns métodos definidos na classe base não serem requeridos por algumas subclasses, depois da aplicação do método desse artigo. Pode ser que esse modelo de código melhor se encaixe para a lógica de negócio que seu projeto tem de utilizar.

Nesse contexto, não deixe de aplicar essa melhoria por causa de alguns métodos extras na superclasse (ou Interface). As refatorações, muitas vezes, vão melhorar o código para uma próxima refatoração.

Outros artigos da série

Abaixo listo os artigos dessa série, com outras refatorações, que já foram liberados:

Internalizar Singleton

Mover Embelezamento Para Decorator

Substituir Condicionais que Alteram Estado por State

Introduzir Objeto Nulo

Unificar Interfaces Com Adapter

Extrair Adapter

Mover Conhecimento de Criação Para Factory

Substituir Notificações Hard-Coded Por Observer

Substituir Código de Tipo Por Classe

Extrair Parâmetro

Limitar Instanciação Com Singleton

Mover Acumulação Para Parâmetro Coletor

Compor Method

Formar Template Method

Substituir Lógica Condicional Por Strategy

Introduzir Criação Polimórfica com Factory Method

Encapsular Classes Com Factory

Encadear Construtores

Substituir Construtores Por Métodos de Criação

Fontes

Refatoração Para Padrões

Vlw.

Investir em Você é Barra de Ouro a R$ 2,00. Cadastre-se e receba grátis conteúdos Android sem precedentes!
Email inválido

Relacionado

Refatoração Para PadrõesRefatoração Para PadrõesLivros
Facebook Login, Firebase Android - Parte 5Facebook Login, Firebase Android - Parte 5Android
Google SignIn API, Firebase Android - Parte 6Google SignIn API, Firebase Android - Parte 6Android
Twitter Login (Fabric), Firebase Android - Parte 7Twitter Login (Fabric), Firebase Android - Parte 7Android

Compartilhar

Comentários Facebook

Comentários Blog

Para código / script, coloque entre [code] e [/code] para receber marcação especifica.
Forneça seu nome válido.
Forneça seu email válido.
Forneça o comentário.
Enviando, aguarde...