Vamos falar de refatoração

Vamos falar de refatoração

Slides da palestra apresentada na Python Floripa

Dfd7b9492f5c5e49dca373bfdd7a3b1a?s=128

Elias Dorneles

December 15, 2016
Tweet

Transcript

  1. Vamos falar de refatoração Elias Dorneles @eliasdorneles

  2. O que é refatorar, afinal?

  3. 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.
  4. Objetivo é acomodar melhor as próximas mudanças

  5. 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!
  6. Hm, por que é tão importante distinguir?

  7. 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
  8. Metáfora dos chapéus Source: http://martinfowler.com/articles/workflowsOfRefactoring/#2hats

  9. Segundo, o escopo e os riscos são diferentes

  10. 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
  11. 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)
  12. 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)
  13. 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)
  14. 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)
  15. 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)
  16. Extrair função/método é a minha refatoração favorita! =)

  17. 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)
  18. É bem provável que você já faça essas coisas, mesmo

    que não use esses nomes
  19. Que outras refatorações existem?

  20. http://refactoring.com/catalog

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

  22. 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)
  23. 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)
  24. 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 ...
  25. 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
  26. Ok, refatorar é legal! Como posso fazer mais e melhor?

  27. 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
  28. • Qual a ferramenta de refatoração mais popular entre os

    Pythonistas? Sobre ferramentas
  29. • 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
  30. • 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?
  31. DEMO no VIM

  32. Alguém aí já gritou Pycharm?

  33. 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