Ir al contenido principal

Conceptos generales de refactoring

Código Limpio (Clean code)

El propósito general del refactoring es luchar con la deuda técnica. Este transforma el lío en código limpio y de diseño simple.
Pero qué es código limpio. Estos son algunas de sus características:

  • Es obvio para otros programadores
  • No contiene duplicación
  • Contiene el número mínimo de clases y otras partes móviles
  • Pasa todos los tests
  • Es más fácil y barato de mantener

Deuda técnica

Todos hacen su mejor esfuerzo por hacer código excelente desde el inicio. Entonces, ¿En qué punto nuestro código se "ensucia"?

Imaginemos la siguiente situación
Si pedís un préstamo de un banco, esto te permite realizar compras más rápido. Pagas más por acelerar el proceso; no solo paga el capital, sino también el interés adicional del préstamo. No hace falta decir que incluso puede acumular tanto interés que la cantidad de interés exceda su ingreso total, haciendo imposible el reembolso completo.

Lo mismo puede suceder con el código. Puede acelerar temporalmente sin escribir pruebas para nuevas funciones, pero esto ralentizará gradualmente su progreso todos los días hasta que finalmente pague la deuda escribiendo pruebas.

Causas de la deuda técnica
  • Presión del negocio
  • Falta de tests
  • Falta de documentación
  • Falta de interacción entre los miembros del equipo
  • Falta de comprensión de las consecuencias de la deuda técnica
  • Refactorización tardía
  • Desarrollo prolongados en ramas separadas
  • La falta de supervisión de cumplimiento
  • Incompetencia

Cuándo refactorizar

Siempre.
Cuando agregas una nueva funcionalidad.
Cuando estás arreglando un bug.
Cuando estas haciendo un code review.

Cómo refactorizar

Refactorizar debería hacerse como una serie de cambios pequeños, los cuales hacen al código existente pequeñas mejoras mientras no cambie el comportamiento del software.

Checklist para refactorizar de una manera correcta.
  • El código debe volverse limpio.
  • No deben crearse nuevas funcionalidades mientras refactorizamos.
  • Todas las pruebas deben ser exitosas luego de la refactorización

Code Smells

Los code smells son malas prácticas que hacen que nuestro código "apeste". No necesariamente son errores sino defectos que pueden ser clasificados en:

Bloaters

Los bloaters son códigos, métodos y clases que han aumentado a proporciones tan gigantescas que es difícil trabajar con ellos. Por lo general, estos code smells no surgen de inmediato, sino que se acumulan con el tiempo a medida que evoluciona el programa (y especialmente cuando nadie hace un esfuerzo por erradicarlos).

Object-Orientation Abusers

Todos estos code smells son una aplicación incompleta o incorrecta de los principios de programación orientada a objetos.

Change Preventers

Estos code smells significan que si necesita cambiar algo en un lugar de su código, también debe realizar muchos cambios en otros lugares. Como resultado, el desarrollo de programas se vuelve mucho más complicado y costoso.

Dispensables

Un dispensable es algo inútil e innecesario cuya ausencia haría el código más limpio, más eficiente y más fácil de entender.

Couplers

Todos los code smells de este grupo contribuyen a un acoplamiento excesivo entre clases o muestran lo que sucede si el acoplamiento se reemplaza por una delegación excesiva.

Técnicas de refactorización

Hay diferentes categorías de técnicas de refactorización:

Componiendo métodos correctamente

Gran parte de la refactorización se dedica a componer correctamente los métodos. En la mayoría de los casos, los métodos excesivamente largos son la raíz de todos los males. Los caprichos del código dentro de estos métodos ocultan la lógica de ejecución y hacen que el método sea extremadamente difícil de entender e incluso más difícil de cambiar.

Las técnicas de refactorización de este grupo agilizan los métodos, eliminan la duplicación de código y allanan el camino para futuras mejoras.

Moviendo las funcionalidades entre objetos

Incluso si ha distribuido la funcionalidad entre diferentes clases de una manera menos que perfecta, todavía hay esperanza.

Estas técnicas de refactorización muestran cómo mover de forma segura la funcionalidad entre clases, crear nuevas clases y ocultar los detalles de implementación del acceso público.

Organizando la información

Estas técnicas de refactorización ayudan con el manejo de datos, reemplazando primitivas con una rica funcionalidad de clase. Otro resultado importante es desenredar las asociaciones de clases, lo que hace que las clases sean más portátiles y reutilizables.

Simplificando expresiones condicionales

Los condicionales tienden a complicarse cada vez más en su lógica con el tiempo, y existen aún más técnicas para combatir esto también.

Simplificando las llamadas a métodos

Estas técnicas hacen que las llamadas a métodos sean más simples y fáciles de entender. Esto, a su vez, simplifica las interfaces para la interacción entre clases.

Lidiando con la Generalización

La abstracción tiene su propio grupo de técnicas de refactorización, principalmente asociadas con mover la funcionalidad a lo largo de la jerarquía de herencia de clases, crear nuevas clases e interfaces y reemplazar la herencia con delegación y viceversa.

Extraído de la genial página https://refactoring.guru/refactoring