Elaine Naomi Watanabe
Desenvolvedora de Software (Plataformatec)
Mestre em Ciência da Computação (USP)
twitter.com/elaine_nw
speakerdeck.com/elainenaomi
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?
Slide 7
Slide 7 text
qualidade de software
Slide 8
Slide 8 text
Software confiável
Funcionamento correto (sem bugs)
Entrega do valor esperado
O que queremos?
Slide 9
Slide 9 text
e como garantimos a qualidade?
Slide 10
Slide 10 text
Testes automatizados
Revisão de código
Testes em QA
O que fazemos?
Slide 11
Slide 11 text
Testes automatizados
Revisão de código
Testes de aceitação
O que fazemos?
Slide 12
Slide 12 text
e em relação ao código escrito?
Slide 13
Slide 13 text
o que precisamos considerar?
Slide 14
Slide 14 text
Como os objetos estão organizados?
Quais métodos e classes foram criados?
O código é fácil de ser reutilizado?
Slide 15
Slide 15 text
"o que importa é código funcionando"
Slide 16
Slide 16 text
Tamanho da base de código
Tempo de entregas
Nota: gráfico ilustrativo, mas baseado em fatos reais
Slide 17
Slide 17 text
"Esse código é difícil de entender"
Slide 18
Slide 18 text
"Joga isso fora e começa do zero"
Slide 19
Slide 19 text
No content
Slide 20
Slide 20 text
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/
Slide 21
Slide 21 text
No content
Slide 22
Slide 22 text
e temos outros caminhos?
Slide 23
Slide 23 text
que tal refatorar o código?
Slide 24
Slide 24 text
Refatoração
processo de melhorar o design do código existente,
alterando o software sem alterar o seu comportamento
Slide 25
Slide 25 text
Por que refatorar?
Código fácil de ler
Código fácil de entender
Código fácil de manter
Código limpo
Slide 26
Slide 26 text
precisamos mesmo refatorar?
Slide 27
Slide 27 text
Dívida Técnica
Custo da mudança
Tempo
Fonte: How to Monetize Application Technical Debt, Gartner, 2011
Slide 28
Slide 28 text
No content
Slide 29
Slide 29 text
Dívida Técnica
Valor de negócio
Custo da mudança
Tempo
Fonte: How to Monetize Application Technical Debt, Gartner, 2011
Slide 30
Slide 30 text
No content
Slide 31
Slide 31 text
e como evitar isso?
Slide 32
Slide 32 text
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.
Slide 33
Slide 33 text
Como medir a necessidade de refatoração?
Quantidade de código duplicado
Cobertura de testes
Desempenho da suíte de testes
Complexidade ciclomática
Slide 34
Slide 34 text
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
Slide 35
Slide 35 text
e onde entram os code smells?
Slide 36
Slide 36 text
Code smells
Sintomas no código que indicam possíveis
problemas de design em sistemas orientados a objeto
Slide 37
Slide 37 text
Code smells
Indícios de que o código precisa ser refatorado
Slide 38
Slide 38 text
Martin Fowler e
Kent Beck listam
22 code smells e
sugerem como
refatorá-los
Dificuldade em dizer o que o método faz,
Excesso de ifs ou case statements
Extrair método
Long Method
Slide 45
Slide 45 text
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
Slide 46
Slide 46 text
Mesma alteração em vários arquivos,
Buscas globais para toda alteração
Extrair método, Extrair classe,
Substituir condicional por polimorfismo
Shotgun Surgery
Slide 47
Slide 47 text
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
Slide 48
Slide 48 text
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
Slide 49
Slide 49 text
Conhecer/alterar detalhes internos de
outra classe
Extrair método
Inappropriate Intimacy
Slide 50
Slide 50 text
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
Slide 51
Slide 51 text
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
Slide 52
Slide 52 text
Classe alterada constantemente
Mudanças não relacionadas
Mover método, Extrair classe,
Uso de Form Object
Divergent Change
Slide 53
Slide 53 text
Vários comentários explicando o
funcionamento do método
Extrair variáveis explicativas,
Extrair métodos, Renomear métodos
Comments
Slide 54
Slide 54 text
# ...
def charge(a)
if credit_card.status == 3
payment_gateway.charge(a)
end
end
Slide 55
Slide 55 text
# ...
def charge(total)
if credit_card.status == 3
payment_gateway.charge(total)
end
end
segundos de vida economizados! o/
Slide 56
Slide 56 text
# ...
def charge(total)
if credit_card.status == 3
payment_gateway.charge(total)
end
end
Slide 57
Slide 57 text
# ...
def charge(total)
if credit_card.active?
payment_gateway.charge(total)
end
end
def active?
status == 3
end
mais segundos de vida economizados!
o/
Slide 58
Slide 58 text
comentário != documentação
Slide 59
Slide 59 text
SECONDS_FOR_CONNECTION_TIMEOUT_IN_INTEGER = 60
Slide 60
Slide 60 text
# Public: Integer number of seconds to wait
# before connection timeout.
CONNECTION_TIMEOUT = 60
Slide 61
Slide 61 text
# 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/
Slide 62
Slide 62 text
Data Clumps
Primitive Obsession
Switch Statements
Parallel Inheritance Hierarchies
Lazy Class
Speculative Generality
Outros code smells
Slide 63
Slide 63 text
Temporary Field
Message Chains
Middle Man
Alternative Classes with Different Interfaces
Incomplete Library Class
Data Class
Refused Bequest
Long Parameter List
Slide 64
Slide 64 text
e como evitar os code smells?
reduzir
Slide 65
Slide 65 text
design de código
Slide 66
Slide 66 text
Objetos
Interfaces públicas e privadas
Herança vs Composição
Polimorfismo
Slide 67
Slide 67 text
Polimorfismo
ter uma interface única de acesso para diferentes
classes/objetos
Slide 68
Slide 68 text
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
Slide 69
Slide 69 text
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
Slide 70
Slide 70 text
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
Slide 71
Slide 71 text
class FinancialReport
def generate(account, file_creator)
file = file_creator.create(account.transactions)
Mailer.send(account.email, file)
end
end
Slide 72
Slide 72 text
class FileCreatorPDF
def create(items)
PDF.print(items)
end
end
class CSVGenerator
def create(items)
FormatCSV.generate(items)
end
end
Slide 73
Slide 73 text
class FileCreatorPDF
def create(items)
PDF.print(items)
end
end
class CSVGenerator
def create(items)
FormatCSV.generate(items)
end
end
Slide 74
Slide 74 text
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)
Slide 75
Slide 75 text
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)
Slide 76
Slide 76 text
Coesão
Encapsulamento
Acoplamento
Abstração de Tipos
Slide 77
Slide 77 text
E nem sempre a ideia é sair extraindo classes!
Pessoa
Pessoa Física
Pessoa
Collapse hierarchy
Slide 78
Slide 78 text
Ter boa cobertura de testes é essencial para
garantir a evolução do seu sistema
Slide 79
Slide 79 text
refatoração != revolução
Slide 80
Slide 80 text
e aí, o que code smells dizem sobre o
nosso código?
Slide 81
Slide 81 text
Apontam possíveis problemas de design
Alertam sobre redução da qualidade
Indicam possível impacto no negócio
Slide 82
Slide 82 text
No content
Slide 83
Slide 83 text
TL;DR;
Slide 84
Slide 84 text
TL;DR:
Qualidade de código
Code smells
Refatoração
Slide 85
Slide 85 text
No content
Slide 86
Slide 86 text
No content
Slide 87
Slide 87 text
esses conceitos nos ajudam a criar
aplicações mais saudáveis
Slide 88
Slide 88 text
mas não é para refatorar só
porque existe um code smell
Slide 89
Slide 89 text
ou tratar todo code smell
como um falso positivo
Slide 90
Slide 90 text
precisamos olhar para o código
que deixamos como legado
Slide 91
Slide 91 text
converse com seu time sobre a
importância da qualidade do código
Slide 92
Slide 92 text
converse com seu time sobre a
importância da qualidade do código
+ qualidade de software
Slide 93
Slide 93 text
analisem juntos os trade-offs
Slide 94
Slide 94 text
cuidado com big design up front e
overengineering
Slide 95
Slide 95 text
e não esqueçam:
Slide 96
Slide 96 text
codar é um processo de comunicação
Slide 97
Slide 97 text
No content
Slide 98
Slide 98 text
Mais sobre qualidade de software?
Design de código, SOLID
Padrões de projeto
TDD, DDD, Agile
Slide 99
Slide 99 text
minhas referências
Slide 100
Slide 100 text
No content
Slide 101
Slide 101 text
No content
Slide 102
Slide 102 text
guidelines.plataformatec.com.br
thoughtbot.com/upcase/clean-code
refactoring.guru
Mais referências: