Fundamentos de la Refactorización
-
Upload
javier-perez -
Category
Technology
-
view
552 -
download
1
description
Transcript of Fundamentos de la Refactorización
Fundamentos de la Refactorización
Marcos MontañoJavier Pérez
https://bitbucket.org/jperezq/refactoring-fundamentals
http://bit.ly/1gVzxcI
Código de ejemplo
“The process of changing a software system in such a way that it does not alter the external behaviour of the code, yet improves its internal structure.”
Martin Fowler, “Refactoring: Improving the Design of Existing Code”, Addison-Wesley,1999.
El proceso de cambiar un sistema de software de manera que no se altere el comportamiento externo del código, pero si se mejore su estructura.
¿Qué es la refactorización?
Mejora la calidad del código:◦ Reduce la duplicidad◦ Mejora la mantenibilidad◦ Acelera la implementación de nueva
funcionalidad◦ Previene la permanencia de las malas practicas
en el código (code smells)
¿Por qué refactorizar?
Código duplicado Métodos largos Clases grandes Largas listas de parámetros (argumentos) Generalización innecesaria Atributos temporales Middle Man Intimidad inapropiada Clases tontas Comentarios excesivos
¿Cuáles son las malas prácticas?
No hay un “tiempo de refactorización” , es un hábito
Antes de agregar nueva funcionalidad◦ Encontrar código a modificar◦ Reparar el código para prevenir mas repetición
Cuando necesitas arreglar un bicho◦ Hace el código mas compresible◦ Ayuda a encontrar el bicho
Durante los Code Reviews◦ Un nuevo enfoque ve las cosas de forma diferente◦ Una revisión mas efectiva
¿Cuándo refactorizar?
Añadir nuevas capacidades al sistema
Añadir nuevos tests Mantener los tests
corriendo
No agrega nueva funcionalidad
No agrega tests (pero pueden haber cambios menores)
Reestructura el código para eliminar redundancia
Añadir nueva funcionalidad VS Refactorización
A un cliente técnico, no es difícil indicarle los beneficios
A un cliente enfocado en la calidad, hacer énfasis en aspectos de calidad◦ Presentarlo como un proceso de revisión
A un cliente enfocado en los plazos, no le digas◦ Encuentra una manera de integrarlo en tu trabajo
cotidiano◦ Ahorra tiempo, pero algunos de los clientes no lo
notaran
¿Cómo lo vendes?
Tests pasando La aplicación funcionando Necesitamos poder probar que no rompimos
nada con la refactorización
NUNCA refactorizar una aplicación rota
¿Qué necesitas para comenzar?
Ciclo de refactorización
Partimos de un sistema que representa la simulación de una red local. El equipo de desarrollo inicial ha trabajado en satisfacer muy rápidamente los requerimientos iniciales y ha logrado lanzar la versión 1.4 del sistema; y ésta contiene toda la funcionalidad deseada para la primera etapa.
El cliente ahora quiere funcionalidad nueva y el equipo de desarrollo teme que el diseño actual no sea lo suficientemente flexible.
El problemaBROADCAST PACKET
Red Token Ring
lanSimulation lanSimulation.internalsNetwork
LANSimulation
Packet
Node
lanSimulation.tests
LANTests
El diseño
lanSimulation
lanSimulation.internals
Network
+defaultExample(): Network+isInitialized(): boolean+hasWorkstation(nm: String): boolean+requestWorkstationPrintsDocument()+requestBroadcast(report: Writer)+printOn(buffer: StringBuffer)+printHTML(buffer: StringBuffer)+printXML(buffer: StringBuffer)
LANSimulationPacket
+message_:String+origin_:String+destination_:String
Node
+type_:byte+name_:String+nextNode_:Node
El diseño
Versión 1.0: Impresión básica del documento◦ Las estaciones de trabajo solicitan a la red de trabajo
de Token Ring el entregar un documento a un nodo que representa una impresora.
Versión 1.1: Registro de paquetes enviados◦ Cada vez que un nodo envía un paquete al siguiente
nodo, debería guardarse el evento en un registro. Versión 1.2: Impresión en PostScript
◦ Un paquete puede empezar con “!PS” en cuyo caso las impresoras deberían reconocerlo como PostScript e invocar el trabajo de impresión adecuado.
Funcionalidad existenteVersión 1.4
Versión 1.3: Registro de impresión◦ Las impresoras deberían registrar el autor y el
título del documento que se esta imprimiendo. Versión 1.4: Paquete de difusión
◦ Introduce un nuevo tipo de paquete “BROADCAST” que debería ser aceptado por todos los nodos en la red.
Funcionalidad existenteVersión 1.4
Versión 2.0: Leer desde un archivo◦ Leer la configuración de una red y los trabajos
que se imprimieron desde un archivo XML Versión 2.1: Nodo de acceso
◦ Introducir un nuevo nodo “Gateway”, que puede reconocer todas las direcciones en su subred actual.
Funcionalidad deseada
Versión 2.2: Lista de nodos compilada◦ Usando el paquete Broadcast, el gateway pide
periódicamente a todos los nodos que respondan con su nombre.
Versión 3.0: Interfaz Grafica◦ El sistema debería tener una interfaz grafica que
será capaz de mostrar la animación de lo que esta ocurriendo.
Funcionalidad deseada
lanSimulation
lanSimulation.internals
Network
+defaultExample(): Network+isInitialized(): boolean+hasWorkstation(nm: String): boolean+requestWorkstationPrintsDocument()+requestBroadcast(report: Writer)+printOn(buffer: StringBuffer)+printHTML(buffer: StringBuffer)+printXML(buffer: StringBuffer)
LANSimulationPacket
+message_:String+origin_:String+destination_:String
Node
+type_:byte+name_:String+nextNode_:Node
¿Qué podemos mejorar del diseño?
¡¡¡Manos a la Obra!!!
Se puede encontrar en varias partes de la aplicación codigo duplicado:◦ El codigo de registro se repite 2 veces en el
método “printDocument”◦ El codigo de impresion se repite 3 veces, dos
veces en el método “requestWorkstationPrintsDocument” y una en el método “requestBroadcast”.
Para solucionar esto utilizarmos la técnica Extraer Metodo
Código Duplicado
La clase Network contiene casi toda la logica de la aplicación.
Por ejemplo podemos ver que los métodos que acabamos de extraer utilizan campos internos de Node y Packet.
Eso nos indica que la logica deberia estar en esas clases, para esto utilizarmos la técnica Mover Método
Concentración de Responsabilidades
Todavia se vé que hay lógica duplicada en el código, la forma en la que se navega a través de los nodos hasta circular por la toda la Red
• Se puede ver lógica duplicada en los métodos “requestWorkstationPrintsDocument” y “requestBroadcast”
Aplicaremos Extraer Método para sacar la lógica duplicada y la optimizaremos.
Lógica de Navegación Duplicada
Se puede ver que la lógica de impresión por tipo está duplicada en los metodos "printOn", "printHTMLOn", "printXMLOn".
Para encapsular y aislar comportamiento diferente segun el tipo es recomendabe usar una jerarquía de Clases.
Lógica de Tipos Duplicada
lanSimulation lanSimulation.internals
Network
+defaultExample(): Network+isInitialized(): boolean+hasWorkstation(nm: String): boolean+requestWorkstationPrintsDocument()+requestBroadcast(report: Writer)+printOn(buffer: StringBuffer)+printHTML(buffer: StringBuffer)+printXML(buffer: StringBuffer)
LANSimulation Packet
+message_:String+origin_:String+destination_:String
+getAuthor(): String+getTitle(): String+isPostScript(): boolean
Node
+name_:String+nextNode_:Node+Attribute1
+atDestination(packet: Packet): boolean+atOrigin(packet: Packet): boolean+logPacketPassage(report: Writer)+printDocument(document, report): boolean+printOn(buffer: StringBuffer)+printXMLOn(buffer: StringBuffer)+send(packet, report): boolean
La Refactorización Terminó
A través del trabajo de refactorización hemos facilitado el mantenimiento del sistema y la implementación de nueva funcionalidad.◦ Versión 2.0: Leer desde un archivo◦ Versión 2.1: Nodo de acceso◦ Versión 2.2: Lista de nodos compilada◦ Versión 3.0: Interfaz Grafica
Conclusión
Usar un sistema de versionamiento de código.
Hacer correr los tests constantemente (Después de cada cambio).
Recomendaciones
Código fuente: https://bitbucket.org/jperezq/refactoring-fundamentals
Refactoring Lab Session, Serge Demeyer, Universidad de Antwerp, http://ansymo.ua.ac.be/artefacts/refactoring-lab-session
Refactoring 101, Adam Culp, PHP-ZendCon2013, http://www.slideshare.net/adamculp/refactoring-23666462
Referencias
“Object-Oriented Reengineering Patterns”, Serge Demeyer, Stéphane Ducasse, Oscar Nierstrasz, http://scg.unibe.ch/download/oorp
"Refactoring: Improving the Design of Existing Code", Martin Fowler , Kent Beck , John Brant, http://refactoring.com
Referencias
¡¡¡Gracias!!!