Refactorización: Eliminación De Flag Booleano Con Strategy Pattern
¡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
-
Crear la Interfaz
Notifier
: Definimos una interfaz llamadaNotifier
que declara un métodosendNotification()
. Esta interfaz será la base para todas nuestras estrategias de notificación.package domain.notifier interface Notifier { fun sendNotification(message: String) }
-
Implementar la Estrategia
EmailNotifier
: Creamos una clase llamadaEmailNotifier
que implementa la interfazNotifier
. 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") } }
-
Inyectar la Dependencia
Notifier
: Modificamos la claseCreateReservationUseCase
para que reciba una instancia deNotifier
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}") } }
-
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 alNotifier
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 interfazNotifier
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!