Refactorización: Eliminación De Flag Booleano Con Strategy Pattern

by ADMIN 67 views

¡Hola a todos! Hoy vamos a sumergirnos en una refactorización crucial que implica la eliminación de un flag booleano utilizando el patrón Strategy. Este es un problema común que encontramos en el desarrollo de software, donde un simple booleano termina controlando la lógica de nuestro código, haciéndolo más difícil de mantener y extender. En este caso particular, estamos abordando un flag llamado sendMail: Boolean que afecta la lógica de envío de notificaciones.

El Problema: Flag Booleano como Anti-patrón

Los flags booleanos, aunque parecen inofensivos al principio, pueden llevar a un código confuso y difícil de manejar. Imaginen una función que hace una cosa si el flag es true y otra cosa completamente diferente si es false. A medida que la aplicación crece, estas condiciones pueden multiplicarse, resultando en una función larga y enredada que viola el principio de responsabilidad única (SRP) y el principio abierto/cerrado (OCP) de SOLID.

En nuestro escenario, el flag sendMail: Boolean controla si se envía un correo electrónico o no. Esto significa que la lógica de envío de correos está intrínsecamente ligada al código que utiliza este flag. Si en el futuro queremos agregar otro tipo de notificación, como un mensaje SMS o una notificación push, tendríamos que modificar el código existente, lo cual es riesgoso y puede introducir errores.

La Solución: Patrón Strategy al Rescate

El patrón Strategy es un patrón de diseño de comportamiento que nos permite definir una familia de algoritmos, encapsular cada uno de ellos y hacerlos intercambiables. Esto significa que podemos elegir el algoritmo a utilizar en tiempo de ejecución sin necesidad de modificar el código del cliente. En nuestro caso, cada tipo de notificación (correo electrónico, SMS, push) será una estrategia diferente.

Pasos para la Refactorización

  1. Crear la Interfaz Notifier: Definimos una interfaz llamada Notifier que declara un método sendNotification(). Esta interfaz será la base para todas nuestras estrategias de notificación.

    package domain.notifier
    
    interface Notifier {
        fun sendNotification(message: String)
    }
    
  2. Implementar la Estrategia EmailNotifier: Creamos una clase llamada EmailNotifier que implementa la interfaz Notifier. Esta clase se encargará de enviar notificaciones por correo electrónico.

    package domain.notifier
    
    class EmailNotifier : Notifier {
        override fun sendNotification(message: String) {
            // Lógica para enviar correo electrónico
            println("Enviando correo electrónico: $message")
        }
    }
    
  3. Inyectar la Dependencia Notifier: Modificamos la clase CreateReservationUseCase para que reciba una instancia de Notifier a través de su constructor. Esto se conoce como inyección de dependencias y es un principio clave del diseño de software. Ahora, CreateReservationUseCase no necesita saber cómo se envía la notificación, solo que se envía.

    class CreateReservationUseCase(private val notifier: Notifier) {
        fun execute(reservationDetails: ReservationDetails) {
            // Lógica para crear la reserva
            notifier.sendNotification("Nueva reserva creada: ${reservationDetails.id}")
        }
    }
    
  4. Eliminar el Flag Booleano: ¡Adiós al flag sendMail: Boolean! Ya no es necesario. La lógica de qué tipo de notificación enviar se delega al Notifier inyectado.

Beneficios de la Refactorización

  • Código más limpio y legible: Al eliminar el flag booleano, simplificamos la lógica de nuestro código.
  • Mayor flexibilidad: Podemos agregar nuevas estrategias de notificación sin modificar el código existente.
  • Mejor mantenibilidad: El código es más fácil de entender, modificar y probar.
  • Cumplimiento de los principios SOLID: La refactorización nos ayuda a adherirnos a los principios de diseño SOLID, como el principio de responsabilidad única y el principio abierto/cerrado.

Alcance de la Refactorización

Los archivos afectados por esta refactorización son:

  • domain/notifier/Notifier.kt (Nueva interfaz)
  • domain/notifier/EmailNotifier.kt (Nueva implementación)
  • CreateReservationUseCase.kt (Modificación del constructor)

Definition of Done

Para considerar esta refactorización como completa, debemos asegurarnos de que se cumplen los siguientes criterios:

  • [x] No hay parámetros booleanos que alteren el flujo público.
  • [x] La notificación se delega al patrón Strategy (Notifier).
  • [x] El Pull Request (PR) contiene diffs antes → después que muestran claramente la eliminación del flag.

Ejemplo de Código (Antes y Después)

Para ilustrar mejor el impacto de esta refactorización, veamos un ejemplo de código antes y después.

Antes (con el flag booleano):

class CreateReservationUseCase {
    fun execute(reservationDetails: ReservationDetails, sendMail: Boolean) {
        // Lógica para crear la reserva
        if (sendMail) {
            // Lógica para enviar correo electrónico
            println("Enviando correo electrónico: Nueva reserva creada")
        }
    }
}

Después (con el patrón Strategy):

class CreateReservationUseCase(private val notifier: Notifier) {
    fun execute(reservationDetails: ReservationDetails) {
        // Lógica para crear la reserva
        notifier.sendNotification("Nueva reserva creada: ${reservationDetails.id}")
    }
}

Como pueden ver, el código después de la refactorización es mucho más limpio y conciso. La responsabilidad de enviar la notificación se ha delegado a la clase Notifier, lo que hace que la clase CreateReservationUseCase sea más enfocada y fácil de entender.

Beneficios Adicionales y Casos de Uso

Más allá de la limpieza del código y la adherencia a los principios SOLID, la implementación del patrón Strategy nos abre un abanico de posibilidades. Imaginen que queremos agregar:

  • Notificaciones SMS: Simplemente creamos una nueva clase SmsNotifier que implemente la interfaz Notifier y se encargue de enviar mensajes de texto.
  • Notificaciones Push: De manera similar, podemos crear una clase PushNotifier para enviar notificaciones push a dispositivos móviles.
  • Notificaciones Personalizadas: Podemos incluso crear notificaciones personalizadas basadas en las preferencias del usuario o en el tipo de reserva.

La flexibilidad que nos brinda el patrón Strategy es invaluable para el crecimiento y la evolución de nuestra aplicación.

Conclusión: Un Paso Hacia un Código Más Sólido

En resumen, la eliminación del flag booleano sendMail: Boolean y la implementación del patrón Strategy es un paso significativo hacia un código más sólido, flexible y mantenible. Este tipo de refactorización no solo mejora la calidad del código a corto plazo, sino que también facilita el desarrollo y la evolución de la aplicación a largo plazo. ¡Espero que este ejemplo les haya sido útil y los anime a aplicar estos principios en sus propios proyectos!

¡Anímense a refactorizar su código y a eliminar esos flags booleanos! Verán cómo su código se vuelve más limpio, legible y fácil de mantener. Y recuerden, el patrón Strategy es una herramienta poderosa que pueden utilizar para resolver una variedad de problemas de diseño. ¡Hasta la próxima!