[Clean Code] Parámetros boleanos (Flags) en funciones

El otro día cuando publiqué este post, alguien me comentó por Twitter que se podía usar un parámetro boleano (Flag) en la función… y comenté que escribiría otro post de por qué debemos evitar parámetros boleanos en nuestras funciones.

Imaginad que en el proyecto actual en el que estamos trabajando se requiere el uso de una caché de almacenamiento, una será persistente y otra temporal (disco o a memoria) y se ha implementado tal cual se muestra a continuación:

public class CacheSystem

{

    public void Add(object key, object value, bool toDisk)

    {

        if (toDisk)

        {

            ///To Disk

        }

        else

        {

            ///To Memory

        }

    }

}

¿Por qué esto está mal y debo evitarlo?

Primer punto a tener en cuenta y muy importante, “Una función sólo debería hacer una única cosa” y en nuestro caso está haciendo 2, escribir a disco o a memoria dependiendo de sí el llamante nos pasa true o false.

Segundo punto a tener en cuenta, mirad como quedaría una llamada a nuestra función en otra parte de la aplicación:

cacheSystem.Add("User", user, true);

Claramente se puede ver que estamos añadiendo algo a una caché pero, ¿Que nos está diciendo ese true? No queda muy claro ¿verdad? No hace nuestro código más legible sino todo lo contrario, dificulta su comprensión.

¿Como lo puedo solucionar?

En este caso hay 2 soluciones, empezaré por la más sencilla:

Partir la función en 2 funciones
public class CacheSystem

{

    public void AddToDisk(object key, object value)

    {

        

    }

 

    public void AddToMemory(object key, object value)

    {

 

    }

}

 

cacheSystem.AddToDisk("User", user);

cacheSystem.AddToMemory("User", user);

Creo que queda bastante claro ¿verdad? Diferenciamos la escritura a disco y a memoria. Ahora cada función hace sólo una cosa.

Crear implementaciones concretas

En este caso que hemos expuesto (No siempre se dará y entonces aplicaremos la primera solución) podemos crear una abstracción de la caché, bien con una clase abstracta o una interfaz:

public interface ICache

{

    void Add(object key, object value);

}

En base a esta interfaz, creamos 2 implementaciones:

public class DiskCache : ICache

{

    public void Add(object key, object value)

    {

        

    }

}

 

public class MemoryCache : ICache

{

    public void Add(object key, object value)

    {

        

    }

}

Y en nuestra aplicación, usar la que más nos convenga, por ejemplo, en las pruebas unitarias podemos usar siempre memoria que es más rápida. Esto se puede acompañar de un contenedor de dependencias y delegar en el la responsabilidad de la creación de dicha caché, que además podremos parametrizar vía código o fichero.

Espero que os haya gustado.

5 comentarios en “[Clean Code] Parámetros boleanos (Flags) en funciones”

  1. Muy bueno, Luis, además y por poner todavía más inconvenientes al método “malo”, si mañana hay un tercer método de guardar la cache (p. ej. a base de datos) directamente el método ya no vale, hasta donde yo sé no hay booleans de 3 valores ;-). A mi me ha pasado muchas veces esto y termino poniendo un enumerado (cuando en realidad la solución es la que tú planteas).

    Otro problema que me encuentro es el booleano de un sólo valor. Por ejemplo, GetAllCustomers(boolean onlyWithAddress), realmente si pasas false quieres todos y se pasas true quieres sólo los clientes con direcciones. ¿No sería mejor 2 métodos? GetAllCustomers y GetCustomersWithAddress?

    Pues eso, algo tan sencillo como un booleano, mira que da juego 😉

    Un saludo.

  2. Mira que cuesta poco hacer bien o mejor las cosas. Cada vez que me tropiezo un código como el del ejemplo me lo apunto para esos días de poco trabajo hacer la refactorización a la solución uno. Normalmente la dos suele implicar más cambios y nos siempre es posible, o por lo menos en los proyectos en los que he estado metido.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *