Refatorando TUDO! @marcosbrizeno
@marcosbrizeno
A única maneira de ir rápido é ter qualidade
https://pt.wikipedia.org/wiki/procrastinação
esforço tempo
esforço prazo tempo
esforço tempo
O Scrum resolve esse problema!
esforço... tempo
esforço... tempo Iteração 1 Iteração 2... Iteração n
You can't ship process
A única maneira de ir rápido é ter qualidade https://www.youtube.com/watch?v=hg4lh6p8syk
Mão na massa: Renomear um método
Mão na massa: Renomear um método
Renomear um método é simples!
Renomear um método é simples! - Muda o nome do método
Renomear um método é simples! - Muda o nome do método - Procura onde é chamado e atualiza
Renomear um método é simples! - Muda o nome do método - Procura onde é chamado e atualiza - Roda os testes
Renomear um método é simples!
Renomear um método é simples? - Quem chama o método vai quebrar? (conflitos de nomes)
Renomear um método é simples? - Quem chama o método vai quebrar? (conflitos de nomes) - Mudar o nome do método não vai quebrar outro ponto? (metaprogramação)
Renomear um método é simples? - Quem chama o método vai quebrar? (conflitos de nomes) - Mudar o nome do método não vai quebrar outro ponto? (metaprogramação) - Tudo ou nada!
Refactoring vs Rehacktoring REFACTORING - Testes passam a cada mudança REHACKTORING - Testes talvez passem
Refactoring vs Rehacktoring REFACTORING REHACKTORING - Testes passam a cada mudança - Testes talvez passem - Mantém comportamento externo - Talvez mantém o comportamento
Refactoring vs Rehacktoring REFACTORING REHACKTORING - Testes passam a cada mudança - Testes talvez passem - Mantém comportamento externo - Talvez mantém o comportamento - Uma mudança por vez - Várias mudanças
Refactoring vs Rehacktoring REFACTORING REHACKTORING - Testes passam a cada mudança - Testes talvez passem - Mantém comportamento externo - Talvez mantém o comportamento - Uma mudança por vez - Várias mudanças - Visão clara do objetivo final - Objetivo final incerto
Refatoração: Renomear método 1. Declare um método com o novo nome
Refatoração: Renomear método 1. Declare um método com o novo nome a. Rode os testes
Refatoração: Renomear método 1. Declare um método com o novo nome a. 2. Rode os testes Copie o código do método antigo para o novo (adaptando os parâmetros) a. Rode os testes
Refatoração: Renomear método 1. Declare um método com o novo nome a. 2. Copie o código do método antigo para o novo (adaptando os parâmetros) a. 3. Rode os testes Rode os testes Faça o método antigo chamar o novo a. Rode os testes
Refatoração: Renomear método 1. Declare um método com o novo nome a. 2. Copie o código do método antigo para o novo (adaptando os parâmetros) a. 3. Rode os testes Faça o método antigo chamar o novo a. 4. Rode os testes Rode os testes Troque o método novo pelo método antigo (um por vez) a. Rode os teste
Sério? Sério
Problemas ao refatorar Falta de feedback
Problemas ao refatorar Falta de feedback Ciclo longo
Problemas ao refatorar Falta de feedback Ciclo longo Visão técnica
Mão na massa: Revisar um Pull Request Julia Carlos
Mão na massa: Revisar um Pull Request
Mão na massa: Revisar um Pull Request
Mão na massa: Revisar um Pull Request
Mão na massa: Revisar um Pull Request
Mão na massa: Revisar um Pull Request - Outras classes vão ter preços - - Também vão precisar retornar uma string com o preço cotado Será necessário ter mais operações envolvendo dinheiro - Somar, subtrair, etc.
Seu código está "ruim". Mas por quê?
Code Smells
Code Smells Name five Code Smells.
Code Smells https://martinfowler.com/bliki/codesmell.html
Code Smells
Long Method Large Class Primitive obsession Long Parameter List Data Clump Switch statements Temporary field Refused Bequest Alternative classes with diff interfaces Code Smells Divergent Change Shotgun Surgery Parallel Inheritance Feature envy Inappropriate Intimacy Message Chains Middle Man Lazy Class Data Class Duplicated Code Dead Code Speculative Generality http://mikamantyla.eu/badcodesmellstaxonomy.html
Long Method Large Class Primitive obsession Long Parameter List Data Clump Switch statements Temporary field Refused Bequest Alternative classes with diff interfaces Bloaters Divergent Change Shotgun Surgery Parallel Inheritance Feature envy Inappropriate Intimacy Message Chains Middle Man Lazy Class Data Class Duplicated Code Dead Code Speculative Generality http://mikamantyla.eu/badcodesmellstaxonomy.html
Long Method Large Class Primitive obsession Long Parameter List Data Clump Switch statements Temporary field Refused Bequest Alternative classes with diff interfaces Divergent Change Shotgun Surgery Parallel Inheritance Feature envy Inappropriate Intimacy Message Chains Middle Man Lazy Class Data Class Duplicated Code Dead Code Speculative Generality Object Orientation Abusers http://mikamantyla.eu/badcodesmellstaxonomy.html
Divergent Change Shotgun Surgery Parallel Inheritance Long Method Large Class Primitive obsession Long Parameter List Data Clump Switch statements Temporary field Refused Bequest Alternative classes with diff interfaces Feature envy Inappropriate Intimacy Message Chains Middle Man Lazy Class Data Class Duplicated Code Dead Code Speculative Generality Change Preventers http://mikamantyla.eu/badcodesmellstaxonomy.html
Long Method Large Class Primitive obsession Long Parameter List Data Clump Switch statements Temporary field Refused Bequest Alternative classes with diff interfaces The Couplers Divergent Change Shotgun Surgery Parallel Inheritance Feature envy Inappropriate Intimacy Message Chains Middle Man Lazy Class Data Class Duplicated Code Dead Code Speculative Generality http://mikamantyla.eu/badcodesmellstaxonomy.html
Long Method Large Class Primitive obsession Long Parameter List Data Clump Switch statements Temporary field Refused Bequest Alternative classes with diff interfaces The Dispensables Divergent Change Shotgun Surgery Parallel Inheritance Feature envy Inappropriate Intimacy Message Chains Middle Man Lazy Class Data Class Duplicated Code Dead Code Speculative Generality http://mikamantyla.eu/badcodesmellstaxonomy.html
Por onde começar? 99 Bottles of OOP https://www.sandimetz.com/99bottles/
Code Smell: Data Clump https://martinfowler.com/bliki/dataclump.html
Code Smell: Data Clump lib/series.rb
Code Smell: Data Clump lib/series.rb
Code Smell: Data Clump lib/series.rb
Code Smell: Data Clump lib/series.rb
Code Smell: Data Clump lib/series.rb
Mão na massa: introduzir Value Class 1. Criar uma Value Class com construtores e getters a. Deve incluir o valor e a moeda 2. Encapsular atributos ao invés de chamá-las diretamente 3. Instanciar Value Object junto com os atributos 4. Trocar chamada getter por getter da Value Class 5. Apagar atributos não utilizados
Value Class para representar dinheiro lib/series.rb
Value Class para representar dinheiro lib/dinheiro.rb
Value Class para representar dinheiro lib/dinheiro.rb
Value Class para representar dinheiro lib/dinheiro.rb
Encapsular atributos preco e moeda lib/serie.rb
Encapsular atributos preco e moeda lib/serie.rb
Encapsular atributos preco e moeda lib/serie.rb
Encapsular atributos preco e moeda lib/serie.rb
Encapsular atributos preco e moeda lib/serie.rb
Instanciar Value Object junto com atributos lib/serie.rb
Instanciar Value Object junto com atributos lib/serie.rb
Instanciar Value Object junto com atributos lib/serie.rb
Trocar chamada do getter pela value class lib/serie.rb
Trocar chamada do getter pela value class lib/serie.rb
Trocar chamada do getter pela value class lib/serie.rb
Apagar atributos não utilizados lib/serie.rb
Apagar atributos não utilizados lib/serie.rb
Apagar atributos não utilizados lib/serie.rb
Apagar atributos não utilizados lib/serie.rb
Apagar atributos não utilizados lib/serie.rb
Apagar atributos não utilizados lib/serie.rb
Code Smell: Primitive Obsession http://wiki.c2.com/?primitiveobsession
Code Smell: Primitive Obsession lib/serie.rb lib/cotacao_util.rb
Code Smell: Primitive Obsession lib/serie.rb lib/cotacao_util.rb
Mão na massa: introduzir Parameter Object 1. Criar uma estrutura para agrupar parâmetros (se não existir) 2. Mudar a assinatura do método a. Criar um método com mesmo corpo e nova assinatura b. Atualizar referências ao novo parâmetro 3. Chamar o método novo no método antigo 4. Atualizar as referências do métodos antigos 5. Apagar método antigo
Criar uma estrutura para agrupar parâmetros lib/dinheiro.rb
Mudar a assinatura do método lib/cotacao_util.rb
Mudar a assinatura do método lib/cotacao_util.rb
Mudar a assinatura do método lib/cotacao_util.rb
Mudar a assinatura do método lib/cotacao_util.rb
Mudar a assinatura do método lib/cotacao_util.rb
Mudar a assinatura do método lib/cotacao_util.rb
Atualizar as referências do método antigo lib/serie.rb
Atualizar as referências do método antigo lib/serie.rb
Apagar método antigo
Code Smell: Feature Envy http://wiki.c2.com/?featureenvysmell
Code Smell: Feature Envy lib/serie.rb
Code Smell: Feature Envy lib/serie.rb
Code Smell: Feature Envy lib/serie.rb
Code Smell: Feature Envy lib/serie.rb
Mão na massa: mover método 1. 2. Identificar e extrair o método que será movido a. Copiar conteúdo para novo método b. Converter variáveis locais em parâmetro Copiar método para nova classe a. trocar parâmetros por atributos (quando possível) 3. Trocar chamadas do método antigo pelo novo método 4. Apagar métodos antigos
Identificar e extrair o método que será movido lib/serie.rb
Identificar e extrair o método que será movido lib/serie.rb
Identificar e extrair o método que será movido lib/serie.rb
Identificar e extrair o método que será movido lib/serie.rb
Copiar método para nova classe lib/dinheiro.rb
Copiar método para nova classe lib/dinheiro.rb
Copiar método para nova classe lib/dinheiro.rb
Trocar chamadas pelo método novo lib/serie.rb
Trocar chamadas pelo método novo lib/serie.rb
Trocar chamadas pelo método novo lib/serie.rb
Apagar método antigo
Code Smell: Feature Envy lib/serie.rb lib/cotacao_util.rb
Code Smell: Feature Envy lib/serie.rb lib/cotacao_util.rb
Code Smell: Feature Envy lib/serie.rb lib/cotacao_util.rb
Classes Util/Service e Orientação a Objetos
Objetos se comunicam através de mensagens, visando proteger e esconder seu estado interno
Pensando orientado a objetos Dinheiro valor: int moeda: String Estados exibir_moeda converter_moeda somar... Mensagens
Pensando orientado a objetos obj obj obj obj obj obj
Code Smell: Data Class Dinheiro valor: int moeda: String getvalor: setvalor: getmoeda: setmoeda: int void String void DinheiroService Estados Mensagens exibir_moeda converter_moeda somar...
Objetos anêmicos Serviços/Util Programação Procedural
Proragamação Procedural é ruim?
Usar uma linguagem OO para programar procedural é ruim!
Code Smell: Feature Envy lib/serie.rb lib/cotacao_util.rb
Mão na massa: mover método 1. 2. Identificar e extrair o método que será movido a. Copiar conteúdo para novo método b. Converter variáveis locais em parâmetro Copiar método para nova classe a. trocar parâmetros por atributos (quando possível) 3. Trocar chamadas do método antigo pelo novo método 4. Apagar métodos antigos
Identificar e extrair o método que será movido lib/serie.rb
Identificar e extrair o método que será movido lib/serie.rb
Identificar e extrair o método que será movido lib/serie.rb
Copiar método para nova classe lib/dinheiro.rb
Copiar método para nova classe lib/dinheiro.rb
Trocar chamadas pelo método novo lib/serie.rb
Trocar chamadas pelo método novo lib/serie.rb
Trocar chamadas pelo método novo lib/serie.rb
Apagar método antigo
Como decidir o que depende do que?
Quantidade de mudanças e acomplamento Probabilidade de mudanças https://www.youtube.com/watch?v=v-2yfmzxqwu
Quantidade de mudanças e acomplamento Probabilidade de mudanças Cotacao Dinheiro Extrair os valores da cotação para um arquivo de configuração https://www.youtube.com/watch?v=v-2yfmzxqwu
Quantidade de mudanças e acomplamento Probabilidade de mudanças Cotacao Dinheiro Dependa da direita para a esquerda https://www.youtube.com/watch?v=v-2yfmzxqwu
Como melhorar seu código efetivamente 1. Entenda como seu programa vai evoluir (Keep it Simple, Stupid) 2. Identifique os Code Smells mais fáceis de resolver 3. Aplique refatorações 4. Repita até que o código esteja aberto a extensão 5. Aplique a mudança
Garantir que os testes sempre passem Feedback rápido
Garantir que os testes sempre passem Feedback rápido Fácil de reverter
Garantir que os testes sempre passem Feedback rápido Fácil de reverter Reduz ansiedade
Code Smell -> Refactoring https://refactoring.com/catalog/
Code Smell -> Refactoring industriallogic.com/blog/smells-to-refactorings-cheatsheet/
Code Smell é ruim?
Simplicidade de código Todos os testes passam Sem duplicac a o Mostra as intenc o es Possui o menor nu mero de classes ou me todos Extreme Programming Explained: embrace change
Mais! Refactoring - Martin Fowler
Mais! 99 Bottles of Object Oriented Programming - Sandi Metz & Katrina Owen
Mais! Refatorando com Padrões de Projeto - Marcos Brizeno
Mais! Refatorando com Padrões de Projeto - Marcos Brizeno
https://www.casadocodigo.com.br/products/livro-refatoracao-ruby 20% - DIADOPROGRAMADOR_2017X
Valeu! @marcosbrizeno