Escribiendo código limpio (parte 1)

Algunos pequeños consejos para aplicar cuando escribimos código que otros tendrán que mantener

DIVULGACIÓNDESARROLLOTIPS

JLJuarez

11/12/20245 min read

Aquellos que me conocen saben que para mi las metodologías, patrones y pautas del desarrollo de software  son buenas prácticas que, aportan un beneficio tangible y contribuyen de manera efectiva a mejorar el  desempeño profesional y por tanto el trabajo resulta, pero que por desgracia pocas veces puedes aplicar.

Algunos podrían pensar que esto que digo es poco ortodoxo, o incluso mentira y tal vez tengan algo de razón, pero hay circunstancias que escapan a nuestro control, que en muchos casos nos limitan su aplicación. Creo que muchos coincidirán conmigo en que la realidad de nuestra profesión, rara vez se ajusta al escenario ideal donde podemos aplicar todas estas metodologías y patrones al pie de la letra. Ya sea por la falta de tiempo, recursos insuficientes o porque quienes toman decisiones las consideran innecesarias, el caso es que a menudo nos enfrentamos a este tipo de limitaciones. En cualquier caso, esto no puede utilizarse como excusa y debemos intentar en la medida de lo posible aplicarlas en los proyectos en los que participemos.

Por eso, os quiero compartir algunos principios básicos y de fácil aplicación en nuestro día a día, que al menos en mi caso, siempre han dado buenos resultados. Estos principios no son invención mía (no doy para tanto), sino que parten de los fundamentos del conocido libro "Clean Code" del gran Robert C. Martin., lo he dividido en dos partes para que no se haga largo, que se que ha mucho os da pereza eso de leer.

Usa nombres con significado

Una idea recurrente en el desarrollo de software es que el código debe poderse leer igual que un libro. Para lograrlo, es fundamental que los nombres de variables, métodos y clases se elijan cuidadosamente, de manera que reflejen claramente la intención de lo que estamos "haciendo" en nuestro programa.

En el caso de las estructuras públicas (como clases y funciones), es importante que los nombres sean concretos y claros, para que quienes interactúen con el código lo comprendan fácilmente. Sin embargo, en las estructuras privadas podemos optar por nombres más largos y descriptivos, siempre que expliquen de forma precisa lo que están haciendo.

Haz unidades de código pequeñas

Las clases y métodos cortos facilitan la comprensión del código y mejoran su mantenibilidad. Las funciones o clases excesivamente largas pueden volverse difíciles de entender sin revisar cada línea con detalle, lo que incrementa considerablemente el tiempo necesario para comprender su funcionamiento.

En cambio, mantenerlos breves y combinarlos con un uso adecuado de nombres significativos hace que el código sea mucho más legible y directo.

Limitar el número de líneas en clases y funciones es una práctica que ayuda a cumplir este principio de manera natural. La cantidad exacta depende de cada caso, pero como referencia, mantener los métodos entre 10-20 líneas y las clases alrededor de 500 líneas puede ser un buen punto de partida.

También es recomendable evitar niveles excesivos de anidamiento. Por ejemplo, cada rama de un `if/else` debería contener idealmente una única línea que llame a una función. Esto se debe a que las bifurcaciones en el código pueden volverse difíciles de seguir. Al extraer el bloque de código a una función, puedes darle un nombre descriptivo que explique claramente lo que ocurre en ese camino específico.

Las unidades de código deben hacer una única cosa

Las funciones deben tener un número limitado de argumentos

Repetir código es una práctica peligrosa que a menudo conduce a problemas. Seguir el principio de evitar la duplicación de código nos ahorrará muchos dolores de cabeza.

Algunos de los problemas comunes que surgen con la repetición de código incluyen:

  • Tener que testar lo mismo varias veces, ya que el código duplicado está en diferentes partes del programa, lo que obliga a validar su correcto funcionamiento en todos los lugares.

  • Si necesitamos modificar algo en un bloque, tendremos que recordar hacerlo en todos los lugares donde se repitió el código, lo que a menudo lleva a olvidos.

  • Aumentamos innecesariamente la cantidad de código que se debe mantener, lo que siempre resulta en más esfuerzo y posibles errores.

La solución es sencilla: extraer el código duplicado a una clase o función reutilizable, y llamarlo desde los distintos lugares donde sea necesario.

Evita utilizar comentarios siempre que sea posible.

Por supuesto, habrá casos en los que un comentario sea útil, por ejemplo, cuando necesitas explicar un código complejo o dejar un arreglo temporal. En estas situaciones, es importante que los comentarios sean claros y concisos.

Si no seguimos el principio mencionado anteriormente, corremos el riesgo de que nuestras estructuras de código se vuelvan demasiado grandes, lo que probablemente significa que están haciendo más de una cosa. Esto viola el "Principio de Responsabilidad Única (Single Responsibility Principle)".

Cuando una clase asume múltiples responsabilidades, inevitablemente nos encontraremos con problemas como:

  • Aumentan las razones por las que necesitaríamos modificar esa clase, lo que incrementa las probabilidades de introducir errores y complica su mantenimiento al volverse más compleja.

  • Los test se volverán más extensos y probablemente menos eficaces, lo que también dificultará su mantenimiento.

  • A medida que la clase crece en tamaño y complejidad, será cada vez más complicado agregar nueva funcionalidad, ya que tendremos que lidiar con las funcionalidades existentes de manera más cuidadosa.

Siempre que sea posible, es preferible utilizar funciones sin parámetros. Sin embargo, cuando es inevitable, limitarse a un máximo de tres parámetros es una buena práctica.

Los parámetros agregan una carga conceptual que dificulta la lectura y comprensión del código. Es mucho más fácil entender el comportamiento de una función sin argumentos que una que reciba parámetros, ya que esto implica que el resultado puede variar según la entrada.

Además, los parámetros complican el proceso de testing. Imagina una función con cuatro parámetros: el número de combinaciones posibles que tendríamos que verificar sería muy alto, y para garantizar que la clase funcione correctamente, tendríamos que probar todas esas combinaciones.

Una alternativa es sustituir los parámetros por un objeto que modele la entrada. Esto no elimina la complejidad, pero al menos hace más comprensible lo que se está haciendo con esos valores.

Sigue el principio DRY: Don't Repeat Yourself

Si sientes la necesidad de agregar un comentario, es probable que tu código no sea lo suficientemente claro, lo que va en contra de las buenas prácticas de legibilidad. Siempre que te encuentres en esta situación, es recomendable modificar el código y mejorar la nomenclatura para que los comentarios sean innecesarios.

El problema con los comentarios es similar al de la duplicación de código: cuando modificamos el código, a menudo olvidamos actualizar los comentarios, ya sea porque estamos apurados o porque estamos tan concentrados en la solución que los comentarios pasan desapercibidos.