Refatoração de Código: Compor Method
Blog /Android /Refatoração de Código: Compor Method
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:
Padrão de Projeto: Cláusula de Guarda.
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.
Método de refatoração Internalizar Método;
Método de refatoração Extrair Método;
Método de refatoração Extrair Classe;
Motivação (Compor Method);
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.
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:
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.
Como já informado no início do artigo, dessa vez temos uma série de dicas e não passos exatos.
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():
/* Cláusula de Guarda */
if( !somenteLeitura ){
Nosso próximo passo é remover o valor (ou número) mágico 10 e colocá-lo em uma constante.
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:
private final static int VALOR_INCREMENTACAO = 10;
/* Claúsula de Guarda */
if( !somenteLeitura ) {
Object[] novosElementos = new Object[ elementos.length + VALOR_INCREMENTACAO ];
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 ).
if( capacidadeCompleta() ){
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.
if ( capacidadeCompleta() ){
crescerVetor();
private void crescerVetor(){
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:
if ( !somenteLeitura ) {
addElemento( elemento );
return tamanho + 1 > elementos.length;
private boolean addElemento( Object 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.
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.
Abaixo listo todos os artigos já liberados desta série do Blog sobre "Codificação Limpa":
código limpo - engenharia de software - kent beck - clean code - refatoração - padrões de implementação - alta performance - programador eficiente - compor method - método compor