Primeiras aulas do curso Refatoração em Java: Boas práticas no seu código

Refatoração em Java: Boas práticas no seu código

Primeiros passos - Introdução

Olá pessoal, tudo bem? Meu nome é Rodrigo Vieira e, no nosso curso, nós vamos ver algumas técnicas de refatoração de código, na linguagem Java, alguns de vocês podem se perguntar, mas quais são as vantagens de aprender essas técnicas de refatoração? O que eu vou ganhar com isso ou, o que o meu sistema vai ganhar com isso?

Eu posso listar algumas aqui, como legibilidade de código, ou seja, seu código vai ficar cada vez mais legível, a partir do momento que, às vezes, você tem um código muito bagunçado e difícil de ler, aplicando algumas técnicas, ele vai se tornar cada vez mais legível, o seu código vai ficar cada vez mais organizado e, quando digo mais cada vez mais organizado, o que significa isso?

Será algo do tipo, métodos cada vez menores, classes cada vez mais concisas, cada vez mais, digamos, direto ao assunto e não métodos ou classes muito longas, ao invés disso, você tem métodos mais curtos e classes mais curtas, mais concisas, as técnicas de refatoração ajudam a gente nesse sentido.

Por consequência, a partir do momento que a gente tem um código, que tá cada vez mais conciso, métodos cada vez menores, o seu sistema fica cada vez mais fica cada vez mais fácil de manter, de inserir novas funções, novas funcionalidades, mas você pode pensar, "Rodrigo, mas eu não preciso de nada disso, eu preciso, simplesmente, colocar novas características do meu sistema e fazer as minhas manutenções, eu não preciso melhorar o código".

Existem alguns programadores, bem conhecidos, da nossa área como Martin Fowler, Uncle Bob e outros, que já comentaram em diversos livros, sites, fóruns de programação, que é importante, que nós, assim como os escoteiros fazem, devemos deixar sempre melhor o lugar que nós chegamos, para que o outro venha e encontre o lugar cada vez melhor, as técnicas de refatoração ajudam muito nesse sentido.

Imagina você pegar um código, que muitas vezes está confuso, está mal escrito, então, você já deixa ele um pouquinho melhor, o próximo desenvolvedor, que for dar manutenção nele, vai encontrar esse código um pouquinho melhor e, muitas vezes, o desenvolvedor é você mesmo, então é importante a gente se preocupar, também, nesse sentido.

As técnicas de refatoração, não trazem novas funcionalidades para o seu sistema, mas, embora não traga novas funcionalidades, elas fazem com que novas funcionalidades e manutenções futuras, que vão ser feitas no seu sistema, fiquem cada vez mais fáceis, então, talvez a curto prazo, a empresa não veja muita vantagem, mas a médio e longo prazo, o sistema vai crescer cada vez e vai ficando cada vez mais consistente, mais durável, vai durar muitos e muitos anos, sem que seja necessário sua reescrita total.

Vamos embarcar, então, nessa jornada? Espero que vocês gostem.

Primeiros passos - Pequeno exemplo de refatoração

Olá pessoal, tudo bem? Conforme prometido, vamos ver alguns exemplos de código repetido, em diversos pontos, de um mesmo sistema, se nós olharmos aqui, nós temos uma classe banco e uma classe conta, a classe conta tem apenas dois métodos, onde você configura o saldo, um set saldo, e o outro método, onde você obtém o saldo da conta, bem simples.

Na classe banco, nós temos dois métodos, o método depositar e o método realizar transferência, o depositar recebe a conta e o valor a ser depositado nessa conta, a gente tem aqui, a lógica do método, para depositar um valor, um determinado valor na conta e, por último, aqui no realizar transferência, nós temos duas contas e um valor, sendo que, a conta "a", deve ter um certo valor retirado, que é esse valor que tá aqui, e a conta "c" vai receber esse valor, é uma transferência entre contas, até aí, tudo bem, bem, simples.

Só que, há situações, onde encontramos códigos repetidos aqui na classe banco, fica claro que alguém copiou e colou o código e fez algumas poucas alterações, para que o sistema funcionasse a contento, repetido ou duplicado, triplicado ou quantas vezes ele se repetir, faz com que uma possível manutenção tenha que ser feita, em todas as repetições de código.

Se a gente olhar aqui, o set saldo é utilizado pelo menos três vezes, dentro da classe banco, a classe banco chama mais de uma vez o método set saldo e chama, também, o método get saldo da classe conta várias vezes, se as repetições fossem encapsuladas num único trecho de código, a manutenção poderia ser feita num único ponto.

Não seria melhor, vejam, a gente tem aqui, se a gente reparar aqui no comportamento de set saldo, ele lê o saldo que está na conta e, depois, adiciona o valor, se a gente olhar aqui no realizar transferência, é feito uma subtração do saldo, utilizando o valor de uma conta e, depois, é acrescentando valor ao saldo da outra conta, não seria melhor a gente criar métodos, chamados "depositar", "sacar", afinal, é o que a gente está fazendo aqui na conta, a gente poderia criar métodos "depositar" na conta e "sacar", também, na conta.

Vamos ver como que ficaria? A gente abre, aqui, a conta, na classe conta, vamos criar o método "sacar", "public void sacar", você saca o valor de uma conta, então ficaria, o valor, você subtrai o valor do saldo da conta, "this.saldo = this.saldo - valor", agora, vamos criar o método "depositar", "depositar" também recebe um valor e, aqui, o saldo vai ser acrescido de um valor, "+ valor", criamos os métodos "sacar" e "depositar" lá na classe conta.

Agora, vamos chamar esses métodos, ou melhor dizendo, utilizar esses métodos dentro da classe banco, vamos, inicialmente, remover esses métodos aqui, essas chamadas de métodos, set saldo, get saldo, no caso de depositar, aqui da classe banco, é bem melhor que, ao invés de chamar, "setSaldo(c.getSaldo() + valor", a gente chamar direto o "c.depositar" que a gente criou agora, a gente passa o valor.

Como os nomes das variáveis são os mesmos, o eclipse já mostra para completar automaticamente a passagem de parâmetro aqui, do método para outro método e agora, aqui no nosso método "realizarTransferência", se a gente parar para pensar, são duas operações, uma que a gente saca valor e, aqui, a gente deposita valor, então, vamos chamar esses métodos, que a gente acabou de criar.

Aqui a gente vai sacar valor, vou substituir aqui por "sacar(valor)" e, aqui embaixo, eu chamo "depositar(valor)", a gente não pode dizer que não há nenhuma repetição de código, mas reparem que o código, agora, nós transferimos a responsabilidade de acrescentar valores, ou subtrair valores, para a classe conta, a classe banco não tem que saber como são feitas essas operações, elas são de responsabilidade da conta, o banco apenas tem que chamar os métodos responsáveis por essas operações, da classe conta.

Então, pode vir a seguinte pergunta, será que o comportamento do sistema permanece o mesmo? Vejam, quando a gente refatora código, uma coisa que a gente deve manter, é o comportamento do sistema como um todo, ou seja, por mais que a gente altere o código, ele deve responder sempre do mesmo jeito, embora, com um código diferente, na próxima aula, a gente vai ver como fazer isso, como é refatorar código, sem alterar o comportamento do sistema.

Primeiros passos - Como os testes ajudam a manter o sistema funcionando

Vamos olhar, novamente, a classe conta e a classe banco, a classe conta, como na aula anterior nós fizemos, tem agora dois métodos, "sacar" e "depositar" e a classe banco, chama esses métodos quando precisa, no depósito, quando é necessário depositar um valor numa conta, é chamado o método depositar, passando o valor como parâmetro, na realização de transferência, é um pouquinho diferente, a gente tem o saque, de um determinado valor de uma conta, e o depósito, desse mesmo valor, numa outra conta, até aí tudo bem.

Parece que, olhando assim, parece que esse código funciona, se a gente olhar de novo, talvez a gente não veja nenhum problema, pois é, se a gente parar para pensar, a gente não tem como provar que esse código funciona ou não, se ele está livre de bugs, se ele não vai ter nenhum problema, etc.

Agora, imagina se algum outro programador, resolve fazer alguma refatoração, nesse código aqui, ele vai lá e, vamos supor, no método do sacar, ele entende que não, esse sacar aqui tá errado, ou ele vai fazer uma refatoração, ou ele vai fazer alguma alteração de código, ele entende que tem alguma coisa errada e, lá no sacar, ali naquele sinal de menos, ele troca para um sinal de mais, o que pode acontecer?

Muito provavelmente não vai mais funcionar como a gente esperava, agora, imagina se esse código está sendo acessado apenas num trecho bastante acessado do sistema, se ele está sendo bastante usado dentro do sistema, tudo bem, logo alguém vai descobrir e a gente corrige rapidamente, mas imagina que esse código, aqui, é acessado somente de vez em quando, um trecho bem pouco acessado, agora, imagina se esse trecho, mesmo pouco acessado, for muito importante.

Para que, problemas como esse, não ocorram antes da gente realizar qualquer refatoração, é recomendada a escrita de testes automatizados, é importante que a gente tenha testes automatizados, que garantam que o nosso sistema não vai quebrar, com qualquer alteração que se faça, essa, aliás, é uma boa prática de programação, ela não impede os bugs de acontecerem, não existe ainda a técnica que diga que um software está 100% livre de bugs.

Mas quando você escreve testes automatizados, você diminui, grandemente, a chance de algum erro acontecer, vamos, então, escrever um teste para esse método sacar, lá no eclipse, eu vou no "default.package" que eu criei e vou dar um "new", "class", e vou criar um "ContaTest", criamos aqui um "ContaTest", vou até fechar o banco, aqui, para facilitar a leitura, vou colocar aqui, pronto, imagina a escrita de um teste para esse método sacar.

Teoricamente, eu vou ter que escrever uma instância em ação de conta, com um determinado valor, e chamar o método sacar, logo em seguida, eu vou ter que verificar se o saldo da conta condiz com o que eu espero que deveria ter lá, vamos testar isso então?

Eu vou escrever um método de teste, aqui, "public void aoSacarUmValorDeUmaContaOSaldoDeveSofrerUmaSubtracaoDesseValor()", estou dizendo que, quando ocorrer uma mudança, quando houver um saque na conta, o valor dele deve estar subtraído, exatamente, daquele valor que foi usado no saque, vamos, então, instanciar uma conta, "Conta conta = new Conta", eu passo um valor aqui qualquer de 200.

Agora, eu vou, esqueci aqui de colocar um valor, agora eu vou sacar um valor, dessa conta, "conta.sacar" um valor, vamos supor, de 50, agora, vamos escrever a assertiva do método, "assertThat", usando o assertivo do Hamcrest, "conta.getSaldo(), is(equalTo(150))", agora é só fazer os imports necessários, por último, vamos anotar com o "@test".

Escrevemos o nosso teste, se esse teste passar, a barra do JUnit, verde, deve aparecer, não é mesmo? Caso contrário, vai aparecer uma barra vermelha, com a descrição do erro, o que deveria ter retornado, o que retornou. O nosso código, se a gente olhar lá na classe conta, ele ainda está errado, então, teoricamente, esse teste não vai passar, vamos verificar isso, clico com o botão direito, mais uma vez, "Run As", "JUnit Test", coloco para rodar.

Se a gente olhar aqui, realmente não funcionou, era esperado 150, mas veio 250, ou seja, aquela alteração, que o nosso suposto amigo programador fez, acabou de introduzir um bug no nosso sistema, vamos corrigir, lá no método sacar, ao invés de ser mais, quando você saca o valor do saldo de uma conta, você deve subtrair o valor do saldo e não somar o valor, eu troco de mais para menos, salvo, mando rodar o teste, novamente, e agora o teste está rodando sem problemas.

Espero que tenham ficado claros, os motivos de se criar testes automatizados, antes de se fazer uma refatoração, é importante, aqui nós criamos o teste depois, só para provar, só para mostrar, o quanto é ruim a gente criar, ou melhor dizendo, alterar, fazer alterações no nosso código, sem testes escritos, a gente pode introduzir bugs e com maior facilidade, sem que a gente perceba muitas vezes, na próxima aula a gente já começa estudar as técnicas de refatoração. Até mais.

Sobre o curso Refatoração em Java: Boas práticas no seu código

O curso Refatoração em Java: Boas práticas no seu código possui 181 minutos de vídeos, em um total de 45 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

Plus

  • Acesso a TODOS os cursos da plataforma

    Mais de 1200 cursos completamente atualizados, com novos lançamentos todas as semanas, em Programação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

12X
R$85
à vista R$1.020
Matricule-se

Pro

  • Acesso a TODOS os cursos da plataforma

    Mais de 1200 cursos completamente atualizados, com novos lançamentos todas as semanas, em Programação, Front-end, UX & Design, Data Science, Mobile, DevOps e Inovação & Gestão.

  • Alura Challenges

    Desafios temáticos para você turbinar seu portfólio. Você aprende na prática, com exercícios e projetos que simulam o dia a dia profissional.

  • Alura Cases

    Webséries exclusivas com discussões avançadas sobre arquitetura de sistemas com profissionais de grandes corporações e startups.

  • Certificado

    Emitimos certificados para atestar que você finalizou nossos cursos e formações.

  • Alura Língua (incluindo curso Inglês para Devs)

    Estude a língua inglesa com um curso 100% focado em tecnologia e expanda seus horizontes profissionais.

12X
R$120
à vista R$1.440
Matricule-se
Conheça os Planos para Empresas

Acesso completo
durante 1 ano

Estude 24h/dia
onde e quando quiser

Novos cursos
todas as semanas