SlideShare uma empresa Scribd logo
1 de 35
Baixar para ler offline
COMBATENDO CODE SMELLS EM
APLICAÇÕES JAVA
Trilha Java
Emmanuel Neri
EMMANUEL NERI
‣ Mestre em Desenvolvimento de Tecnologia
‣ Desenvolvedor desde 2010
‣ Atualmente desenvolvedor back-end na Navita
)(
PROBLEMA
O que são code smells?
COMO RESOLVER?
Como evitar códigos ruins no dia a dia?
CULTURAL
Reuso
Abstração
Código limpo
Encapsulamento
PRATICAR
POR ONDE COMEÇAR?
LEGIBILIDADE
‣ Nome claros
‣ Nome que revelem seu propósito
‣ Nomes pronunciáveis
‣ Nomes passíveis de busca
LEITURA DO CÓDIGO
BigDecimal valor = BigDecimal.ZERO;
for(Conta x : lista) {
for(ItemConta y : x.getItens()) {
if(y.getValor() != null) {
valor = valor.add(y.getValor());
}
}
BigDecimal media = valor.divide(BigDecimal.valueOf(lista.size()));
LEITURA DO CÓDIGO
BigDecimal valor = BigDecimal.ZERO;
for(Conta x : lista) {
for(ItemConta y : x.getItens()) {
if(y.getValor() != null) {
valor = valor.add(y.getValor());
}
}
BigDecimal media = valor.divide(BigDecimal.valueOf(lista.size()));
LEITURA DO CÓDIGO
BigDecimal valorTotal = BigDecimal.ZERO;
for(Conta conta : contas) {
for(ItemConta itemConta : conta.getItens()) {
if(itemConta.getValor() != null) {
valorTotal = valorTotal.add(itemConta.getValor());
}
}
}
BigDecimal quantidadeDeContas = BigDecimal.valueOf(contas.size());
BigDecimal media = valorTotal.divide(quantidadeDeContas);
S O L I D
SINGLE
RESPONSIBILITY
PRINCIPLE
OPEN / CLOSE
PRINCIPLE
LISKOVS
SUBSTITUTION
PRINCIPLE
INTERFACE
SEGREGATION
PRINCIPLE
DEPENDENCY
INVERSION
PRINCIPLE
SRP OCP LSP ISP DIP
O
"A class should have only one reason to change."
ACRÔNIMO
EXTRAINDO EM MÉTODOS
public SumarioConta sumarizarConta(List<Conta> contas) {
final BigDecimal valorTotal = calcularValorTotal(contas);
final BigDecimal quantidadeDeContas = getQuantidadeDeContas(contas);
final BigDecimal media = CalculoUtil.media(valorTotal, quantidadeDeContas);
return new SumarioConta(valorTotal, media);
}
private BigDecimal calcularValorTotal(List<Conta> contas) {
return contas.stream()
.map(Conta::getValorTotal)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
private BigDecimal getQuantidadeDeContas(List<Conta> contas) {
return BigDecimal.valueOf(contas.size());
}
TAMANHO DE CÓDIGO
‣ Classes
DUPLICAÇÃO DE CÓDIGO
public class ContaService {
public BigDecimal calcularDesconto(Conta conta) {
....
}
}
public class ItemContaService {
public BigDecimal calcularDesconto(Conta conta) {
....
}
}
public class Conta {
public BigDecimal calcularDesconto() {
....
}
}
DUPLICAÇÃO DE CÓDIGO
private static final int ESCALA_FINANCEIRA = 2;
private static final int ESCALA_CONTABIL = 6;
public BigDecimal calcularMediaFinanceira(BigDecimal total,
BigDecimal quantidade) {
return total.divide(quantidade, ESCALA_FINANCEIRA, HALF_EVEN);
}
public BigDecimal calcularMediaContabil(BigDecimal total,
BigDecimal quantidade) {
return total.divide(quantidade, ESCALA_CONTABIL, HALF_EVEN);
}
DUPLICAÇÃO DE CÓDIGO
private static final int ESCALA_FINANCEIRA = 2;
private static final int ESCALA_CONTABIL = 6;
public BigDecimal calcularMediaFinanceira(BigDecimal total,
BigDecimal quantidade) {
return total.divide(quantidade, ESCALA_FINANCEIRA, HALF_EVEN);
}
public BigDecimal calcularMediaContabil(BigDecimal total,
BigDecimal quantidade) {
return total.divide(quantidade, ESCALA_CONTABIL, HALF_EVEN);
}
DUPLICAÇÃO DE CÓDIGO
private static final int ESCALA_FINANCEIRA = 2;
private static final int ESCALA_CONTABIL = 6;
public BigDecimal calcularMediaFinanceira(BigDecimal total,
BigDecimal quantidade) {
return divide(total, quantidade, ESCALA_FINANCEIRA);
}
public BigDecimal calcularMediaContabil(BigDecimal total,
BigDecimal quantidade) {
return divide(total, quantidade, ESCALA_CONTABIL);
}
private BigDecimal divide(BigDecimal total, BigDecimal quantidade,
int escala) {
return total.divide(quantidade, escala, RoundingMode.HALF_EVEN);
}
EXCESSO DE COMPLEXIDADE
public BigDecimal calcular(Conta conta) {
if() {
if() {
}
} else if() {
} else {
if() {
} else {
}
}
}
‣ KISS ("keep it small and simple”)
public class Fatura {
private TipoFatura tipoFatura;
private Integer quantidade;
private Integer duracao;
private Integer bytes;
private BigDecimal valorUnitario;
public BigDecimal getValorTotal() {
if(tipoFatura == TipoFatura.VOZ) {
return valorUnitario.multiply(BigDecimal.valueOf(duracao));
} else if(tipoFatura == TipoFatura.DADOS) {
return valorUnitario.multiply(BigDecimal.valueOf(bytes));
} else {
return valorUnitario.multiply(BigDecimal.valueOf(quantidade));
}
}
}
public class Fatura {
private TipoFatura tipoFatura;
private Integer quantidade;
private Integer duracao;
private Integer bytes;
private BigDecimal valorUnitario;
public BigDecimal getValorTotal() {
if(tipoFatura == TipoFatura.VOZ) {
return valorUnitario.multiply(BigDecimal.valueOf(duracao));
} else if(tipoFatura == TipoFatura.DADOS) {
return valorUnitario.multiply(BigDecimal.valueOf(bytes));
} else {
return valorUnitario.multiply(BigDecimal.valueOf(quantidade));
}
}
}
public enum TipoFatura {
VOZ {
@Override
public BigDecimal calcularValorTotal(Fatura fatura) {
return multiply(fatura.getValorUnitario(), fatura.getDuracao());
}
},
DADOS {
@Override
public BigDecimal calcularValorTotal(Fatura fatura) {
return multiply(fatura.getValorUnitario(), fatura.getBytes());
}
}
public abstract BigDecimal calcularValorTotal(Fatura fatura);
}
public BigDecimal getValorTotal() {
return tipoFatura.calcularValorTotal(this);
}
PRINCIPIO DE ABERTO / FECHADO
"Software entities (classes, modules, functions, etc.) should be
open for extension, but closed for modification"
O - OPEN / CLOSE PRINCIPLE
public BigDecimal getValorTotal() {
if(tipoFatura == TipoFatura.VOZ) {
return valorUnitario.multiply(BigDecimal.valueOf(duracao));
} else if(tipoFatura == TipoFatura.DADOS) {
return valorUnitario.multiply(BigDecimal.valueOf(bytes));
} else {
return valorUnitario.multiply(BigDecimal.valueOf(quantidade));
}
}
INVEJOSO
public class ContaService {
public void resumir(Conta conta) {
final BigDecimal valorTotal = conta.getItens().stream()
.map(item -> item.getValorUnitario()
.multiply(item.getMinutos()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
final BigDecimal quantidadeDeMinutos = conta.getItens().stream()
.map(ItemConta::getMinutos)
.reduce(BigDecimal.ZERO, BigDecimal::add);
final int quantidadeDeItensNaConta = conta.getItens().size();
...
}
}
INVEJOSO
public class ContaService {
public void resumir(Conta conta) {
final BigDecimal valorTotal = conta.getItens().stream()
.map(item -> item.getValorUnitario()
.multiply(item.getMinutos()))
.reduce(BigDecimal.ZERO, BigDecimal::add);
final BigDecimal quantidadeDeMinutos = conta.getItens().stream()
.map(ItemConta::getMinutos)
.reduce(BigDecimal.ZERO, BigDecimal::add);
final int quantidadeDeItensNaConta = conta.getItens().size();
...
}
}
FEATURE ENVY
public class ContaService {
public void resumir(Conta conta) {
final BigDecimal valorTotal = conta.calcularValorTotal();
final BigDecimal quantidadeDeMinutos =
conta.calcularQuantidadeDeMinutos();
final BigDecimal quantidadeDeItensNaConta =
conta.getQuantidadeDeItensNaConta();
...
}
}
NÍVEL DE MÉTODO
‣ Muitos parâmetros
public List<Conta> buscar(LocalDate dataInicio, LocalDate dataFim,
String cliente, String identificador,
String descricao) {
}
public List<Conta> buscar(ContaFiltroTO contaFiltro) {
}
NÍVEL DE MÉTODO
‣ Parâmetros de saída
public void pagarConta(Conta conta) {
conta.setStatus(StatusConta.PAGA);
}
conta.pagar();
NÍVEL DE MÉTODO
‣ Parâmetros lógicos
public void pagar(boolean isAtrasada, boolean isNotificarPagamento) {
if(isAtrasada) {
conta.pagaAtrasada();
} else {
conta.pagar();
}
if(isNotificarPagamento) {
notificarPagamento();
}
}
public void pagarAtrasada() { }
public void pagarNoPrazo() { }
public void notificarPagamento() { }
OUTROS
‣ Excessivo retorno de dados
‣ Lazy class
‣ Intimidade inapropriada
‣ Uso de Switch
‣ Refused bequest (Liskov Substitution Principle)
‣ Atributos de classe temporários
‣ Data clumps
‣ Dead code
‣ ….
FERRAMENTAS
‣ SonarQube
‣ FindBugs
‣ IDEs
DASHBOARD SONAR
https://github.com/emmanuelneri/productivity-with-spring/blob/master/pom.xml#L80
USANDO SONAR
RECOMENDAÇÃO
OBRIGADO
emmanuelnerisouza@gmail.com
https://github.com/emmanuelneri
@emmanuelnerii
www.emmanuelneri.com.br
“VOCÊ SEMPRE DEVE DEIXAR O LUGAR
MAIS LIMPO DO QUE ENCONTROU”

Mais conteúdo relacionado

Destaque

O comparativo de arquiteturas de software monolíticas em relação a arquitetur...
O comparativo de arquiteturas de software monolíticas em relação a arquitetur...O comparativo de arquiteturas de software monolíticas em relação a arquitetur...
O comparativo de arquiteturas de software monolíticas em relação a arquitetur...Emmanuel Neri
 
Desenvolvimento baseado em componentes com JSF
Desenvolvimento baseado em componentes com JSFDesenvolvimento baseado em componentes com JSF
Desenvolvimento baseado em componentes com JSFEmmanuel Neri
 
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVCConstruindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVCEmmanuel Neri
 
Jett: Exporte Excel do jeito que seu cliente sempre sonhou
Jett: Exporte Excel do jeito que seu cliente sempre sonhouJett: Exporte Excel do jeito que seu cliente sempre sonhou
Jett: Exporte Excel do jeito que seu cliente sempre sonhouEmmanuel Neri
 
Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...
Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...
Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...Emmanuel Neri
 
Criando uma arquitetura escalável para processamento de arquivos com micro s...
Criando uma arquitetura escalável para processamento de arquivos com micro s...Criando uma arquitetura escalável para processamento de arquivos com micro s...
Criando uma arquitetura escalável para processamento de arquivos com micro s...Emmanuel Neri
 
A Cultura do Home Office
A Cultura do Home OfficeA Cultura do Home Office
A Cultura do Home OfficeEmmanuel Neri
 
O Impacto da arquitetura de Micro Serviços nas soluções de software
O Impacto da arquitetura de Micro Serviços nas soluções de softwareO Impacto da arquitetura de Micro Serviços nas soluções de software
O Impacto da arquitetura de Micro Serviços nas soluções de softwareEmmanuel Neri
 
A trilogia Spring MVC + Spring Data + AngularJS
A trilogia  Spring MVC + Spring Data + AngularJSA trilogia  Spring MVC + Spring Data + AngularJS
A trilogia Spring MVC + Spring Data + AngularJSEmmanuel Neri
 

Destaque (9)

O comparativo de arquiteturas de software monolíticas em relação a arquitetur...
O comparativo de arquiteturas de software monolíticas em relação a arquitetur...O comparativo de arquiteturas de software monolíticas em relação a arquitetur...
O comparativo de arquiteturas de software monolíticas em relação a arquitetur...
 
Desenvolvimento baseado em componentes com JSF
Desenvolvimento baseado em componentes com JSFDesenvolvimento baseado em componentes com JSF
Desenvolvimento baseado em componentes com JSF
 
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVCConstruindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
Construindo APIs de forma produtiva com Spring Boot, Spring Data e Spring MVC
 
Jett: Exporte Excel do jeito que seu cliente sempre sonhou
Jett: Exporte Excel do jeito que seu cliente sempre sonhouJett: Exporte Excel do jeito que seu cliente sempre sonhou
Jett: Exporte Excel do jeito que seu cliente sempre sonhou
 
Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...
Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...
Microservices: Mais que uma arquitetura de software, uma filosofia de desenvo...
 
Criando uma arquitetura escalável para processamento de arquivos com micro s...
Criando uma arquitetura escalável para processamento de arquivos com micro s...Criando uma arquitetura escalável para processamento de arquivos com micro s...
Criando uma arquitetura escalável para processamento de arquivos com micro s...
 
A Cultura do Home Office
A Cultura do Home OfficeA Cultura do Home Office
A Cultura do Home Office
 
O Impacto da arquitetura de Micro Serviços nas soluções de software
O Impacto da arquitetura de Micro Serviços nas soluções de softwareO Impacto da arquitetura de Micro Serviços nas soluções de software
O Impacto da arquitetura de Micro Serviços nas soluções de software
 
A trilogia Spring MVC + Spring Data + AngularJS
A trilogia  Spring MVC + Spring Data + AngularJSA trilogia  Spring MVC + Spring Data + AngularJS
A trilogia Spring MVC + Spring Data + AngularJS
 

Semelhante a Combatendo code smells em aplicações Java

Artesanato de software
Artesanato de softwareArtesanato de software
Artesanato de softwareEdson Yanaga
 
Android DevConference - SOLID no Android
Android DevConference - SOLID no AndroidAndroid DevConference - SOLID no Android
Android DevConference - SOLID no AndroidiMasters
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaEduardo Bregaida
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Luis Gustavo Almeida
 
Programação orientada a objetos em delphi
Programação orientada a objetos em delphiProgramação orientada a objetos em delphi
Programação orientada a objetos em delphiHelder Lopes
 
Semana 10: Encapsulação, cópia de instâncias, igualdade de instâncias
Semana 10: Encapsulação, cópia de instâncias, igualdade de instânciasSemana 10: Encapsulação, cópia de instâncias, igualdade de instâncias
Semana 10: Encapsulação, cópia de instâncias, igualdade de instânciasManuel Menezes de Sequeira
 
Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Renato Haddad
 
Design Patterns na Programação de Jogo
Design Patterns na Programação de JogoDesign Patterns na Programação de Jogo
Design Patterns na Programação de JogoBruno Cicanci
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - FlisolLeonn Leite
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dadosHenrique Fernandes
 
Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02thomasdacosta
 
[CLPE] Design patterns com c#
[CLPE] Design patterns com c#[CLPE] Design patterns com c#
[CLPE] Design patterns com c#Felipe Pimentel
 
Atividades e Intenções (Android)
Atividades e Intenções (Android)Atividades e Intenções (Android)
Atividades e Intenções (Android)Natanael Fonseca
 

Semelhante a Combatendo code smells em aplicações Java (20)

Artesanato de software
Artesanato de softwareArtesanato de software
Artesanato de software
 
TDD e Clean Code
TDD e Clean CodeTDD e Clean Code
TDD e Clean Code
 
Android DevConference - SOLID no Android
Android DevConference - SOLID no AndroidAndroid DevConference - SOLID no Android
Android DevConference - SOLID no Android
 
Clean code
Clean codeClean code
Clean code
 
Refatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completaRefatoração de código com Capitão Nascimento versão completa
Refatoração de código com Capitão Nascimento versão completa
 
Solid
SolidSolid
Solid
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
Dip the dependency inversion principle
Dip   the dependency inversion principleDip   the dependency inversion principle
Dip the dependency inversion principle
 
DDD > Experiências
DDD > ExperiênciasDDD > Experiências
DDD > Experiências
 
Programação orientada a objetos em delphi
Programação orientada a objetos em delphiProgramação orientada a objetos em delphi
Programação orientada a objetos em delphi
 
Semana 10: Encapsulação, cópia de instâncias, igualdade de instâncias
Semana 10: Encapsulação, cópia de instâncias, igualdade de instânciasSemana 10: Encapsulação, cópia de instâncias, igualdade de instâncias
Semana 10: Encapsulação, cópia de instâncias, igualdade de instâncias
 
Dip the dependency inversion principle
Dip   the dependency inversion principleDip   the dependency inversion principle
Dip the dependency inversion principle
 
Dip the dependency inversion principle
Dip   the dependency inversion principleDip   the dependency inversion principle
Dip the dependency inversion principle
 
Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6Palestra Novidades da linguagem C# 6
Palestra Novidades da linguagem C# 6
 
Design Patterns na Programação de Jogo
Design Patterns na Programação de JogoDesign Patterns na Programação de Jogo
Design Patterns na Programação de Jogo
 
Programando Melhor - Flisol
Programando Melhor - FlisolProgramando Melhor - Flisol
Programando Melhor - Flisol
 
Como conectar programas em linguagem java a bases de dados
Como conectar programas em linguagem java  a bases de dadosComo conectar programas em linguagem java  a bases de dados
Como conectar programas em linguagem java a bases de dados
 
Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02Programação Estruturada 2 - Aula 02
Programação Estruturada 2 - Aula 02
 
[CLPE] Design patterns com c#
[CLPE] Design patterns com c#[CLPE] Design patterns com c#
[CLPE] Design patterns com c#
 
Atividades e Intenções (Android)
Atividades e Intenções (Android)Atividades e Intenções (Android)
Atividades e Intenções (Android)
 

Mais de Emmanuel Neri

Arquitetura orientada a eventos
Arquitetura orientada a eventosArquitetura orientada a eventos
Arquitetura orientada a eventosEmmanuel Neri
 
Iniciando com Docker
Iniciando com DockerIniciando com Docker
Iniciando com DockerEmmanuel Neri
 
Arquitetura reativa, a solução para os microserviços?
Arquitetura reativa,  a solução para os microserviços?Arquitetura reativa,  a solução para os microserviços?
Arquitetura reativa, a solução para os microserviços?Emmanuel Neri
 
Preparando nossas aplicações para falharem com feature toggle e configurações...
Preparando nossas aplicações para falharem com feature toggle e configurações...Preparando nossas aplicações para falharem com feature toggle e configurações...
Preparando nossas aplicações para falharem com feature toggle e configurações...Emmanuel Neri
 
Preparando nossa aplicação para falhar com feature toggle e configurações dis...
Preparando nossa aplicação para falhar com feature toggle e configurações dis...Preparando nossa aplicação para falhar com feature toggle e configurações dis...
Preparando nossa aplicação para falhar com feature toggle e configurações dis...Emmanuel Neri
 
Combatendo code smells em Java
Combatendo code smells em Java Combatendo code smells em Java
Combatendo code smells em Java Emmanuel Neri
 
Configurações distribuídas com Spring Cloud Config
Configurações distribuídas com Spring Cloud ConfigConfigurações distribuídas com Spring Cloud Config
Configurações distribuídas com Spring Cloud ConfigEmmanuel Neri
 
Lidando com desafios dos microserviços com a stack Spring Cloud Netflix
Lidando com desafios dos microserviços com a stack Spring Cloud NetflixLidando com desafios dos microserviços com a stack Spring Cloud Netflix
Lidando com desafios dos microserviços com a stack Spring Cloud NetflixEmmanuel Neri
 
Aplicação da arquitetura de micro serviços em softwares corporativos
Aplicação da arquitetura de micro serviços em softwares corporativosAplicação da arquitetura de micro serviços em softwares corporativos
Aplicação da arquitetura de micro serviços em softwares corporativosEmmanuel Neri
 
Análise e Design - RUP
Análise e Design - RUPAnálise e Design - RUP
Análise e Design - RUPEmmanuel Neri
 
Solução técnica - CMMI nível 3
Solução técnica - CMMI nível 3Solução técnica - CMMI nível 3
Solução técnica - CMMI nível 3Emmanuel Neri
 

Mais de Emmanuel Neri (13)

Arquitetura orientada a eventos
Arquitetura orientada a eventosArquitetura orientada a eventos
Arquitetura orientada a eventos
 
Iniciando com Docker
Iniciando com DockerIniciando com Docker
Iniciando com Docker
 
Arquitetura reativa, a solução para os microserviços?
Arquitetura reativa,  a solução para os microserviços?Arquitetura reativa,  a solução para os microserviços?
Arquitetura reativa, a solução para os microserviços?
 
Preparando nossas aplicações para falharem com feature toggle e configurações...
Preparando nossas aplicações para falharem com feature toggle e configurações...Preparando nossas aplicações para falharem com feature toggle e configurações...
Preparando nossas aplicações para falharem com feature toggle e configurações...
 
Preparando nossa aplicação para falhar com feature toggle e configurações dis...
Preparando nossa aplicação para falhar com feature toggle e configurações dis...Preparando nossa aplicação para falhar com feature toggle e configurações dis...
Preparando nossa aplicação para falhar com feature toggle e configurações dis...
 
Combatendo code smells em Java
Combatendo code smells em Java Combatendo code smells em Java
Combatendo code smells em Java
 
Configurações distribuídas com Spring Cloud Config
Configurações distribuídas com Spring Cloud ConfigConfigurações distribuídas com Spring Cloud Config
Configurações distribuídas com Spring Cloud Config
 
Lidando com desafios dos microserviços com a stack Spring Cloud Netflix
Lidando com desafios dos microserviços com a stack Spring Cloud NetflixLidando com desafios dos microserviços com a stack Spring Cloud Netflix
Lidando com desafios dos microserviços com a stack Spring Cloud Netflix
 
Trabalho Remoto
Trabalho RemotoTrabalho Remoto
Trabalho Remoto
 
Aplicação da arquitetura de micro serviços em softwares corporativos
Aplicação da arquitetura de micro serviços em softwares corporativosAplicação da arquitetura de micro serviços em softwares corporativos
Aplicação da arquitetura de micro serviços em softwares corporativos
 
Análise e Design - RUP
Análise e Design - RUPAnálise e Design - RUP
Análise e Design - RUP
 
Solução técnica - CMMI nível 3
Solução técnica - CMMI nível 3Solução técnica - CMMI nível 3
Solução técnica - CMMI nível 3
 
Jenkins
JenkinsJenkins
Jenkins
 

Combatendo code smells em aplicações Java

  • 1. COMBATENDO CODE SMELLS EM APLICAÇÕES JAVA Trilha Java Emmanuel Neri
  • 2. EMMANUEL NERI ‣ Mestre em Desenvolvimento de Tecnologia ‣ Desenvolvedor desde 2010 ‣ Atualmente desenvolvedor back-end na Navita )(
  • 3. PROBLEMA O que são code smells?
  • 4. COMO RESOLVER? Como evitar códigos ruins no dia a dia?
  • 8. LEGIBILIDADE ‣ Nome claros ‣ Nome que revelem seu propósito ‣ Nomes pronunciáveis ‣ Nomes passíveis de busca
  • 9. LEITURA DO CÓDIGO BigDecimal valor = BigDecimal.ZERO; for(Conta x : lista) { for(ItemConta y : x.getItens()) { if(y.getValor() != null) { valor = valor.add(y.getValor()); } } BigDecimal media = valor.divide(BigDecimal.valueOf(lista.size()));
  • 10. LEITURA DO CÓDIGO BigDecimal valor = BigDecimal.ZERO; for(Conta x : lista) { for(ItemConta y : x.getItens()) { if(y.getValor() != null) { valor = valor.add(y.getValor()); } } BigDecimal media = valor.divide(BigDecimal.valueOf(lista.size()));
  • 11. LEITURA DO CÓDIGO BigDecimal valorTotal = BigDecimal.ZERO; for(Conta conta : contas) { for(ItemConta itemConta : conta.getItens()) { if(itemConta.getValor() != null) { valorTotal = valorTotal.add(itemConta.getValor()); } } } BigDecimal quantidadeDeContas = BigDecimal.valueOf(contas.size()); BigDecimal media = valorTotal.divide(quantidadeDeContas);
  • 12. S O L I D SINGLE RESPONSIBILITY PRINCIPLE OPEN / CLOSE PRINCIPLE LISKOVS SUBSTITUTION PRINCIPLE INTERFACE SEGREGATION PRINCIPLE DEPENDENCY INVERSION PRINCIPLE SRP OCP LSP ISP DIP O "A class should have only one reason to change." ACRÔNIMO
  • 13. EXTRAINDO EM MÉTODOS public SumarioConta sumarizarConta(List<Conta> contas) { final BigDecimal valorTotal = calcularValorTotal(contas); final BigDecimal quantidadeDeContas = getQuantidadeDeContas(contas); final BigDecimal media = CalculoUtil.media(valorTotal, quantidadeDeContas); return new SumarioConta(valorTotal, media); } private BigDecimal calcularValorTotal(List<Conta> contas) { return contas.stream() .map(Conta::getValorTotal) .reduce(BigDecimal.ZERO, BigDecimal::add); } private BigDecimal getQuantidadeDeContas(List<Conta> contas) { return BigDecimal.valueOf(contas.size()); }
  • 15. DUPLICAÇÃO DE CÓDIGO public class ContaService { public BigDecimal calcularDesconto(Conta conta) { .... } } public class ItemContaService { public BigDecimal calcularDesconto(Conta conta) { .... } } public class Conta { public BigDecimal calcularDesconto() { .... } }
  • 16. DUPLICAÇÃO DE CÓDIGO private static final int ESCALA_FINANCEIRA = 2; private static final int ESCALA_CONTABIL = 6; public BigDecimal calcularMediaFinanceira(BigDecimal total, BigDecimal quantidade) { return total.divide(quantidade, ESCALA_FINANCEIRA, HALF_EVEN); } public BigDecimal calcularMediaContabil(BigDecimal total, BigDecimal quantidade) { return total.divide(quantidade, ESCALA_CONTABIL, HALF_EVEN); }
  • 17. DUPLICAÇÃO DE CÓDIGO private static final int ESCALA_FINANCEIRA = 2; private static final int ESCALA_CONTABIL = 6; public BigDecimal calcularMediaFinanceira(BigDecimal total, BigDecimal quantidade) { return total.divide(quantidade, ESCALA_FINANCEIRA, HALF_EVEN); } public BigDecimal calcularMediaContabil(BigDecimal total, BigDecimal quantidade) { return total.divide(quantidade, ESCALA_CONTABIL, HALF_EVEN); }
  • 18. DUPLICAÇÃO DE CÓDIGO private static final int ESCALA_FINANCEIRA = 2; private static final int ESCALA_CONTABIL = 6; public BigDecimal calcularMediaFinanceira(BigDecimal total, BigDecimal quantidade) { return divide(total, quantidade, ESCALA_FINANCEIRA); } public BigDecimal calcularMediaContabil(BigDecimal total, BigDecimal quantidade) { return divide(total, quantidade, ESCALA_CONTABIL); } private BigDecimal divide(BigDecimal total, BigDecimal quantidade, int escala) { return total.divide(quantidade, escala, RoundingMode.HALF_EVEN); }
  • 19. EXCESSO DE COMPLEXIDADE public BigDecimal calcular(Conta conta) { if() { if() { } } else if() { } else { if() { } else { } } } ‣ KISS ("keep it small and simple”)
  • 20. public class Fatura { private TipoFatura tipoFatura; private Integer quantidade; private Integer duracao; private Integer bytes; private BigDecimal valorUnitario; public BigDecimal getValorTotal() { if(tipoFatura == TipoFatura.VOZ) { return valorUnitario.multiply(BigDecimal.valueOf(duracao)); } else if(tipoFatura == TipoFatura.DADOS) { return valorUnitario.multiply(BigDecimal.valueOf(bytes)); } else { return valorUnitario.multiply(BigDecimal.valueOf(quantidade)); } } }
  • 21. public class Fatura { private TipoFatura tipoFatura; private Integer quantidade; private Integer duracao; private Integer bytes; private BigDecimal valorUnitario; public BigDecimal getValorTotal() { if(tipoFatura == TipoFatura.VOZ) { return valorUnitario.multiply(BigDecimal.valueOf(duracao)); } else if(tipoFatura == TipoFatura.DADOS) { return valorUnitario.multiply(BigDecimal.valueOf(bytes)); } else { return valorUnitario.multiply(BigDecimal.valueOf(quantidade)); } } }
  • 22. public enum TipoFatura { VOZ { @Override public BigDecimal calcularValorTotal(Fatura fatura) { return multiply(fatura.getValorUnitario(), fatura.getDuracao()); } }, DADOS { @Override public BigDecimal calcularValorTotal(Fatura fatura) { return multiply(fatura.getValorUnitario(), fatura.getBytes()); } } public abstract BigDecimal calcularValorTotal(Fatura fatura); } public BigDecimal getValorTotal() { return tipoFatura.calcularValorTotal(this); }
  • 23. PRINCIPIO DE ABERTO / FECHADO "Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification" O - OPEN / CLOSE PRINCIPLE public BigDecimal getValorTotal() { if(tipoFatura == TipoFatura.VOZ) { return valorUnitario.multiply(BigDecimal.valueOf(duracao)); } else if(tipoFatura == TipoFatura.DADOS) { return valorUnitario.multiply(BigDecimal.valueOf(bytes)); } else { return valorUnitario.multiply(BigDecimal.valueOf(quantidade)); } }
  • 24. INVEJOSO public class ContaService { public void resumir(Conta conta) { final BigDecimal valorTotal = conta.getItens().stream() .map(item -> item.getValorUnitario() .multiply(item.getMinutos())) .reduce(BigDecimal.ZERO, BigDecimal::add); final BigDecimal quantidadeDeMinutos = conta.getItens().stream() .map(ItemConta::getMinutos) .reduce(BigDecimal.ZERO, BigDecimal::add); final int quantidadeDeItensNaConta = conta.getItens().size(); ... } }
  • 25. INVEJOSO public class ContaService { public void resumir(Conta conta) { final BigDecimal valorTotal = conta.getItens().stream() .map(item -> item.getValorUnitario() .multiply(item.getMinutos())) .reduce(BigDecimal.ZERO, BigDecimal::add); final BigDecimal quantidadeDeMinutos = conta.getItens().stream() .map(ItemConta::getMinutos) .reduce(BigDecimal.ZERO, BigDecimal::add); final int quantidadeDeItensNaConta = conta.getItens().size(); ... } }
  • 26. FEATURE ENVY public class ContaService { public void resumir(Conta conta) { final BigDecimal valorTotal = conta.calcularValorTotal(); final BigDecimal quantidadeDeMinutos = conta.calcularQuantidadeDeMinutos(); final BigDecimal quantidadeDeItensNaConta = conta.getQuantidadeDeItensNaConta(); ... } }
  • 27. NÍVEL DE MÉTODO ‣ Muitos parâmetros public List<Conta> buscar(LocalDate dataInicio, LocalDate dataFim, String cliente, String identificador, String descricao) { } public List<Conta> buscar(ContaFiltroTO contaFiltro) { }
  • 28. NÍVEL DE MÉTODO ‣ Parâmetros de saída public void pagarConta(Conta conta) { conta.setStatus(StatusConta.PAGA); } conta.pagar();
  • 29. NÍVEL DE MÉTODO ‣ Parâmetros lógicos public void pagar(boolean isAtrasada, boolean isNotificarPagamento) { if(isAtrasada) { conta.pagaAtrasada(); } else { conta.pagar(); } if(isNotificarPagamento) { notificarPagamento(); } } public void pagarAtrasada() { } public void pagarNoPrazo() { } public void notificarPagamento() { }
  • 30. OUTROS ‣ Excessivo retorno de dados ‣ Lazy class ‣ Intimidade inapropriada ‣ Uso de Switch ‣ Refused bequest (Liskov Substitution Principle) ‣ Atributos de classe temporários ‣ Data clumps ‣ Dead code ‣ ….

Notas do Editor

  1. Visando um código limpo Para fácil manutenção
  2. propícios a erros Causa confusão Difícil compreensão Ruins para manutenibilidade
  3. Pensar a todo momento Conhecer as boas práticas Independente do tamanho de código Até que código ruins nos incomode
  4. E colocar em prática! "Não da tempo”, não cabe nada tarefa
  5. Apagar tudo e fazer de novo? Precisamos de testes
  6. Não impacta no resultado, apenas na apresentação Code = Leitura de um livro (Clean code)
  7. Concordam não é uma leitura fluente?
  8. Concordam não é uma leitura fluente? Exige interpretação
  9. Concordam que tem uma leitura melhor? Tem fluência
  10. S: Uma classe só deve ter uma responsabilidade O: Nossas entidades devem ser abertas para evoluções mais fechadas para alterações L: Classes derivadas devem poder ser substituídas por suas classes base I: Entidades não devem ser forçados a depender de métodos que não usam D: Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.
  11. Extrair Método pequenos Melhor para testar
  12. Probabilidade de estar fazendo mais de uma coisa (SRP) Quebrar a classe em classes menores  (God Object)
  13. The Rule of Three
  14. Chamar atenção Códigos parecidos Nem sempre são identificados em ferramentas
  15. Chamar atenção Nem sempre são identificados em ferramentas
  16. Extrair para reaproveitar Sobrecarga (OO)
  17. Existem código complexos + nós complicados códigos simples Complexidade cíclomatica Quantidade de fluxo …
  18. qual o problema desse código? Muda comportamento
  19. qual o problema desse código?
  20. Usufruir do Polimorfismo - complexidade + constência
  21. Cuidado com o Invejoso Get demais de outro objeto
  22. Viola Encapsulamento Get demais de outro objeto
  23. Método que acesso muito dados de outro
  24. Além do tamanho, … Até 3 parâmetros
  25. Imutabilidade
  26. Sentimento de estar fazendo mais de uma coisa + complexidade ciclomática
  27. - Liskov: Classes derivadas devem poder ser substituídas por suas classes base
  28. - Iteração ineficiente de Map