Refatorando tudo! [Agile brazil 2017]

Post on 29-Jan-2018

106 views 0 download

Transcript of Refatorando tudo! [Agile brazil 2017]

Refatorando TUDO!

@marcosbrizeno

@marcosbrizeno

A única maneirade ir rápidoé ter qualidade

https://pt.wikipedia.org/wiki/Procrastinação

tempo

esforço

prazo

tempo

esforço

tempo

esforço

O Scrum resolve esse problema!

tempo

esforço

...

Iteração 1 Iteração 2 Iteração n...

...

tempo

esforço

You can't ship process

A única maneirade 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 RehacktoringREFACTORING

- Testes passam a cada mudança

REHACKTORING

- Testes talvez passem

Refactoring vs RehacktoringREFACTORING

- Testes passam a cada mudança

- Mantém comportamento externo

REHACKTORING

- Testes talvez passem

- Talvez mantém o comportamento

Refactoring vs RehacktoringREFACTORING

- Testes passam a cada mudança

- Mantém comportamento externo

- Uma mudança por vez

REHACKTORING

- Testes talvez passem

- Talvez mantém o comportamento

- Várias mudanças

Refactoring vs RehacktoringREFACTORING

- Testes passam a cada mudança

- Mantém comportamento externo

- Uma mudança por vez

- Visão clara do objetivo final

REHACKTORING

- Testes talvez passem

- Talvez mantém o comportamento

- Várias mudanças

- Objetivo final incerto

Refatoração: Renomear método1. Declare um método com o novo nome

Refatoração: Renomear método1. Declare um método com o novo nome

a. Rode os testes

Refatoração: Renomear método1. Declare um método com o novo nome

a. Rode os testes

2. Copie o código do método antigo para o novo (adaptando os parâmetros)

a. Rode os testes

Refatoração: Renomear método1. Declare um método com o novo nome

a. Rode os testes

2. Copie o código do método antigo para o novo (adaptando os parâmetros)

a. Rode os testes

3. Faça o método antigo chamar o novoa. Rode os testes

Refatoração: Renomear método1. Declare um método com o novo nome

a. Rode os testes

2. Copie o código do método antigo para o novo (adaptando os parâmetros)

a. Rode os testes

3. Faça o método antigo chamar o novoa. Rode os testes

4. Troque o método novo pelo método antigo (um por vez)

a. Rode os teste

Sério?Sério

Falta de feedback

Problemas ao refatorar

Falta de feedback

Ciclo longo

Problemas ao refatorar

Falta de feedback

Ciclo longo

Visão técnica

Problemas ao refatorar

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 fiveCode Smells.

Code Smells

https://martinfowler.com/bliki/CodeSmell.html

Code Smells

Code Smellshttp://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

Lazy Class

Data Class

Duplicated Code

Dead Code

Speculative Generality

Feature envy

Inappropriate Intimacy

Message Chains

Middle Man

Bloatershttp://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

Lazy Class

Data Class

Duplicated Code

Dead Code

Speculative Generality

Feature envy

Inappropriate Intimacy

Message Chains

Middle Man

Object Orientation Abusershttp://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

Lazy Class

Data Class

Duplicated Code

Dead Code

Speculative Generality

Feature envy

Inappropriate Intimacy

Message Chains

Middle Man

Change Preventershttp://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

Lazy Class

Data Class

Duplicated Code

Dead Code

Speculative Generality

Feature envy

Inappropriate Intimacy

Message Chains

Middle Man

The Couplershttp://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

Lazy Class

Data Class

Duplicated Code

Dead Code

Speculative Generality

Feature envy

Inappropriate Intimacy

Message Chains

Middle Man

The Dispensableshttp://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

Lazy Class

Data Class

Duplicated Code

Dead Code

Speculative Generality

Feature envy

Inappropriate Intimacy

Message Chains

Middle Man

Por onde começar?

99 Bottles of OOPhttps://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 gettersa. 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/cotacao_util.rb

lib/serie.rb

Code Smell: Primitive Obsession

lib/cotacao_util.rb

lib/serie.rb

Mão na massa: introduzir Parameter Object1. Criar uma estrutura para agrupar parâmetros (se não existir)

2. Mudar a assinatura do métodoa. 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. Identificar e extrair o método que será movidoa. Copiar conteúdo para novo método

b. Converter variáveis locais em parâmetro

2. Copiar método para nova classea. 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 protegere esconder seu estado interno

Pensando orientado a objetos

Dinheiro

valor: intmoeda: String

exibir_moedaconverter_moedasomar...

Estados

Mensagens

Pensando orientado a objetos

obj

obj

obj

obj

obj

obj

Code Smell: Data Class

Dinheiro

valor: intmoeda: String

getValor: intsetValor: voidgetMoeda: StringsetMoeda: void

Estados

Mensagens

DinheiroService

exibir_moedaconverter_moedasomar...

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. Identificar e extrair o método que será movidoa. Copiar conteúdo para novo método

b. Converter variáveis locais em parâmetro

2. Copiar método para nova classea. 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

https://www.youtube.com/watch?v=v-2yFMzxqwU

Probabilidade de mudanças

Quantidade de mudanças e acomplamento

https://www.youtube.com/watch?v=v-2yFMzxqwU

Probabilidade de mudanças

Cotacao Dinheiro

Extrair os valores da cotação para um arquivo de configuração

Quantidade de mudanças e acomplamento

https://www.youtube.com/watch?v=v-2yFMzxqwU

Probabilidade de mudanças

Dependa da direita para a esquerda

Cotacao Dinheiro

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 ostestes sempre passem

Feedback rápido

Garantir que ostestes sempre passem

Feedback rápido

Fácil de reverter

Garantir que ostestes 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

Extreme Programming Explained: embrace change

Todos os testes passam

Sem duplicac ao

Mostra as intenc oes

Possui o menor numero de classes ou metodos

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

20% - DIADOPROGRAMADOR_2017X

https://www.casadocodigo.com.br/products/livro-refatoracao-ruby

Valeu!@marcosbrizeno