paint-brush
Como encontrar as partes fedorentas do seu código [Parte XXII]por@mcsee
783 leituras
783 leituras

Como encontrar as partes fedorentas do seu código [Parte XXII]

por Maximiliano Contieri8m2022/08/29
Read on Terminal Reader
Read this story w/o Javascript

Muito longo; Para ler

Cheira porque provavelmente há muitos casos em que poderia ser editado ou melhorado.

Companies Mentioned

Mention Thumbnail
Mention Thumbnail
featured image - Como encontrar as partes fedorentas do seu código [Parte XXII]
Maximiliano Contieri HackerNoon profile picture

Cheiros de código são um clássico.

Cheira porque provavelmente há muitos casos em que poderia ser editado ou melhorado.


A maioria desses cheiros são apenas indícios de algo que pode estar errado. Eles não são necessariamente consertados per se ... (Você deve investigar isso.)


Código anterior cheira

Vamos continuar...


Cheiro de Código 106 - Código Dependente de Produção

Não adicione IFs verificando o ambiente de produção.

TL;DR: Evite adicionar condicionais relacionados à produção

problemas

  • Falha na violação do princípio rápido
  • Falta de testabilidade

Soluções

  1. Se for absolutamente necessário, modele ambientes e teste TODOS eles.

Contexto

Às vezes, precisamos criar comportamentos diferentes no desenvolvimento e na produção.

Por exemplo, a força das senhas.

Nesse caso, precisamos configurar o ambiente com a estratégia de força e testar a estratégia e não o ambiente em si.

Código de amostra

Errado

 def send_welcome_email(email_address, environment): if ENVIRONMENT_NAME == "production": print(f"Sending welcome email to {email_address} from Bob Builder <[email protected]>") else: print("Emails are sent only on production") send_welcome_email("[email protected]", "development") # Emails are sent only on production send_welcome_email("[email protected]", "production") # Sending welcome email to [email protected] from Bob Builder <[email protected]>

Certo

 class ProductionEnvironment: FROM_EMAIL = "Bob Builder <[email protected]>" class DevelopmentEnvironment: FROM_EMAIL = "Bob Builder Development <[email protected]>" # We can unit test environments # and even implement different sending mechanisms def send_welcome_email(email_address, environment): print(f"Sending welcome email to {email_address} from {environment.FROM_EMAIL}") # We can delegate into a fake sender (and possible logger) # and unit test it send_welcome_email("[email protected]", DevelopmentEnvironment()) # Sending welcome email to [email protected] from Bob Builder Development <[email protected]> send_welcome_email("[email protected]", ProductionEnvironment()) # Sending welcome email to [email protected] from Bob Builder <[email protected]>

Detecção

  • [x] manual

Este é um cheiro de design.

Precisamos criar configurações vazias de desenvolvimento/produção e delegá-las com objetos polimórficos personalizáveis.

Tag

  • Acoplamento

Conclusão

Evite adicionar condicionais não testáveis.

Crie configurações delegando regras de negócio.

Use abstrações, protocolo e interfaces, evite hierarquias rígidas.

Relações

Code Smell 56 - Pré-processadores

Mais informações

Créditos

Foto de Birmingham Museums Trust no Unsplash

Este tweet foi inspirado por @ Jan Giacomelli

Twitter


A complexidade é um sinal de imaturidade técnica. Simplicidade de uso é o sinal real de um produto bem projetado, seja um ATM ou um míssil Patriot.

Daniel T. Ling

Grandes Citações de Engenharia de Software


Code Smell 107 - Reutilização de Variáveis

A reutilização de variáveis torna os escopos e limites mais difíceis de seguir

TL;DR: Não leia e escreva a mesma variável para propósitos diferentes

problemas

  • Legibilidade
  • problemas ocultos

Soluções

  1. Não reutilize variáveis
  2. Extrair método para isolar escopos

Contexto

Ao programar um script é comum reutilizar variáveis.

Isso causa confusão e dificulta a depuração.

Devemos restringir o escopo o máximo possível.

Código de amostra

Errado

 // print line total double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); // print amount total total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); // variable is reused

Certo

 function printLineTotal() { double total = item.getPrice() * item.getQuantity(); System.out.println("Line total: " + total ); } function printAmountTotal() { double total = order.getTotal() - order.getDiscount(); System.out.println( "Amount due: " + total ); }

Detecção

  • [ ] Automático

Os Linters podem usar a árvore de análise para encontrar definições e usos de variáveis.

Tag

  • Legibilidade

Conclusão

Evite reutilizar nomes de variáveis. Use nomes mais específicos e diferentes.

Relações

Cheiro de código 03 - as funções são muito longas

Mais informações

Refatoração 002 - Método Extrair

Créditos

Foto de Sigmund no Unsplash


Simplicidade antes da generalidade, uso antes da reutilização.

Kevlin Henney

Grandes Citações de Engenharia de Software


Code Smell 108 - Float Assertions

Afirmar que dois números float são iguais é um problema muito difícil

TL;DR: Não compare floats

problemas

  • resultados de teste errados
  • Testes frágeis
  • Falha na violação do princípio rápido

Soluções

  1. Evite flutuações, a menos que você tenha problemas de desempenho REAIS
  2. Use números de precisão arbitrária
  3. Se você precisar comparar os flutuadores, compare com a tolerância.

Contexto

Comparar números float é um antigo problema da ciência da computação.

A solução usual é usar comparações de limite.

Recomendamos evitar flutuações e tentar usar números de precisão infinita.

Código de amostra

Errado

 Assert.assertEquals(0.0012f, 0.0012f); // Deprecated Assert.assertTrue(0.0012f == 0.0012f); // Not JUnit - Smell

Certo

 Assert.assertEquals(0.0012f, 0.0014f, 0.0002); // true Assert.assertEquals(0.0012f, 0.0014f, 0.0001); // false // last parameter is the delta threshold Assert.assertEquals(12 / 10000, 12 / 10000); // true Assert.assertEquals(12 / 10000, 14 / 10000); // false

Detecção

  • [ ] Automático

Podemos adicionar uma verificação com assertEquals() em nossas estruturas de teste para evitar a verificação de flutuações.

Tag

  • Testar odores

Conclusão

Devemos sempre evitar comparar floats.

Relações

Code Smell 71 - Flutuadores Mágicos Disfarçados de Decimais

Mais informações

Créditos

Foto de Mika Baumeister no Unsplash


Deus fez os números naturais; tudo o mais é obra do homem.

Leopold Kronecker

Grandes Citações de Engenharia de Software


Cheiro de Código 109 - Propriedades Automáticas

O que acontece se você combinar 4 code smells?

TL;DR: Evite getters, evite setters, evite metaprogramação. Pense no Comportamento.

problemas

Soluções

  1. Remover setters e getters automáticos

Contexto

Setters e getters são uma má prática da indústria.

Muitos IDEs favorecem esse cheiro de código.

Algumas linguagens fornecem suporte explícito para construir modelos anêmicos e DTOs.

Código de amostra

Errado

 class Person { public string name { get; set; } }

Certo

 class Person { private string name public Person(string personName) { name = personName; //imutable //no getters, no setters } //... more protocol, probably accessing private variable name }

Detecção

  • [ ] Automático

Este é um recurso de linguagem.

Devemos evitar línguas imaturas ou proibir suas piores práticas.

Tag

  • Encapsulamento

Conclusão

Precisamos pensar bem antes de expor nossas propriedades.

O primeiro passo é parar de pensar em propriedades e focar apenas no comportamento.

Relações

Code Smell 28 - Setters

Code Smell 68 - Getters

Code Smell 70 - Geradores de modelos anêmicos

Code Smell 40 - DTOs

Cheiro de Código 01 - Modelos Anêmicos

Mais informações

Créditos

Foto de Kony no Unsplash


Nada é mais difícil do que trabalhar com um prazo apertado e ainda reservar um tempo para limpar enquanto trabalha.

Kent Beck

Grandes Citações de Engenharia de Software


Code Smell 110 - Switches com padrões

Padrão significa 'tudo o que ainda não sabemos'. Não podemos prever o futuro.

TL;DR: Não adicione uma cláusula padrão aos seus casos. Altere-o para uma exceção. Seja explícito.

problemas

Soluções

  1. Substitua if e cases por polimorfismo
  2. Altere o código padrão para uma exceção

Contexto

Ao usar casos, geralmente adicionamos um caso padrão para que não falhe.

Falhar é sempre melhor do que tomar decisões sem provas.

Como o gabinete e os interruptores também são um cheiro, podemos evitá-los.

Código de amostra

Errado

 switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; default: // if value does not presently match the above values // or future values // the following will be executed doSomethingSpecial(); break; }

Certo

 switch (value) { case value1: // if value1 matches the following will be executed.. doSomething(); break; case value2: // if value2 matches the following will be executed.. doSomethingElse(); break; case value3: case value4: // We currently know these options exist doSomethingSpecial(); break; default: // if value does not match the above values we need to take a decision throw new Exception('Unexpected case ' + value + ' we need to consider it'); break; }

Detecção

  • [x] Semiautomático

Podemos dizer aos nossos linters para nos avisar sobre usos padrão, a menos que haja uma exceção.

Tag

  • Falhar rápido

Conclusão

Escrever código robusto não significa que precisamos tomar decisões sem evidências.

Relações

Cheiro de código 36 - instruções switch/case/elseif/else/if

Mais informações

Créditos

Foto de Joshua Woroniecki no Unsplash


O custo de adicionar um recurso não é apenas o tempo necessário para codificá-lo. O custo também inclui a adição de um obstáculo à expansão futura. O truque é escolher os recursos que não lutam entre si.

John Carmack

Grandes Citações de Engenharia de Software



E isso é tudo por agora…

O próximo artigo explicará mais 5 code smells!