refactoring workshop - rubyconf argentina 2014

53
4 recetas para simplificar tu código git clone http://github.com/tute/ refactoring-workshop

Upload: thoughtbot

Post on 08-Jul-2015

388 views

Category:

Software


0 download

DESCRIPTION

Slidedeck for the Refactoring Workshop given at RubyConf Argentina 2014 rubyconfargentina.org

TRANSCRIPT

Page 1: Refactoring Workshop - RubyConf Argentina 2014

4 recetas para simplificar tu código

git clone http://github.com/tute/refactoring-workshop

Page 2: Refactoring Workshop - RubyConf Argentina 2014

¡Buen día!

1. ¿Cómo te llamás? 2. ¿Sos nuevo/nueva programando? 3. ¿Cuánto tiempo llevás programando en Ruby?

Page 3: Refactoring Workshop - RubyConf Argentina 2014

Aprenderemos a transformar esto…

Page 4: Refactoring Workshop - RubyConf Argentina 2014

En esto!

Page 5: Refactoring Workshop - RubyConf Argentina 2014

Patrones de Refactorización

Eufemismo para “No vas a creer cómo simplificamos

esta masa de código en 5 sencillos pasos”

Hoy veremos

Page 6: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

Page 7: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

Page 8: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

Page 9: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

Page 10: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

http://www.nodocomunitario.org/?page_id=462

Page 11: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

http://www.nodocomunitario.org/?page_id=462

Page 12: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

http://www.nodocomunitario.org/?page_id=462

Page 13: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

2011/2012: Chef Surfing

• No parábamos de programar

• La complejidad nos bloqueaba c/ 2 meses

• Parábamos. Testéabamos. Refactorizábamos.

• No era predecible.

Page 14: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

2011/2012: Chefsurfing

Page 15: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

2013: General Assembly

• Rails app en malas condiciones

• Pero con buenos tests

• Me dijeron “refactorizá lo que quieras”

• Agilizó el trabajo, semana tras semana

• Quiero repetir (y mejorar) esta historia

Page 16: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

2013: General Assembly

Page 17: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

2014: thoughtbot

• Calidad del código es el pan de cada día

• Priorizamos agresivamente qué desarrollar

• Escribimos lo mejor posible siempre

• No se acepta deuda técnica

• Programadores y clientes felices

Page 18: Refactoring Workshop - RubyConf Argentina 2014

Sobre mi

2014: thoughtbot

Page 19: Refactoring Workshop - RubyConf Argentina 2014

Patrones de Refactorización

1. Método que revela la intención

2. Objeto de "Caso Especial"

3. Reemplazar método con Objeto Método

4. Objeto "Servicio"

Hoy veremos

Page 20: Refactoring Workshop - RubyConf Argentina 2014

1/4 Método que revela la intención

Método que revela la intención

Porqué se llama es más importante que qué, o cómo, se hace.

Page 21: Refactoring Workshop - RubyConf Argentina 2014

Método que revela la intención

1/4 Método que revela la intención

“Planché la camisa y me afeité” (qué)

“Puse la camisa sobre la remera que me regaló mi tía, y pasé una afeitadora por mi cara” (cómo)

“Me preparé para salir” (porqué)

Page 22: Refactoring Workshop - RubyConf Argentina 2014

1/4 Método que revela la intención

# Remove duplicates?if hash[row[1]][date] != row[0] # ...

if remove_duplicates?(row, date) # ...

def remove_duplicates?(row, date) hash[row[1]][date] != row[0]

Page 23: Refactoring Workshop - RubyConf Argentina 2014

Un Algoritmo

1/4 Método que revela la intención

1. Agregar comentarios si son necesarios

2. Transformar comentarios en métodos

3. Los comentarios son ahora código

4. El código se auto-describe

Page 24: Refactoring Workshop - RubyConf Argentina 2014

¿“No más de 5 líneas por método”?

1/4 Método que revela la intención

¡No hay problema!

Page 25: Refactoring Workshop - RubyConf Argentina 2014

El patrón más sencillo

1/4 Método que revela la intención

y difícil a la vez

Page 26: Refactoring Workshop - RubyConf Argentina 2014

Sin Tests no hay refactorización

O van a tener que escuchar, con razón, “no arregles lo que no está roto”

Prerequisito: hay tests

Page 27: Refactoring Workshop - RubyConf Argentina 2014

Prerequisito: hay tests

¡Estos karting van a 200!

Page 28: Refactoring Workshop - RubyConf Argentina 2014

Prerequisito: hay tests

Parece que este 747 no se mueve.

Page 29: Refactoring Workshop - RubyConf Argentina 2014

Sens

ació

n de

Vel

ocid

ad

0

50

100

150

200

Velocidad Real

0 250 500 750 1000

747

Kart

Prerequisito: hay tests

Page 30: Refactoring Workshop - RubyConf Argentina 2014

Prerequisito: hay tests

Sens

ació

n de

Vel

ocid

ad

0

50

100

150

200

Velocidad Real

0 250 500 750 1000

TDD-refactor

Deploy!

Page 31: Refactoring Workshop - RubyConf Argentina 2014

Objeto de Caso Especial (Nulo)

2/4 Objetos de Caso Especial

El objeto más común del mundo Ruby:

nil

Page 32: Refactoring Workshop - RubyConf Argentina 2014

Problema 1: origen de nil

2/4 Objetos de Caso Especial

session[:current_user] # => nil session[:current_uzer] # => nil if (false) then 1 end # => nil empty_method() # => nil

Page 33: Refactoring Workshop - RubyConf Argentina 2014

Problema 1: origen de nil

2/4 Objetos de Caso Especial

Undefined method `title' for nil:NilClass

¿Viene de un blog post, un producto, o una noticia?

Page 34: Refactoring Workshop - RubyConf Argentina 2014

2/4 Objetos de Caso Especial

def blog_post Post.find(params[:id]) || :no_post end blog_post.title

Undefined method `title' for no_post:Symbol

Problema 1: mejor retornar un símbolo

Page 35: Refactoring Workshop - RubyConf Argentina 2014

Problema 2: condicionales

2/4 Objetos de Caso Especial

if blog_post “Ver #{blog_post.title}” else ‘Ver todos los posts' end

Más imperativo que orientado a objetos.

Fácil de olvidar.

Page 36: Refactoring Workshop - RubyConf Argentina 2014

Solución: retornar un Objeto

2/4 Objetos de Caso Especial

class NullPost def title; “todos”; end end

def blog_post Post.find(params[:post_id]) || NullPost.new end

“Ver #{blog_post.title}” # WIN

Page 37: Refactoring Workshop - RubyConf Argentina 2014

3/4 Reemplazar Método con Objeto Método

def row_per_day_format(file_name) file = File.open file_name, 'r:ISO-8859-1' # hash[NivelConsistencia][date] = [[value, status]] hash = { '1' => {}, '2' => {} } dates = [] str = ''

CSV.parse(file, col_sep: ';').each do |row| next if row.empty? next if row[0] =~ /^\/\// date = Date.parse(row[2]) (13..43).each do |i| measurement_date = date + (i-13)

# If NumDiasDeChuva is empty it means no data

Page 38: Refactoring Workshop - RubyConf Argentina 2014

3/4 Reemplazar Método con Objeto Método

Reemplazar Método con Objeto Método

1. Crear una clase con los mismos argumentos de inicialización que el método

2. Copiar y pegar el método en la nueva clase, sin argumentos

3. Reemplazar el método original con un llamado a la nueva clase

4. Aplicar “Método que Revela la Intención”. Voilà.

Page 39: Refactoring Workshop - RubyConf Argentina 2014

1. Nueva clase con mismos argumentos

class FormatAtoB def initialize(file_name) @file_name = file_name end end

3/4 Reemplazar Método con Objeto Método

Page 40: Refactoring Workshop - RubyConf Argentina 2014

2. Copiar y pegar el cuerpo

class FormatAtoB def initialize(file_name) @file_name = file_name end

def row_per_day_format file = File.open file_name, 'r:ISO-8859-1' # …

3/4 Reemplazar Método con Objeto Método

Page 41: Refactoring Workshop - RubyConf Argentina 2014

3. Reemplazar llamada original

def row_per_day_format(file_name) FormatAtoB.new(file_name). row_per_day_format end

3/4 Reemplazar Método con Objeto Método

Page 42: Refactoring Workshop - RubyConf Argentina 2014

4. Aplicar “Método que Revela la Intención”

class FormatAtoB def initialize(file_name) @file_name = file_name end

def row_per_day_format load_file_a format_data end …

3/4 Reemplazar Método con Objeto Método

Page 43: Refactoring Workshop - RubyConf Argentina 2014

3/4 Reemplazar Método con Objeto Método

Reemplazar Método con Objeto Método

1. Crear una clase con los mismos argumentos de inicialización que el método

2. Copiar y pegar el método en la nueva clase, sin argumentos

3. Reemplazar el método original con un llamado a la nueva clase

4. Aplicar “Método que Revela la Intención”. Voilà.

Page 44: Refactoring Workshop - RubyConf Argentina 2014

Objetos Servicio

Decoupling different concerns from chubby classes

4/4 Objetos Servicio

Page 45: Refactoring Workshop - RubyConf Argentina 2014

Si agregamos nueva funcionalidad a un objeto existente

• Se acopla a nuevas dependencias

• Pierde cohesión

• Los tests se tornan más complejos y lentos

• La descripción del objeto incluye “y"/"o" (SRP)

4/4 Objetos Servicio

Page 46: Refactoring Workshop - RubyConf Argentina 2014

Modelando nuevo comportamiento

4/4 Objetos Servicio

Page 47: Refactoring Workshop - RubyConf Argentina 2014

• Si fuera un concepto del dominio del problema es un nuevo Modelo (una Entidad).

• Si es sólo un proceso o algoritmo (sin estado),es un nuevo Servicio.

Términos del libro “Domain Driven Design”.

4/4 Objetos Servicio

Modelando nuevo comportamiento

Page 48: Refactoring Workshop - RubyConf Argentina 2014

Próximos Pasos

• Envíen Pull Requests en GitHub

• Es una mina de oro para enseñar y aprender

• Eligen proyectos y mentores como en un supermercado eligen galletitas

Próximos Pasos

Page 49: Refactoring Workshop - RubyConf Argentina 2014

Próximos Pasos: las 4 reglas

• Clases de a lo sumo 100 líneas

• Métodos de a lo sumo 5 líneas

• Métodos con 4 argumentos como máximo

• Un controlador instancia sólo una variable de instancia

Próximos Pasos

Page 50: Refactoring Workshop - RubyConf Argentina 2014

Porqué Refactorizar

No sólo sobre estética (aunque es consecuencia)

También conocimiento compartido,encontrar bugs, y performance.

Próximos Pasos

Page 51: Refactoring Workshop - RubyConf Argentina 2014

Porqué Refactorizar

Trabajamossobre las herramientas con que trabajamos.

Somos usuarios y creadores.

Próximos Pasos

Page 52: Refactoring Workshop - RubyConf Argentina 2014

Porqué Refactorizar

Si tengo un sesgo, elijo “over-engineering".

Porque “Under-engineering” es caro, riesgoso y superpoblado.

Próximos Pasos

Page 53: Refactoring Workshop - RubyConf Argentina 2014

¡Gracias!

Preguntas bienvenidas.