Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Code Smells: o que eles dizem sobre seu código?

Elaine Naomi
December 13, 2018

Code Smells: o que eles dizem sobre seu código?

Apresentação RubyConfBR 2018

No mundo do Rails, aprendemos a sempre analisar o nosso código sobre o princípio do DRY e seguimos a estratégia de afastar qualquer lógica das nossas views, manter nossos controllers simples e mover toda a lógica de negócio para nossos models.
E quando a nossa aplicação começa a ficar complexa e de difícil manutenção? Models cada vez maiores e com cenários de testes complexos? O que isso diz sobre a nossa aplicação e sobre a qualidade do código escrito? É hora de começar do zero e reescrever tudo? É hora de mudar de paradigma? É hora de migrar para microsserviços? Calma! Vamos, primeiro, identificar os problemas de design da base de código atual.
Nessa talk, vamos conhecer code smells que nos auxiliam na refatoração e na medição da qualidade do nosso código, discutindo o impacto das decisões de design na evolução das aplicações, na entrega de funcionalidades, no processo de desenvolvimento e na comunicação e interação entre as pessoas da equipe.

Elaine Naomi

December 13, 2018
Tweet

More Decks by Elaine Naomi

Other Decks in Programming

Transcript

  1. code smells: o que eles dizem sobre seu código?

  2. hello

  3. Elaine Naomi Watanabe Desenvolvedora de Software (Plataformatec) Mestre em Ciência

    da Computação (USP) twitter.com/elaine_nw speakerdeck.com/elainenaomi
  4. http://careers.plataformatec.com.br temos vagas o/

  5. http://careers.plataformatec.com.br + sorteios!!

  6. qual a importância da qualidade do seu código como reconhecer

    os sinais de problemas na base de código como lidar com dívida técnica e refatorar nossas aplicações O que vamos ver?
  7. qualidade de software

  8. Software confiável Funcionamento correto (sem bugs) Entrega do valor esperado

    O que queremos?
  9. e como garantimos a qualidade?

  10. Testes automatizados Revisão de código Testes em QA O que

    fazemos?
  11. Testes automatizados Revisão de código Testes de aceitação O que

    fazemos?
  12. e em relação ao código escrito?

  13. o que precisamos considerar?

  14. Como os objetos estão organizados? Quais métodos e classes foram

    criados? O código é fácil de ser reutilizado?
  15. "o que importa é código funcionando"

  16. Tamanho da base de código Tempo de entregas Nota: gráfico

    ilustrativo, mas baseado em fatos reais
  17. "Esse código é difícil de entender"

  18. "Joga isso fora e começa do zero"

  19. None
  20. Quando reescrever um sistema? Uso de tecnologia desatualizada Contratação de

    pessoas está difícil Existência de tecnologias mais vantajosas Fonte: http://blog.plataformatec.com.br/2016/07/key-points-to-consider-when-doing-a-software-rewrite/
  21. None
  22. e temos outros caminhos?

  23. que tal refatorar o código?

  24. Refatoração processo de melhorar o design do código existente, alterando

    o software sem alterar o seu comportamento
  25. Por que refatorar? Código fácil de ler Código fácil de

    entender Código fácil de manter Código limpo
  26. precisamos mesmo refatorar?

  27. Dívida Técnica Custo da mudança Tempo Fonte: How to Monetize

    Application Technical Debt, Gartner, 2011
  28. None
  29. Dívida Técnica Valor de negócio Custo da mudança Tempo Fonte:

    How to Monetize Application Technical Debt, Gartner, 2011
  30. None
  31. e como evitar isso?

  32. Custo da mudança Tempo dívida técnica refatoração caso ótimo Fonte:

    An Empirical Model of Technical Debt and Interest, MTD' 11, Ariadni Nugroho et al.
  33. Como medir a necessidade de refatoração? Quantidade de código duplicado

    Cobertura de testes Desempenho da suíte de testes Complexidade ciclomática
  34. def total_compra(valor, epoca) total = 0 total += 0.1 if

    valor < 100 total += 0.5 if epoca.pre_black_friday? total end Complexidade ciclomática: 4
  35. e onde entram os code smells?

  36. Code smells Sintomas no código que indicam possíveis problemas de

    design em sistemas orientados a objeto
  37. Code smells Indícios de que o código precisa ser refatorado

  38. Martin Fowler e Kent Beck listam 22 code smells e

    sugerem como refatorá-los
  39. no mundo do Ruby...

  40. None
  41. exemplos de code smells

  42. Duplicated Code Código duplicado Extrair método, Extrair classe, Substituir condicional

    por polimorfismo
  43. Regra de negócio duplicada != Texto duplicado

  44. Dificuldade em dizer o que o método faz, Excesso de

    ifs ou case statements Extrair método Long Method
  45. Large Class Muitos métodos, God Classes, Dificuldade em dizer o

    que a classe faz, Excesso de concerns Extrair método, Extrair classe, Substituir condicional por polimorfismo
  46. Mesma alteração em vários arquivos, Buscas globais para toda alteração

    Extrair método, Extrair classe, Substituir condicional por polimorfismo Shotgun Surgery
  47. Acesso mais a dados de outro objeto, Violação do princípio

    Tell, don't ask Extrair método, Mover método, Internalizar classe Feature Envy
  48. class Subscription def charge(user) if user.has_credit_card? user.charge(total) else false end

    end end Violação do princípio Tell, don't ask Subscription não confia na classe User
  49. Conhecer/alterar detalhes internos de outra classe Extrair método Inappropriate Intimacy

  50. class Subscription def charge(user) if user.has_credit_card? && user.credit_card.status == 3

    user.charge(total) user.current_installment.paid! end end end
  51. class Subscription def charge(user) if user.has_credit_card? && user.credit_card.status == 3

    user.charge(total) user.current_installment.paid! end end end Subscription sabe demais sobre User, Credit Card e Installment
  52. Classe alterada constantemente Mudanças não relacionadas Mover método, Extrair classe,

    Uso de Form Object Divergent Change
  53. Vários comentários explicando o funcionamento do método Extrair variáveis explicativas,

    Extrair métodos, Renomear métodos Comments
  54. # ... def charge(a) if credit_card.status == 3 payment_gateway.charge(a) end

    end
  55. # ... def charge(total) if credit_card.status == 3 payment_gateway.charge(total) end

    end segundos de vida economizados! o/
  56. # ... def charge(total) if credit_card.status == 3 payment_gateway.charge(total) end

    end
  57. # ... def charge(total) if credit_card.active? payment_gateway.charge(total) end end def

    active? status == 3 end mais segundos de vida economizados! o/
  58. comentário != documentação

  59. SECONDS_FOR_CONNECTION_TIMEOUT_IN_INTEGER = 60

  60. # Public: Integer number of seconds to wait # before

    connection timeout. CONNECTION_TIMEOUT = 60
  61. # Public: A summary of how much some user has

    consumed in a certain plan. # # Examples # plan_consumption_summary(contracted_plan) # # => '2.44% (500 MB of 20 GB)' # # Returns a String. def plan_consumption_summary(contracted_plan) total_contracted = contracted_plan.plan_storage_limit total_consumed = contracted_plan.total_consumed # ... Fonte: http://blog.plataformatec.com.br/2018/06/the-anatomy-of-code-documentation/
  62. Data Clumps Primitive Obsession Switch Statements Parallel Inheritance Hierarchies Lazy

    Class Speculative Generality Outros code smells
  63. Temporary Field Message Chains Middle Man Alternative Classes with Different

    Interfaces Incomplete Library Class Data Class Refused Bequest Long Parameter List
  64. e como evitar os code smells? reduzir

  65. design de código

  66. Objetos Interfaces públicas e privadas Herança vs Composição Polimorfismo

  67. Polimorfismo ter uma interface única de acesso para diferentes classes/objetos

  68. class FinancialReport def generate(account, file_format) case file_format when :csv file

    = FormatCSV.generate(account.transactions) when :pdf file = PDFGenerator.print(account.transactions) end Mailer.send(account.email, file) end end
  69. class FinancialReport def generate(account, file_format) case file_format when :csv file

    = FormatCSV.generate(account.transactions) when :pdf file = PDFGenerator.print(account.transactions) end Mailer.send(account.email, file) end end
  70. class FinancialReport def generate(account, file_format) case file_format when :csv file

    = FormatCSV.generate(account.transactions) when :pdf file = PDFGenerator.print(account.transactions) when :xls file = FormatXLSGenerator.run(account.transactions) end Mailer.send(account.email, file) end end
  71. class FinancialReport def generate(account, file_creator) file = file_creator.create(account.transactions) Mailer.send(account.email, file)

    end end
  72. class FileCreatorPDF def create(items) PDF.print(items) end end class CSVGenerator def

    create(items) FormatCSV.generate(items) end end
  73. class FileCreatorPDF def create(items) PDF.print(items) end end class CSVGenerator def

    create(items) FormatCSV.generate(items) end end
  74. class FinancialReport def generate(account, file_creator) file = file_creator.create(account.transactions) Mailer.send(account.email, file)

    end end FinancialReport.new.generate(account, FileCreatorPDF.new) FinancialReport.new.generate(account, CSVGenerator.new)
  75. class FinancialReport def generate(account, file_creator) file = file_creator.create(account.transactions) Mailer.send(account.email, file)

    end end FinancialReport.new.generate(account, FileCreatorXLS.new)
  76. Coesão Encapsulamento Acoplamento Abstração de Tipos

  77. E nem sempre a ideia é sair extraindo classes! Pessoa

    Pessoa Física Pessoa Collapse hierarchy
  78. Ter boa cobertura de testes é essencial para garantir a

    evolução do seu sistema
  79. refatoração != revolução

  80. e aí, o que code smells dizem sobre o nosso

    código?
  81. Apontam possíveis problemas de design Alertam sobre redução da qualidade

    Indicam possível impacto no negócio
  82. None
  83. TL;DR;

  84. TL;DR: Qualidade de código Code smells Refatoração

  85. None
  86. None
  87. esses conceitos nos ajudam a criar aplicações mais saudáveis

  88. mas não é para refatorar só porque existe um code

    smell
  89. ou tratar todo code smell como um falso positivo

  90. precisamos olhar para o código que deixamos como legado

  91. converse com seu time sobre a importância da qualidade do

    código
  92. converse com seu time sobre a importância da qualidade do

    código + qualidade de software
  93. analisem juntos os trade-offs

  94. cuidado com big design up front e overengineering

  95. e não esqueçam:

  96. codar é um processo de comunicação

  97. None
  98. Mais sobre qualidade de software? Design de código, SOLID Padrões

    de projeto TDD, DDD, Agile
  99. minhas referências

  100. None
  101. None
  102. guidelines.plataformatec.com.br thoughtbot.com/upcase/clean-code refactoring.guru Mais referências:

  103. None
  104. None
  105. Até a próxima!

  106. obrigada speakerdeck.com/elainenaomi