Slide 1

Slide 1 text

Vamos falar de refatoração Elias Dorneles @eliasdorneles

Slide 2

Slide 2 text

O que é refatorar, afinal?

Slide 3

Slide 3 text

Refatorar é... ● Mudar a estrutura do código ● SEM mudar o comportamento externo ● Visando melhorar o design Em geral, envolve fazer uma série de pequenas mudanças preservando o funcionamento.

Slide 4

Slide 4 text

Objetivo é acomodar melhor as próximas mudanças

Slide 5

Slide 5 text

Refatorar NÃO é... ● Reescrever um módulo/função ● Alterar um código, mudando o comportamento ● Adicionar ou remover um recurso Mesmo que essas coisas visem melhorar o design!

Slide 6

Slide 6 text

Hm, por que é tão importante distinguir?

Slide 7

Slide 7 text

Primeiro, refatorar requer um lock Reestruturar código preservando comportamento é algo que precisa ser feito de maneira “atômica” Ou seja, quando estiver refatorando, não faça outras coisas ao mesmo tempo: apenas refatore

Slide 8

Slide 8 text

Metáfora dos chapéus Source: http://martinfowler.com/articles/workflowsOfRefactoring/#2hats

Slide 9

Slide 9 text

Segundo, o escopo e os riscos são diferentes

Slide 10

Slide 10 text

Refatorar é pra ser um hábito ● Cotidiano, como tomar água, abrir o editor, rodar o código, rodar os testes ● Não é algo que você precise pedir permissão pro gerente A seguir vamos ver alguns exemplos

Slide 11

Slide 11 text

Exemplos: renomear variável current_page = int(find_element_by_css('.page.active')) if current_page < total_pages: goto_page(current_page + 1) c = int(find_element_by_css('.page.active')) if c < total_pages: goto_page(c + 1)

Slide 12

Slide 12 text

Exemplos: extrair variável if cur_page < max(int(x) for x in page_links): goto_page(cur_page + 1) total_pages = max(int(x) for x in page_links) if cur_page < total_pages: goto_page(cur_page + 1)

Slide 13

Slide 13 text

Exemplos: inline da variável (inverso de extrair) if cur_page < max(int(x) for x in page_links): goto_page(cur_page + 1) total_pages = max(int(x) for x in page_links) if cur_page < total_pages: goto_page(cur_page + 1)

Slide 14

Slide 14 text

Exemplos: extrair função if cur_page < max(int(x) for x in page_links): goto_page(cur_page + 1) def get_total_pages(): return max(int(x) for x in page_links) if cur_page < get_total_pages(): goto_page(cur_page + 1)

Slide 15

Slide 15 text

Exemplos: extrair função (opção 2) if cur_page < max(int(x) for x in page_links): goto_page(cur_page + 1) def get_total_pages(all_pages): return max(int(x) for x in all_pages) if cur_page < get_total_pages(page_links): goto_page(cur_page + 1)

Slide 16

Slide 16 text

Extrair função/método é a minha refatoração favorita! =)

Slide 17

Slide 17 text

Exemplos: inline da função (inverso de extrair) if cur_page < max(int(x) for x in page_links): goto_page(cur_page + 1) def get_total_pages(all_pages): return max(int(x) for x in all_pages) if cur_page < get_total_pages(page_links): goto_page(cur_page + 1)

Slide 18

Slide 18 text

É bem provável que você já faça essas coisas, mesmo que não use esses nomes

Slide 19

Slide 19 text

Que outras refatorações existem?

Slide 20

Slide 20 text

http://refactoring.com/catalog

Slide 21

Slide 21 text

E Python? Existem refatorações pythônicas, né?

Slide 22

Slide 22 text

YESSS! Alguns exemplos: ● Substituir retorno múltiplo por namedtuple ● Extrair context manager ● Vários exemplos nessas talks do Raymond Hettinger: ○ Beyond PEP-8: http://pyvideo.org/pycon-us-2015/beyond-pep-8-best-practices-for-be autiful-inte.html ○ Transforming Code into Beautiful, Idiomatic Python: http://pyvideo.org/pycon-us-2013/transforming-code-into-beautiful-id iomatic-pytho.html (Slides)

Slide 23

Slide 23 text

Substituir retorno múltiplo por namedtuple from collections import namedtuple Interval = namedtuple('Interval', 'start end') def fetch_last_interval(conn): query = "SELECT start_time,end_time FROM facts ORDER by end_time LIMIT 1" start, end = next(conn.execute(query)) return Interval(start, end) # Interval(start=u'2016-12-15 13:52:45', end=None) def fetch_last_interval(conn): query = "SELECT start_time,end_time FROM facts ORDER by end_time LIMIT 1" start, end = next(conn.execute(query)) return start, end # (u'2016-12-15 13:52:45', None)

Slide 24

Slide 24 text

Extrair context manager import tempfile _, arq = tempfile.mkstemp() try: # processa o # arquivo aqui # ... finally: os.remove(arq) import tempfile from contextlib import contextmanager @contextmanager def arquivo_temp(): _, arq = tempfile.mkstemp() try: yield arq finally: os.remove(arq) with arquivo_temp() as arq: # processa arquivo aqui ...

Slide 25

Slide 25 text

Refatoração & YAGNI ● Humanos são péssimos em antecipar mudanças ● “You Aren’t Gonna Need It”: princípio que preza pela simplicidade, não olhando muito para o futuro, evitando complexidade desnecessária ● Você precisa refatorar para obter simplicidade ● Refatore para os casos de uso conhecidos

Slide 26

Slide 26 text

Ok, refatorar é legal! Como posso fazer mais e melhor?

Slide 27

Slide 27 text

Refatorar precisa ser fácil! Para isso, é preciso: ● Dominar profundamente a linguagem ○ Quanto mais coisas você souber fazer de cabeça, mais fácil fica ● Escrever testes ○ É uma necessidade básica ● Obter boas ferramentas ● Educar-se e praticar ○ Ler livros, ler código dos outros, tentar refactor grande num branch

Slide 28

Slide 28 text

● Qual a ferramenta de refatoração mais popular entre os Pythonistas? Sobre ferramentas

Slide 29

Slide 29 text

● Qual a ferramenta de refatoração mais popular entre os Pythonistas? ○ grep (e similares) ○ Será que não podemos fazer melhor? “The cobbler’s children have no shoes” Sobre ferramentas

Slide 30

Slide 30 text

● https://github.com/python-rope/rope ● Biblioteca de refatorações ○ e outras coisas mais (jump to definition) ● Plugins para VIM/Emacs/Sublime: ○ UI espartana ○ Poucas pessoas conhecem & usam ● Pessoalmente, uso pouco, a UI me assusta ○ Tenho mappings no VIM para as refatorações mais simples Rope -- is there hope?

Slide 31

Slide 31 text

DEMO no VIM

Slide 32

Slide 32 text

Alguém aí já gritou Pycharm?

Slide 33

Slide 33 text

Thanks! Elias Dorneles @eliasdorneles Algumas referências ● http://refactoring.com ● http://martinfowler.com/articles/ workflowsOfRefactoring ● https://www.infoq.com/br/articles /is-design-dead ● https://pythonhelp.wordpress.co m/2016/10/01/usando-comando- with-para-evitar-acoplamento-te mporal/ ● Livro do Martin Fowler ● Livro The Pragmatic Programmer