Código limpio: No hables con extraños

Código limpio: No hables con extraños

En la última entrada repasamos qué son las estructuras de datos, en que se diferencian de los objetos y cuándo conviene más utilizar una aproximación u otra.

Esta es la octava 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.

Empezemos describiendo los motivos por los que no deberías hablar con extraños: muchas veces cuando tenemos una clase que a su vez está formada por objetos de otras clases y estas a su vez por otras, tenemos una estructura de clases. Hasta aquí todo bien, pero: ¿qué ocurre cuando estas estructuras se vuelven complejas? Veamos un ejemplo que podría darse en un comando de symfony.

class CustomCommand extends Command
{
    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->getApplication()->getKernel()->getContainer()->getCustomService()->getManager()->execute();

        return 1;
    }
}

Como puedes ver, estamos acoplando de forma innecesaria nuestro código a todas las clases que aparecen en la cadena de llamadas. Cualquier cambio en estas clases o en las relaciones entre ellas podría suponer que nuestro código dejase de funcionar. Para que esto no suceda viene al rescate la ley de demeter.

La ley de demeter

La ley de demeter

La ley de demeter fue descrita por primera vez dentro del proyecto demeter en 1987. Como curiosidad quiero contarte que Demeter, hace referencia a la diosa griega de la agricultura. Querian hacer referencia a algo así como "cultivar" software en contraposición a "construir" el software.

La ley indica que desde un método solo deberías "hablar" con aquellos a quien conozcas bien. Y estos son:

  • Métodos de la misma clase.
  • Métodos de los objetos de la clase.
  • Métodos de los objetos creados en la misma función.
  • Métodos de los objetos pasados como argumento a la función.

¿Y cómo lo soluciono?

Ya hemos detectado que es lo que no debes hacer, te voy a proponer ahora tres opciones a tener en cuenta cuando detectes este problema en tu código.

No hacer nada

La primera es no hacer nada. Es la solución más sencilla, y la peor de las tres que vamos a ver, pero como ya vimos en la entrada sobre los dogmas en el desarrollo de software, si crees que las clases que estás llamando y sus relaciones están muy consolidadas, podrías permitirte el lujo de realizar este tipo de llamadas en cadena.

Usar atajos

La segunda consiste en hacer atajos que permitan evitar estas llamadas encadenadas. Esta es una solución bastante rápida, que te puede permitir salir del paso en algún momento.

Por ejemplo en CustomService podríamos añadir el método executeManager.

class CustomService
{
    public function executeManager(): void
    {
        $this->getManager()->execute();
    }
}

Esta solución como puedes imaginarte tampoco es la mejor. Te permite abstraer parte de esa cadena de llamadas y por lo tanto es una opción mejor que al principio, ya que si la relacion cambia sólo tendrás que cambiar en este punto las llamadas.

El problema de esta solución es que puedes encontrarte con tu código con un montón de estos métodos atajos, que realmente por diseño no deberían encontraser ahí, pero están simplemente para hacer cumplir la ley de demeter.

Inyectar dependencias

La solución buena, como probablemente ya te venías imaginando es inyectar las dependencias. Veamos un ejemplo.

class CustomCommand extends Command
{
    public function setCustomManager(CustomManager $customManager)
    {
        $this->manager = $customManager;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->manager->execute();
    }
}

Hemos añadido como dependencia la clase CustomManager que era la que realmente necesitamos, y se la hemos inyectado a través de un setter, pero hemos eliminado toda la cadena de dependencias y las relaciones entre sí.

Con este sencillo cambio hemos podido eliminar fácilmente todas las dependencias sobrantes.

¿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.