¿a qué huele tu código? afinando nuestro olfato

28
¿A qué huele tu código? Afinando nuestro olfato Code Smells Rubén Bernárdez @rubenbpv www.rubenbernardez.com

Upload: ruben-bernardez

Post on 05-Dec-2014

2.529 views

Category:

Technology


2 download

DESCRIPTION

Repaso por los principales olores de código que podemos encontrar en el desarrollo de software. Obtenidos a partir del libro "Refactoring: Improving the design of existing code" de Martin Fowler

TRANSCRIPT

Page 1: ¿A qué huele tu código? Afinando nuestro olfato

¿A qué huele tu código?

Afinando nuestro olfatoCode Smells

Rubén Bernárdez @rubenbpv

www.rubenbernardez.com

Page 2: ¿A qué huele tu código? Afinando nuestro olfato

¿Qué es un Code Smell?

• Son todos los síntomas que podemos encontrar en el código fuente de un sistema que indican que muy probablemente existan problemas más profundos de calidad de código, de diseño o de ambos.

• Es difícil definir si el código es malo o bueno, o cuando deberíamos cambiarlo.

• Un buen desarrollador tiene el “olfato fino”.

Page 3: ¿A qué huele tu código? Afinando nuestro olfato

Es VITAL aprender a detectar y reconocer el olor de nuestro propio código

Page 4: ¿A qué huele tu código? Afinando nuestro olfato

¿Qué hacer cuando se detecta un ‘Code Smell’?

Pero antes, proteger con test automatizados aquella parte de código que se va a modificar. .

Page 5: ¿A qué huele tu código? Afinando nuestro olfato

¿Qué es la refactorización?

• Refactorizar significa cambiar el código internamente sin alterar su funcionalidad externa. En general, con motivos de mejorar el diseño y obtener un código mas simple.

• Refactorización enseña técnicas para descubrir el código de mala calidad y técnicas para cambiarlo.

Page 6: ¿A qué huele tu código? Afinando nuestro olfato

Code Smells

Page 7: ¿A qué huele tu código? Afinando nuestro olfato

#0 Código duplicadoDuplicate code

• El peor olor de todos, el rey de la pestilencia!

• Un código duplicado 5 veces con un bug, es tener 5 bugs en tu software.

• Si algún día quieres mejorar lo que hace un código duplicado, tienes que modificar cada parte duplicada de tu código.

• Más líneas de código, más probabilidades de error.

POSIBLE SOLUCIÓN

• Sacar el código duplicado a un método o clase nueva y utilizarlo en todos aquellos lugares que se necesita.

Page 8: ¿A qué huele tu código? Afinando nuestro olfato

#1 Código muerto

• Aparición de código que no se utiliza, probablemente procedente de versiones anteriores, prototipos o pruebas.

• También incluye aquel código comentado que se dejó por si alguna día…

POSIBLE SOLUCIÓN

• Revisar si realmente se debe de usar, sino, borrarlo (para recuperarlo algún día siempre está control de código fuente)

Page 9: ¿A qué huele tu código? Afinando nuestro olfato

#2 Métodos largosLong method

• ¿A quién le gusta un método de decenas o cientos de líneas?

• Dificulta muchísimo su compresión

• Seguramente estará realizando más de una responsabilidad.

• El extraer un trozo de código a un método y llamarlo, no penalizará la velocidad de tu programa.

• Tu código es menos reutilizable.

POSIBLE SOLUCIÓN

• Detectar las diferentes responsabilidades y sacarlas a métodos o clases nuevos.

• Antes de ello intentar eliminar variables temporales por querys.

Page 10: ¿A qué huele tu código? Afinando nuestro olfato

#3 Clases largasLarge class

• Ocurre lo mismo que con los métodos largos.

• Seguramente esté encargándose de más de una responsabilidad.

• La pestilencia nº1 #0 (código duplicado) no estará muy lejos si es que no le ha afectado ya…

• Un síntoma es cuando la case tiene demasiados atributos.

POSIBLE SOLUCIÓN

• Detectar las diferentes responsabilidades y sacarlas a clases nuevas colaboradoras.

Page 11: ¿A qué huele tu código? Afinando nuestro olfato

#4 Lista larga de parámetrosLong parameter list

• Una lista larga de parámetros es difícil de comprender y sin muchos son del mismo tipo, fácil de equivocarte al usar el método.

POSIBLE SOLUCIÓN

• Encapsular los parámetros relacionados en objetos tipados o reemplazar parámetro por un métodos.

• NO usar datos globales sólo para traspasar datos.

Page 12: ¿A qué huele tu código? Afinando nuestro olfato

#5 Cambios divergentesDivergent Change

• Cuando una única clase que tiene que modificarse de diferentes maneras por distintos motivos (más de una responsabilidad).

• Esta mala señal indica que la clase no es cohesiva.

POSIBLE SOLUCIÓN

• Extraer las diferentes responsabilidades a distintas clases.

Page 13: ¿A qué huele tu código? Afinando nuestro olfato

#6 Cirugía a escopetazosShotgun Surgery

• Un determinado tipo de modificación en el sistema lleva repetidamente a la realización de cambios pequeños en muchas clases.

• La “cirugía a escopetazos" generalmente implica una sola idea o función lógica distribuida por varias clases.

POSIBLE SOLUCIÓN

• Trata de corregir ese problema reuniendo todas las partes del código que tienen que modificarse en una única clase cohesiva.

• Es recomendable tener algo de “cambios divergentes” que este olor, ya que será más fácil de tratar.

Page 14: ¿A qué huele tu código? Afinando nuestro olfato

#7 Envidia de característicasFeature Envy

• Un método en la ClassA parece más interesado por la ClassBque por su propia clase.

• Generalmente la envidia suele venir por los datos de otra clase.

• La "envidia" de la ClassA por los recursos de la ClassB es una indicación del acoplamiento fuerte de la ClassA con la ClassB.

POSIBLE SOLUCIÓN

• Mover la funcionalidad del método de ClassA a ClassB, que ya está más cerca de la mayoría de datos implicados en la tarea.

• Si no todo el método tiene “envidia”, extraer a un método el código envidioso y mover sólo ese método a ClassB.

Page 15: ¿A qué huele tu código? Afinando nuestro olfato

#8 Grupos de datosData Clumps

• Uso de un mismo conjunto de variables o propiedades en diferentes lugares en vez de crear una clase apropiada para almacenar los datos, lo que a su vez provoca el incremento de parámetros en métodos y clases.

POSIBLE SOLUCIÓN

• Aglutinar los parámetros en uno o varios objetos lógicos y pasarlos como nuevos parámetros.

public void DarDeAltaNuevoCliente( stringnombre, string apellido1, stringapellido2, string direccion, stringcodigoPostal)

{

}

Public void DarDeAltaNuevoCliente(

Cliente cliente)

{

}

Ejemplo:

Page 16: ¿A qué huele tu código? Afinando nuestro olfato

#9 Obsesión por primitivosPrimitive obsession

• Muchas personas tienen la obsesión de negarse a utilizar objetos pequeñitos para modelar algunos comportamientos.

• Por ejemplo: Un número de teléfono, igual sale más rentable utilizar un objeto pequeñito que modele el comportamiento que tener que lidiar con una cadena de caracteres para modelarlo y tener que parsearla y tratarla.

POSIBLE SOLUCIÓN

• Crear una nueva clase con los primitivos con algo en común, usa enumerados, subclases o el patrón State o Strategy.

Page 17: ¿A qué huele tu código? Afinando nuestro olfato

#10 Sentencias switchSwitch statements

• La duplicación de código no está lejos con este tipo de sentencias, puedes llegar a verlo varias veces en un mismo sitio. Si añades una condición a un switch en un sitio, tendrás que propagarlo donde se haya repetido.

POSIBLE SOLUCIÓN

• Generalmente, utilizar polimorfismo.

Page 18: ¿A qué huele tu código? Afinando nuestro olfato

#11 Jerarquías de herencias paralelasParallel Inheritance Hierarchies

• Es un caso especial de la cirugía a escopetazos (shotgunsurgery).

• Paralelismo que aparece cuando cada vez que se crea una instancia de una clase es necesario crear una instancia de otra clase, evitable uniendo ambas en una única clase final.

POSIBLE SOLUCIÓN

• Mover los métodos y campos de una jerarquía de objetos a otra para que la jerarquía de objetos referida desaparezca.

Page 19: ¿A qué huele tu código? Afinando nuestro olfato

#12 Clase perezosaLazy class

• Toda clase debe de tener definida una responsabilidad, una razón para existir. Si no es así, ¿para qué sirve esa clase?

• Cada clase que crees cuesta dinero para mantenerla y comprenderla.

POSIBLE SOLUCIÓN

• Una clase sin apenas responsabilidad hay que dotarla de sentido, o bien eliminarla.

Page 20: ¿A qué huele tu código? Afinando nuestro olfato

#13 Generalización especulativaSpeculative generality

• Este olor es bastante general, y siempre comienza por las palabras de: "Algún día necesitaré que ..." o “… por si algún día lo necesito”.

• En ese momento suena la señal de alarma. Tienes que tener en cuenta que si vas a montar una infraestructura para hacer cosas complejas, puede ser compleja de comprender y eso tiene un coste también. Si lo vas a tener que utilizar algún día, no te preocupes; no hay plazo que no se cumpla.

POSIBLE SOLUCIÓN

• Complica tu solución sólo lo necesario y escribe la funcionalidad que te hace falta para tus necesidades actuales y no para las futuras.

Page 21: ¿A qué huele tu código? Afinando nuestro olfato

#14 Campo temporalTemporary field

• Se salta el principio de encapsulamiento y ocultación de variables haciendo que éstas pertenezcan a la clase cuando su ámbito debería ser exclusivamente el método que las usa.

POSIBLE SOLUCIÓN

• Si una propiedad sólo se una para un par de métodos, conviértela en un parámetro de esos métodos.

• Otra alternativa es sacar a una clase nueva los campos y métodos que los usan.

Page 22: ¿A qué huele tu código? Afinando nuestro olfato

#15 Mensajes encadenadosMessage Chains

• Cuando se realiza una cadena de llamadas a métodos de clases distintas utilizando como parámetros el retorno de las llamadas anteriores, como A.getB().getC().getD().getTheNeededData(), que dejan entrever un acoplamiento excesivo de la primera clase con la última.

• Cualquier cambio en las relaciones intermedias causa cambios en el cliente.

• No se refiere a las API’s fluidas.

POSIBLE SOLUCIÓN

• Mover los métodos a niveles anteriores o esconder el uso del delegado para minimizar la cadena de llamadas.

Page 23: ¿A qué huele tu código? Afinando nuestro olfato

#16 IntermediarioMiddle man

• Este es quien se ocupa de delegar las llamadas, y simplemente hace eso.

• Exploras la clase, y ves que solamente esta llamando a un método y delegando la llamada.

• Sin intermediarios y burocracia se vive mucho mejor.

• Cuestiona la necesidad de tener clases cuyo único objetivo es actuar de intermediaria entre otras dos clases.

POSIBLE SOLUCIÓN

• Saltarte al intermediario y usar la clase que implementa la acción directamente. Usar “Inline Method” para unos pocos métodos o convertir el intermediario en una subclase del objeto real.

Page 24: ¿A qué huele tu código? Afinando nuestro olfato

#17 Intimidad inapropiadaInappropriate intimacy

• Se produce cuando dos clases comienzan a conocer demasiados detalles una de otra.

POSIBLE SOLUCIÓN

• Mover métodos y propiedades de una clase a otra para eliminar la intimidad.

• Cambiar la comunicación bidireccional por unidireccionar.

• Con clases con intereses comunes, extraer dichos intereses comunes a una clase externa.

Page 25: ¿A qué huele tu código? Afinando nuestro olfato

#18 Clases alternativas con diferentes interfacesAlternative Classes with Different Interfaces

• Indica la ausencia de interfaces comunes entre clases similares.

• También aplicable a métodos.

• Por ejemplo: CalcularFactura (); y FacturaCalcula(). Es probable que hagan lo mismo, pero sin embargo como eliges uno u otro?.

POSIBLE SOLUCIÓN

• Esta muy claro que si el código es duplicado, debe ser eliminado y si no, podemos renombrar métodos o utilizar sobrecarga u otros mecanismos que nos ayuden a entenderlo mejor.

Page 26: ¿A qué huele tu código? Afinando nuestro olfato

#19 Rechazo del legadoRefused bequest

• Cuando una subclase 'rechaza' métodos o propiedades heredadas, atentando directamente contra la POO.

• Las clases que heredan de otra, heredan sus campos y sus métodos, pero ¿Qué ocurre si no quieren o no necesitan todo lo que se les da?

• No importa negar implementaciones, pero si interfaz legada.

POSIBLE SOLUCIÓN

• Baja los métodos no comunes del padre al hijo que lo necesite para que el padre sólo tenga los métodos comunes.

• Elimina la herencia y haz que las clases colaboren.

Page 27: ¿A qué huele tu código? Afinando nuestro olfato

#20 ComentariosComments

• Hay que tener un poco de cuidado al interpretar estas palabras, los comentarios son útiles, pero usados con sabiduría, no como un desodorante para tapar algo que no esta bien hecho (código malo).

• En cuanto hayamos mejorado nuestro código y hayamos localizado los olores de nuestro código y los hayamos refactorizado, nos daremos cuenta que muchos de ellos sobran.

• TIP: Cuando sientes la necesidad de escribir un comentario, primero trata de refactorizarlo para que cualquier comentario resulte superfluo.

POSIBLE SOLUCIÓN

• Extraer el trozo de código comentado a un método y darle un buen nombre.

• Usa comentarios en zonas que no estés seguro del código o que quieras recordar algo para futuras modificaciones.

Page 28: ¿A qué huele tu código? Afinando nuestro olfato

Referencias

• Refactoring: Improving the Design of Existing Code

• Refactoring to Patterns

• xUnit Test Patterns: Refactoring Test Code

• Smells to refactoring

• http://www.refactoring.com