Código limpio: Argumentos

Código limpio: Argumentos

Esta entrada está disponible en video

Puedes encontrar una versión en video de esta entrada en nuestro canal de youtube.

Código Limpio

El libro Clean Code o Código Limpo es considerado por muchos como "la biblia" del desarrollo de software. Probablemente esta es una afirmación exagerada, sin embargo no se puede negar que es un gran libro que merece la pena leer. En esta serie de entradas analizamos los principales capítulos del libro clean code publicado por Robert C Martin en el año 2008.

Se han escrito mil entradas sobre el que se considera uno de los más importantes libros sobre filosofía de desarrollo de software, pero nosotros en esta serie de entradas queremos profundizar un poco más en cada uno de los capítulos. Si te dedicas a programar y te interesa mejorar en tu profesión quedate. A lo largo de esta serie de entradas vamos a aprender un montón de cosas.


Si lo deseas puedes ver el resto de entradas de la serie: Código Limpio

En esta entrada vamos a profundizar en la importancia que tienen los argumentos y ver algunas reglas para elegirlos y ordenarlos correctamente.

Número de argumentos

Según el autor podríamos clasificar las funciones o los métodos según el número de argumentos posibles.

Monádicaos tienen un sólo argumento, son fáciles de testear y fáciles de entender. No hay lugar a dudas en cuanto a que es lo que hace y probablemente será bastante sencillo crear un test unitario para la misma. Siempre que podamos debemos basar nuestra api en este tipo de funciones.

Diádicos tienen dos argumentos. Siguen siendo relativamente fáciles de entender, y probablemente seguirán siendo fáciles de testear.

Triadicos son las que tienen tres argumentos, comienza a complicarse la forma de testear, aumenta la complejidad ciclomática o número de "caminos" posibles dentro de la función, y se complica recordar los argumentos y su orden. Este tipo de funciones deberían evitarse si es posible.

Cuatro o más argumentos Este tipo de funciones tienen todos los problemas que ya hemos comentado pero en mayor expotente. Veamos un ejemplo a continuación la función que ejecuta el filtro localizeddate de twig.

function twig_localized_date_filter(
    Twig_Environment $env,
    $date,
    $dateFormat = 'medium',
    $timeFormat = 'medium',
    $locale = null,
    $timezone = null,
    $format = null,
    $calendar = 'gregorian'
) {
    //..
}

Habitualmente usamos esta función de esta forma lo que la hace muy cómoda de usar

{{ item.date|localizeddate }}
{{ item.date|localizeddate('short', 'none') }} {# el uso de las constantes es muy cómodo en el día a día. #}

El problema viene cuando queremos pasarle un formato personalizado. Es muy dificil de recordar cuales son los argumentos, y tenemos que ir a la documentación para comprobarlo. Además los primeros dos argumentos son ignorados lo que la vuelve un poco confusa.

{{ item.date|localizeddate('none', 'none', null, null, 'MMMM y') }}
{{ item.date|localizeddate('full', 'full', null, null, 'MMMM y') }} {# ambas hacen lo mismo. #}

¿Que os parece si cambiamos esta función por dos? En la primera usaremos las constantes definidas para $dateFormat y $timeFormat mientras que en la segunda usaremos un formato personalizado.

function twig_localized_date_filter(
    Twig_Environment $env,
    $date,
    $dateFormat = 'medium',
    $timeFormat = 'medium',
    $locale = null,
    $timezone = null,
    $calendar = 'gregorian'
) {
//..
}

function twig_localized_date_filter_by_format(
    Twig_Environment $env,
    $date,
    $customFormat = null,
    $locale = null,
    $timezone = null,
    $calendar = 'gregorian'
) {
//..
}

Hemos reducido un poco el número de argumentos y hemos facilitado su utilización, ya que el uso de la segunda función quedaría en algo parecido a esto.

Nota: Aunque todavía son muchos argumentos el primero es injectado por twig asi que contaría uno menos.

{{ item.date|localizeddate('da_igual_lo_que_pongas', 'da_igual_lo_que_pongas', null, null, 'MMMM y') }} {# antes #}
  {{ item.date|localizeddate_by_format('MMMM y') }} {# mejor esta no? #}

Grupos de argumentos

En el caso en el que tenemos una función con un grupo de argumentos relacionados entre sí, podemos agruparlos todos ellos en una clase de forma que nuestro código mejora en su legibilidad. Es lo que han hecho aquí.

¿Que os parece si crearamos una clase para almacenar la configuración de la localización $locale, $timezone, $calendar. Es muy probable que este grupo de argumentos se repitan en otras funciones.

class Localization
{
    private $locale = null;
    private $timezone = null;
    private $calendar = 'gregorian';

    public function __construct($locale, $timezone, string $calendar)
    {
        $this->locale = $locale;
        $this->timezone = $timezone;
        $this->calendar = $calendar;
    }

}

Con esto mejoramos mucho la legibilidad del código, veamos cómo quedarían nuestras funciones anteriores

function twig_localized_date_filter(
    Twig_Environment $env,
    $date,
    $dateFormat = 'medium',
    $timeFormat = 'medium',
    $localization
) {
//..
}

function twig_localized_date_filter_by_format(
    Twig_Environment $env,
    $date,
    $customFormat = null,
    $localization
) {
//..
}

Orden de argumentos

A partir de este punto todo lo que vamos a ver no aparece en el libro, pero si que hemos querido completarlo con algunos criterios adicionales. Deberías tener en cuenta las siguientes condiciones a la hora de elegir el orden de los argumentos.

  • Los más importantes primero.
  • Utiliza el contexto para que el lector sepa cual es el primer argumento.
  • Trata de agrupar por tipos.
  • Argumentos opcionales al final.

Nombres

Los nombres de tus argumentos son parte de tu función. Trata de que séan lo más expecíficos posibles, ayuda al lector a entender tu función y lo que pueda esperar de ella, a través de esos nombres. ¿Que te parece este cambio?

function twig_localized_date_filter(
    Twig_Environment $env,
    $dateTime, // $date no era fiel a la realidad, ya que en ese argumento no importa sólo la fecha, si no también la hora.
    $dateFormat = 'medium',
    $timeFormat = 'medium',
    $localization
) {
//..
}

Tipado

El último apartado que me gustaría ver en esta entrada es el tipado. La regla es muy sencilla. Tipa siempre que puedas.

function twig_localized_date_filter(
    Twig_Environment $env,
    \DateTime $date,
    string $dateFormat = 'medium',
    string $timeFormat = 'medium',
    Localization $localization = null
) {
//..
}

function twig_localized_date_filter_by_format(
    Twig_Environment $env,
    \DateTime $date,
    string $customFormat,
    Localization $localization = null
) {
//..
}

El tipado también forma parte de tu función, quizá no tengas claro que es exactamente $localization, pero el tipado te ayuda a entender que se trata de una clase.

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