Refatoração de Código: Extrair Parâmetro
(2527)
CategoriasAndroid, Design, Protótipo
AutorVinÃcius Thiengo
VÃdeo aulas186
Tempo15 horas
ExercÃciosSim
CertificadoSim
CategoriaEngenharia de Software
Autor(es)Vlad Khononov
EditoraAlta Books
Edição1ª
Ano2024
Páginas320
Tudo bem?
Neste artigo continuamos com a série "Refatoração de Código" com o objetivo de obter maior performance nossa como desenvolvedores de software.
Desta vez abordando um outro simples método de refatoração, mais precisamente o método: Extrair Parâmetro.
Antes de prosseguir ressalto que os artigos desta série são válidos para qualquer algoritmo de qualquer linguagem de programação que trabalhe também o paradigma Orientação a Objetos.
Alguns métodos da série também funcionam com outros paradigmas de desenvolvimento.
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:
Motivação
Para instâncias de classes que têm atributos sendo preenchidos por objetos que são criados dentro da própria instância proprietária do atributo.
Porém esses objetos são criados com valores vindos como parâmetros de construtores ou métodos.
Para o caso descrito anteriormente utiliza-se o método de refatoração proposto aqui para injetar a dependência e remover o forte acoplamento.
Forte acoplamento tem um nome sério, realmente parece expressar um problema, mas ele é mesmo um problema que deve ser levado em conta?
Sim, tão ruim quanto código duplicado.
Assuma que uma classe de seu projeto instancie, dentro dos códigos dela, uma outra classe.
Essa instância é necessária para preencher um atributo importante no processamento de objetos do tipo da classe cliente.
Agora, como exemplo, altere o construtor dessa classe instanciada, digo, todos os construtores.
Somente esse passo de atualizarão já é o suficiente para mostrar o que acontecerá com a classe cliente:
O código dela deverá ser refatorado mesmo ela não sendo alvo da refatoração, tendo em mente que a classe fornecedora somente teve o construtor alterado, nada que deveria afetar a classe cliente.
Esse é um exemplo simples que mostra como a evolução do projeto fica prejudicada devido ao forte acoplamento entre classes.
Código de exemplo
Para seguir com a apresentação do método de refatoração desse artigo, um código de domínio de problema de carros será utilizado como exemplo.
Mais precisamente, uma classe, Carro:
public class Carro {
private String modelo;
private Marca marca = new Marca();
private Motor motor;
public Carro(
String modelo,
String marca,
String tipoMotor,
int cilindradas ){
this.modelo = modelo;
this.marca.setNome( marca );
this.motor = new Motor( tipoMotor, cilindradas );
}
public void setMotor(
String tipoMotor,
int cilindradas ){
this.motor = new Motor( tipoMotor, cilindradas );
}
...
}
Note que para os atributos motor e marca as instâncias são criadas dentro do objeto proprietário.
O principal problema nesse caso é o forte acoplamento criado entre os objetos das classes Carro, Marca e Motor.
A leitura do código também fica prejudicada, pois o número de parâmetros no construtor ou método aumenta.
Mecânica
Nosso primeiro passo na aplicação do método de refatoração Extrair Parâmetro é localizar atribuições de instâncias locais a atributos do objeto.
Todas as sentenças desse tipo devem estar dentro de métodos ou construtores.
Caso alguma esteja fora, na declaração dos atributos, devemos movê-la para dentro de um método ou construtor.
Em nosso caso temos o atributo marca recebendo a instância do tipo Marca ainda na declaração dele.
Logo vamos mover esse código para o construtor de Carro:
public class Carro {
private String modelo;
private Marca marca;
private Motor motor;
public Carro(
String modelo,
String marca,
String tipoMotor,
int cilindradas ){
this.modelo = modelo;
this.marca = new Marca( marca );
this.motor = new Motor( tipoMotor, cilindradas );
}
public void setMotor(
String tipoMotor,
int cilindradas ){
this.motor = new Motor( tipoMotor, cilindradas );
}
...
}
Note que para adiantar o processo já assumi que existe na classe Marca um construtor que recebe como parâmetro de entrada uma String representando o nome da marca.
Porém o código abaixo seria perfeitamente válido:
...
public Carro(
String modelo,
String marca,
String tipoMotor,
int cilindradas ){
this.modelo = modelo;
this.marca = new Marca();
this.marca.setNome( marca );
this.motor = new Motor( tipoMotor, cilindradas );
}
...
Nosso segundo e último passo (apenas dois!) é adicionar parâmetros que terão como valor as respectivas instâncias necessárias para os atributos que estão sendo iniciados no construtor ou método da classe sendo refatorada, Carro.
Logo depois removeremos os parâmetros que não mais têm valor no objeto, os que eram utilizados para preencher as instâncias dos atributos.
Segue código de Carro atualizado:
public class Carro {
private String modelo;
private Marca marca;
private Motor motor;
public Carro(
String modelo,
Marca marca,
Motor motor ){
this.modelo = modelo;
this.marca = marca;
this.motor = motor;
}
public void setMotor( Motor motor ){
this.motor = motor;
}
}
Note que a alteração deve ser feita em construtores e métodos.
Com isso atingimos nossos objetivos aplicando o método Extrair Parâmetro.
São eles:
- Fraco acoplamento entre as dependências;
- e Melhor leitura de código.
Um código cliente, antigo, das instâncias de Carro não mais faria isso:
...
public static void main( String[] args ){
...
carro = new Carro( "720i", "BMW", "v8", 55000 );
list.add( carro );
}
...
Para então passar a trabalhar da seguinte forma:
...
public static void main( String[] args ){
...
motor = new Motor( "v8", 55000 );
marca = new Marca( "BMW" );
carro = new Carro( "720i", marca, motor );
list.add( carro );
}
...
O algoritmo mais atual do cliente de instâncias de Carro apresenta mais linhas de código.
Porém essas não apresentam perda de performance e a leitura do código fica mais intuitiva.
Então é uma substituição perfeitamente válida e que preza pela leitura, código limpo.
Conclusão
O trabalho com injeção de dependência como o método Extrair Parâmetro prega, na verdade, é uma das práticas recomendadas de código limpo, muito devido a melhora de leitura do código.
Ou seja, não somente devido ao problema de forte acoplamento.
Tenha em mente que em média 90% dos gastos com a evolução de um software é com o tempo de leitura (entendimento) dele.
A refatoração apresentada aqui é do nível daquelas que não têm contra indicação, sempre deve ser aplicada assim que enxergado o problema de forte acoplamento.
E o problema de leitura de código prejudicada? Somente enxergando ele não é o suficiente para aplicarmos o método Extrair Parâmetro?
Caso o algoritmo não apresente junto o problema de forte acoplamento, então outra refatoração é que deve ser aplicada.
Algumas vezes somente alterar os nomes de classes, métodos e variáveis, deixando o código autocomentado, ajuda em muito.
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 são listados todos os artigos já liberados desta série do Blog sobre "Codificação Limpa":
- 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;
- Unificar Interfaces;
- 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.
Comentários Facebook