Saltar al contenido principal

Anotaciones sobre el libro Clean Code - 4

Capítulo 3 (Funciones)

El hacer software es como cualquier otro proceso creativo, primero se estructuran las ideas y después el mensaje, hasta que se lea bien. El primer borrador puede estar desorganizado, pero se retoca y se mejora hasta tener la forma adecuada.

  • Deben ser de tamaño reducido (máximo de 20 lineas)
  • Sangrado (o anidado) de máximo 2 niveles, de lo contrario dificulta la lectura
  • Hacen algo o responden algo, no ambas cosas (cambia el estado de una estructura/objeto o devuelve información del mismo, hacer ambas causa confusión)

Hacer una sola cosa

  • Solo DEBEN hacer una cosa, hacerlo bien y debe ser lo único que hagan
  • Las funciones que hacen una sola cosa no se pueden dividir en secciones
  • Las funciones hacen una cosa si sus instrucciones están en el mismo nivel de abstracción
  • El código se debería poder leer como un texto (de arriba a abajo); El primer párrafo P0 describe en un nivel de abstracción, el segundo párrafo P1 detalla la abstracción de la primera instrucción del párrafo anterior (P0) y así sucesivamente, de manera que cada uno describe el nivel de abstracción, mientras hace referencia a los párrafos posteriores del siguiente nivel

Usar nombres descriptivos

  • Cuanto más reducida y concreta sea una función, más sencillo será elegir un nombre descriptivo
  • Un nombre descriptivo extenso es mejor que uno breve pero enigmático
  • No tema dedicar tiempo a elegir un buen nombre; pruebe con varios nombres y lea el código con todos ellos hasta encontrar uno lo bastante descriptivo
  • No es extraño que la búsqueda de nombres descriptivos genere una reestructuración favorable
  • Use las mismas frases, sustantivos y verbos para los módulos

Argumentos de funciones

  • El número ideal de argumentos para una función es 0, después 1 y 2
  • Siempre que sea posible evite 3 argumentos
  • Más de 3 argumentos requiere una justificación especial y NO es muy habitual
  • Son más complicados desde el punto de vista de pruebas; tener que probar todas las permutaciones de valores en los argumentos es titánico en comparación con una función sin argumentos o con 1 argumento
  • Los argumentos de salida son mucho más difíciles de entender que los de entrada; antes de la programación orientada a objetos, los argumentos de salida eran necesarios. Regularmente obligan a revisar la firma de la función, convirtiéndolo en un esfuerzo doble (pausa cognitiva)

Formas monódicas (1 argumento)

  • Realizan una pregunta sobre el argumento (fileExists(fileName) //verifica si el archivo existe)
  • Procesan el argumento, lo transforma en otra cosa y la devuelve (readFile(fileName) // transforma un nombre de archivo en una cadena de caracteres)
  • Eventos; hay un argumento de entrada, pero no de salida. Hay que ejercer precaución para aclarar al lector que se trata de un evento
  • EVITAR funciones monódicas que tengan un argumento de salida, use un valor devuelto en su lugar
  • EVITAR argumentos de indicador (booleanos); son una práctica totalmente desaconsejable, indican que la función hace más de una cosa dependiendo del valor. Mejor descomponer la función en 2 (para valor positivo y para valor negativo)

Funciones diádicas (2 argumentos)

  • Es más difícil de entender que una función monódica

  • Puede no haber cohesión en los argumentos (es decir, sin relación)

  • Hay que detenerse a entender o ignorar uno de los argumentos; generando posibles errores

  • Los argumentos carecen de orden natural, por ejemplo:

    assert.Equals(expected, actual)
    

    ¿Cuántas veces no se cambiarían por error el orden de los argumentos? No hay un orden natural, sino una convención adquirida con la práctica

Funciones triadas (3 argumentos)

  • Mucho más difíciles de entender que las de 2 argumentos
  • Los problemas para ordenar, ignorar o detenerse en los argumentos se duplica

Estructura/Objeto como argumento

  • Cuando una función parece necesitar 2 o más argumentos, es muy probable que alguno se incluya en otro a través de una estructura u objeto nuevo:

    newCircle( float x, float y, float radius)
    // x and y can create a Point struct
    newCircle( Point center, float radius)
    

Listas de argumentos

  • Si los argumentos se procesan de la misma forma, serán equivalentes a una lista del tipo de dato del argumento; la función podría ser de 1, 2 o tal vez 3 argumentos, pero sería un error asignar más

Verbos y palabras clave

  • El uso de nombres correctos para una función mejora su explicación y su cometido así como el orden y cometido de sus argumentos
  • En forma monódica (1 argumento), la función y argumento deben formar un verbo y sustantivo (por ejemplo process(payment), o mejor aún processOrder(payment)

Sin efectos secundarios

  • Un efecto secundario es cuando la función promete hacer una cosa, pero también hace otras ocultas. Esto se podría aclarar cambiando el nombre de la función (por ejemplo, validaUsuarioEInicializaUsuario), pero esto incumple con la regla de hacer una sola cosa.