Refatoração de Código: Compor Method

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: Compor Method

Refatoração de Código: Compor Method

Vinícius Thiengo
(2653)
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

Tudo bem?

Neste artigo continuamos com a série sobre Refatoração de Código, com o propósito de se tornar um coder de alta performance.

Desta vez vamos abordar o método de refatoração Compor Method que está entre os mais simples e úteis

Diferente dos outros métodos de refatoração, o Compor Method tem dicas de refatoração e não passos específicos.

Porém, antes de prosseguir é importante que você conheça o padrão Cláusula de Guarda.

Caso ainda não conheça o padrão informado acima, aqui no Blog temos um artigo somente sobre ele.

Alias é um artigo bem pequeno, pois o Cláusula de Guarda consegue ser ainda mais simples que o Singleton:

Ressalto que apesar da categoria do artigo ser "Android", ele e todos os outros dessa série de artigos de engenharia de software podem ser utilizados em qualquer projeto que está utilizando o paradigma orientado a objetos.

Além do padrão Cláusula de Guarda ainda há outros três métodos de refatoração como pré-requisito do método proposto aqui.

Mas esses explico logo abaixo, tendo em mente que são muito simples e não necessitam de artigos somente para eles.

Antes de prosseguir, não esqueça de se inscrever na ðŸ“« lista de e-mails do Blog para receber em primeira mão todos os conteúdos exclusivos sobre desenvolvimento e codificação limpa.

A seguir os tópicos que estaremos abordando em artigo:

Método de refatoração Internalizar Método

Esse método de refatoração é aplicado quando temos um método que, a principio, somente infla nossa classe, pois está sendo utilizado apenas uma vez ou porque é resultado de uma refatoração mal feita.

Logo, o que esse método de refatoração prega é que nós developers devemos colocá-lo novamente no método que o originou ou então apenas colocá-lo dentro do método que o utiliza, nesse caso não necessariamente a origem dele.

Com isso extrairemos o código desse método não necessário e colocaremos esse código no local da chamada a ele no método cliente, que deve recebe-lo.

Método de refatoração Extrair Método

Sabe aqueles métodos com "n" linhas e condicionais e algumas vezes chamadas a outros métodos (incluindo também os construtores de classe)?

São exatamente nesses métodos que deveríamos aplicar o método de refatoração Extrair Método, para podermos colocar mais intenção em nosso método complexo, dessa forma teríamos vários métodos extraídos.

Mas com nomes que diriam o que exatamente faz o código dele, intenção.

Método de refatoração Extrair Classe

Com esse método é possível criar uma nova classe partindo de outra classe que realiza mais de uma tarefa principal, com isso criando uma melhor divisão de código no projeto.

Lembrando que um dos princípios de programação orientada a objetos é que cada classe deve ter somente uma única tarefa principal.

Esse método de refatoração é comumente aplicado em classes grandes, onde somente o tamanho delas já é um indício forte de que há mais de uma tarefa principal como responsabilidade dessas classes.

Motivação (Compor Method)

Colocando aqui um dos princípios de Kent Beck em Padrões de Implementação (2008) temos que:

"devemos primeiro programar sem padrões e técnicas de performance em código, apenas devemos resolver o problema de lógica deferido a nós em um belo e longo método."

Ok, e depois disso, depois do problema lógico resolvido?

Ai sim aplicamos alguns métodos de refatoração (ou padrões de projeto, diretamente) para colocar intenção no código, remover código repetido entre outras melhorias.

Ou seja, a motivação aqui é um código que foi finalizado, as saídas são consistentes com as entradas, porém esse ainda não passou por nenhum processo de melhoria.

Código de exemplo

O exemplo a seguir é o código de um método de uma classe de manipulação de listas.

Ele é pequeno, mas pouco indica como faz sua tarefa, apesar do nome do método ser bem descritivo.

Segue código do método add() de List:

public class List {

Object[] elementos;
int tamanho;
boolean somenteLeitura;

...
public void add( Object elemento ){

if( somenteLeitura ){
int novoTamanho = tamanho + 1;

if( novoTamanho > elementos.length ){
Object[] novosElementos = new Object[ elementos.length + 10 ];

for( int i = 0; i < tamanho; i++ ){
novosElementos[i] = elementos[i];
}

elementos = novosElementos;
}

elementos[ tamanho++ ] = elemento;
}
}
...
}

 

Em Mecânica vamos colocar mais intenção ao código melhorando principalmente a leitura dele para posteriores refatorações.

Mecânica

Como já informado no início do artigo, dessa vez temos uma série de dicas e não passos exatos.

Segue:

  • Pense pequeno: métodos compostos poucas vezes têm mais de dez linhas e em geral ficam em torno de cinco linhas de código;
  • Remova duplicação e código morto: remova código que não mais é utilizado, incluindo código dentro de comentário. Remova também código repetido, veja se o passo repetido não pode virar um método;
  • Comunique intenção: nomeie as entidades (métodos, parâmetros e variáveis) de forma que comuniquem a responsabilidade do código, evitando a necessidade de comentários;
  • Simplifique: quase um passo de meditação (sério), pois mesmo já tendo refatorado (ou não) veja como pode melhorar o código ainda mais e então melhore caso um novo caminho venha em mente;
  • Utilize o mesmo nível de detalhamento: se junto as chamadas de métodos em seu método composto também há lógica condicional complexa, então é uma boa prática colocar essa lógica condicional complexa dentro de um novo método para que o método composto tenha uma estrutura mais comunicativa quanto a tarefa dele.

Seguindo com a refatoração Compor Método, nosso primeiro passo é utilizar o padrão Cláusula de Guarda para colocar uma saída rápida em nosso código e remover o aninhamento do script principal.

Segue novo código do método add():

...
public void add( Object elemento ){

/* Cláusula de Guarda */
if( !somenteLeitura ){
return;
}

int novoTamanho = tamanho + 1;

if( novoTamanho > elementos.length ){
Object[] novosElementos = new Object[ elementos.length + 10 ];

for( int i = 0; i < tamanho; i++ ){
novosElementos[i] = elementos[i];
}

elementos = novosElementos;
}

elementos[ tamanho++ ] = elemento;
}
...

 

Nosso próximo passo é remover o valor (ou número) mágico 10 e colocá-lo em uma constante.

Número mágico?

São valores constantes no código (de qualquer tipo primitivo) que não estão dentro de tipos constantes ou variáveis.

Esse valores "soltos" são chamados de valores mágicos e podem ser um tremendo problema para manutenção se você tiver de utilizá-los mais de uma vez.

Segue código refatorado:

public class List {

private final static int VALOR_INCREMENTACAO = 10;

...
public void add( Object elemento ){

/* Claúsula de Guarda */
if( !somenteLeitura ) {
return;
}

int novoTamanho = tamanho + 1;

if( novoTamanho > elementos.length ){
Object[] novosElementos = new Object[ elementos.length + VALOR_INCREMENTACAO ];

for( int i = 0; i < tamanho; i++ ){
novosElementos[i] = elementos[i];
}

elementos = novosElementos;
}

elementos[ tamanho++ ] = elemento;
}
...
}

 

O passo seguinte é aplicar o método de refatoração Extrair Método na condicional que verifica se o vetor elementos suporta ou não mais um elemento.

Estamos falando desse condicional: if( novoTamanho > elementos.length ).

Segue código:

public class List {
...
public void add( Object elemento ){
...

if( capacidadeCompleta() ){
Object[] novosElementos = new Object[ elementos.length + VALOR_INCREMENTACAO ];

for( int i = 0; i < tamanho; i++ ){
novosElementos[i] = elementos[i];
}

elementos = novosElementos;
}

elementos[ tamanho++ ] = elemento;
}

private boolean capacidadeCompleta(){
return (tamanho + 1) > elementos.length;
}
...
}

 

Novamente, em nosso próximo passo, aplicaremos Extrair Método, dessa vez no código que aumenta o tamanho do vetor.

Segue código:

public class List {

private final static int VALOR_INCREMENTACAO = 10;
...

public void add( Object elemento ){
...

if ( capacidadeCompleta() ){
crescerVetor();
}

elementos[ tamanho++ ] = elemento;
}

private void crescerVetor(){
Object[] novosElementos = new Object[ elementos.length + VALOR_INCREMENTACAO ];

for( int i = 0; i < tamanho; i++ ){
novosElementos[i] = elementos[i];
}

elementos = novosElementos;
}
...
}

 

Para finalizar a refatoração vamos realocar a linha de código final, a que adiciona o elemento ao vetor elementos.

Essa linha vai para um método exclusivo dela, isso permitirá que nosso método composto tenha todo o corpo no mesmo nível de detalhe, com somente chamadas a métodos.

Segue código final refatorado:

public class List {

private final static int VALOR_INCREMENTACAO = 10;

Object[] elementos;
int tamanho;
boolean somenteLeitura;

public void add( Object elemento ){

if ( !somenteLeitura ) {
return;
}
if ( capacidadeCompleta() ){
crescerVetor();
}

addElemento( elemento );
}

private boolean capacidadeCompleta(){
return tamanho + 1 > elementos.length;
}

private void crescerVetor(){
Object[] novosElementos = new Object[ elementos.length + VALOR_INCREMENTACAO ];

for( int i = 0; i < tamanho; i++ ){
novosElementos[i] = elementos[i];
}

elementos = novosElementos;
}

private boolean addElemento( Object elemento ){
elementos[ tamanho++ ] = elemento;
}
...
}

 

Com isso o método add() passa mais intenção no processamento de seu algoritmo e temos alguns novos métodos que podem ainda ser aproveitados por outros métodos internos a List.

Conclusão

Nesse exemplo não tivemos nenhum problema, mas em códigos maiores pode ser que tenhamos um resultado final com vários outros pequenos métodos, deixando a leitura da classe, por parte de outros developers, complicada.

Logo nesse caso é preciso verificar se não podemos aplicar o método de refatoração Extrair Classe, onde uma nova classe seria criada com parte dos métodos da classe atual.

Outra problemática que pode ocorrer é um novo método, auxiliar ao método composto, com um corpo de processamento grande e não realizando somente uma tarefa, deixando o código dele confuso.

Nesse caso aplica-se o método de refatoração Internalizar Método para voltar com o corpo desse método para o método original e então se desfazendo dele.

Dessa forma é refatorar novamente (aplicando Extrair Método, por exemplo) buscando um novo caminho.

A criação de mais de um método é bem provável que seja esse novo caminho.

Algo que pode vir a sua mente é:

Esses métodos pequenos criam mais chamadas em meu código acabando com o desempenho.

Nesse caso é prudente utilizar um medidor de desempenhos junto a linguagem que você escolheu para saber onde realmente é o gargalo.

Pois modificar o código atacando o trecho errado vai trazer somente perda de tempo.

Então é isso.

Por fim, não deixe de se inscrever na 📩 lista de e-mails do Blog para receber os conteúdos de desenvolvimento e codificação limpa exclusivos, em primeira mão e também...

... na versão em PDF (versão liberada somente para os inscritos da lista de e-mails).

Abraço.

Outros artigos da série

Abaixo listo todos os artigos já liberados desta série do Blog sobre "Codificação Limpa":

Fontes

Refatoração Para Padrões

Padrões de Implementação

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

Código Limpo - Habilidades Práticas do Agile SoftwareCódigo Limpo - Habilidades Práticas do Agile SoftwareLivros
O Codificador Limpo - Um código de conduto para programadores profissionaisO Codificador Limpo - Um código de conduto para programadores profissionaisLivros
Padrões de Implementação - Um Catálogo de Padrões Indispensável Para o Dia a Dia do ProgramadorPadrões de Implementação - Um Catálogo de Padrões Indispensável Para o Dia a Dia do ProgramadorLivros
Refatoração Para PadrõesRefatoração Para PadrõesLivros

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...