Código limpio: El malvado argumento booleano

Código limpio: El malvado argumento booleano

En la última entrada repasamos qué debemos tener en cuenta cuando estamos definiendo nuestros argumentos, pero hemos querido dedicar una entrada específica para profundizar en los malvados argumentos booleanos.

Esta es la quinta entrega de una serie en la que analizamos el libro clean code de Robert C Martin publicado en el año 2008. Si quieres puedes ir a ver el índice de la serie. También puedes ver la versión en video de esta entrada en nuestro canal de youtube.

Veamos los motivos por los que deberías evitar los argumentos booleanos.

Confunden al lector

En general los argumentos booleanos confunden al lector. Veamos un ejemplo, con una clase del componente Config de Symfony. Esta clase en concreto es la responsable de buscar un fichero de un determinado nombre en un array de paths definidos en los que se podría encontrar.

namespace Symfony\Component\Config;

/**
 * FileLocator uses an array of pre-defined paths to find files.
 */
class FileLocator implements FileLocatorInterface
{
    // ..
    public function locate(string $name, string $currentPath = null, bool $first = true)
    {
        // ..
    }
   // ..
}

¿Sabrías decirme qué hace exactamente el tercer argumento? Quizá tengas la siguiente intuición, si le pasamos true probablemente devolverá la primera coincidencia, pero ¿qué ocurre si le paso un false?. Si realmente quiero entender esta función voy a necesitar ir al código y leer que es lo que hace.

Una vez que ya nos hemos leído el código entendemos que el funcionamiento es el siguiente:

  • si le paso un true, me devolverá la primera coincidencia
  • si le paso un false me devolverá todas.

¿No se lo pondríamos mucho más fácil al lector si somos explícitos de esta forma?

namespace Symfony\Component\Config;

/**
 * FileLocator uses an array of pre-defined paths to find files.
 */
class FileLocator implements FileLocatorInterface
{
    // ..
    public function locateAll(string $name, string $currentPath = null)
    {
        // ..
    }

    public function locateFirst(string $name, string $currentPath = null)
    {
        // ..
    }
   // ..
}

Como siempre esto no significa que debamos duplicar el código, ya que probablemente podemos encontrar la forma de que uno llame a otro o utilizar funciones privadas más pequeñas, para evitar cualquier duplicidad.

Hace dos cosas

En muchas ocasiones un argumento booleano indica que la función hace dos cosas diferentes. Como ya vimos en la entrada dedicada a funciones, estas deberían hacer una única cosa y deberían hacerla bien.

Veamos un ejemplo con el componente DomCrawler de Symfony. Este componente permite crear un cliente que simula ser un navegador y que se utiliza en pruebas funcionales y para tareas de scrapping.

La función que vamos a ver se llama después de haber ejecutado una query sobre un documento HTML $message = $crawler->filterXPath('//body/p')->text();

namespace Symfony\Component\DomCrawler;

/**
 * Crawler eases navigation of a list of \DOMNode objects.
 */
class Crawler implements \Countable, \IteratorAggregate
{
    // ..
    /**
     * Returns the text of the first node of the list.
     *
     * Pass true as the second argument to normalize whitespaces.
     */
    public function text(string $default = null, bool $normalizeWhitespace = true)
    {
        // ..
    }
    // ..
}

¿No da la sensación de que el segundo argumento responde a una necesidad del programador que a una decisión de diseño? ¿Quién realizaría un diseño así? Obviamente el siguiente ejemplo es mejor.

namespace Symfony\Component\DomCrawler;

/**
 * Crawler eases navigation of a list of \DOMNode objects.
 */
class Crawler implements \Countable, \IteratorAggregate
{
    // ..
    public function text(string $default = null)
    {
        // ..
    }

    public function normalizeWhitespace(string $text)
    {
        // ..
    }
    // ..
}

Y una vez realizado este diseño, ¿no parece evidente que normalizeWhitespace debería ir en otra clase? esto lo veremos más adelante en la entrada dedicada a las clases.

¿Quieres ser una bestia del desarrollo de software?
¡Continúa con nosotros en YouTube!

Todas las semanas un nuevo vídeo sobre desarrollo de software en tu bandeja de entrada.

Tranquilo, no te vamos a enviar spam.