miércoles, 7 de septiembre de 2016

Hoy por mí, mañana por ti... ¿Por qué ser prolijos al escribir código?

¡Hola! Hoy quería hacer foco en un tema que refleja la calidad de las soluciones que desarrollamos como parte de nuestro trabajo. No, no voy a hablar de Testing como la última vez, sino de desarrollo de software.

Cuando hablamos de calidad, no sólo lo hacemos pensando en que un sistema funcione correctamente, sin bugs, sin problemas de performance, con un buen look & feel, cumpliendo con los requerimientos de nuestro cliente, etc. Cuando hablamos de calidad, también podemos referirnos al código fuente, es decir, a aquello que no se ve pero está allí presente, y que es lo que hace que los sistemas puedan funcionar bien, o no tanto…

Hoy por mí

En primer lugar, deberíamos generar código de calidad pensando en que luego es uno mismo quien debe leer, mantener y evolucionar constantemente el mismo a lo largo del proyecto. Difícilmente algo que desarrollemos pueda mantenerse aislado del resto de los componentes de la solución o, una vez listo, no tengamos que volver a modificarlo nunca más.

El primer y principal punto a considerar entonces, es generar el código lo suficientemente claro, ordenado y prolijo, como para que nosotros mismos podamos entenderlo pasados unos días, unas semanas, o unos requerimientos.

Dentro de los aspectos más importantes que debemos tener en cuenta a la hora de escribir buen código fuente, podemos mencionar:

Evitar la duplicación de código, ya sean líneas, bloques completos, métodos y/o clases.

Mantener el código simple, evitando la complejidad innecesaria.

Asignar nombres claros y precisos a las clases, variables, métodos y propiedades. Definir una forma de nombrarlos y luego mantenerla consistente a lo largo de todo el desarrollo.

Comentar nuestro código fuente responsablemente, evitando aquellos comentarios innecesarios que no añadan nada valioso y poniendo sólo aquellos que realmente aporten algo de valor. Además, hay que recordar que la primera documentación del código, debe ser el código mismo. Si logramos que el código sea autodocumentado, sólo deberemos utilizar comentarios en casos particulares o con alguna lógica compleja que deba detallarse.

Evitar construir métodos y/o clases muy largas, o como decimos en la jerga, kilométricas. Esto generalmente suele ser un indicio de un mal diseño técnico previo.

No construir funciones “por las dudas”. Si algo no va a ser usado, es mejor no construirlo. Por otro lado, siguiendo la misma línea, si estamos haciendo mantenimiento de código y vamos a pasar a desuso un bloque de código, es preferible eliminarlo en vez de comentarlo. Si en un futuro lo volvemos a necesitar, podemos obtenerlo del historial de cambios del repositorio de código fuente que estemos usando (hoy en día no hay excusas para trabajar sin uno de ellos).

No abusar de la herencia. Si bien es un mecanismo potente, un mal uso de la misma sólo hace que la solución sea más compleja y difícil de interpretar. Además, es importante no confundir “herencia” con “agregación” a la hora de compartir y dividir responsabilidades funcionales.

Seleccionar los patrones de diseño que realmente nos van a aportar valor a la solución y nos permitirán lograr un diseño más flexible y preciso. Es un error muy común creer que agregando más patrones de diseño la solución va a ser mejor; por el contrario, sólo la hacen más compleja y difícil de mantener.

Evitar las “God Classes”, es decir, esas estructuras que hacen de todo un poco, ya que termina siendo muy engorroso poder modificarlas debido a que su nivel de acoplamiento termina siendo muy alto.

No diseñar firmas de métodos con una gran cantidad de parámetros, ya que agregar o quitar uno de ellos terminará siendo un dolor de cabeza importante, más allá de que logremos volver a hacer compilar la solución. Si tenemos un método que recibe muchos parámetros, podemos preguntarnos si realmente son necesarios o si deberíamos dividir la funcionalidad en dos o más partes. En el caso de que realmente los necesitemos, vayamos por el enfoque de utilizar un DTO en vez de pasar los parámetros individualmente, ya que las modificaciones serán mucho más fáciles de esta forma.

Y la lista continúa… Lo ideal es, más allá de las reglas generales, consultar cuáles son las buenas prácticas particulares que existen para el lenguaje y/o plataforma que estemos utilizando, e implementarlas como parte de la solución.

Mañana por ti

De la forma en la que hoy trabajamos desarrollando software, es muy poco probable que lo hagamos solos, aislados, sin un equipo al lado nuestro participando del mismo proyecto. Por eso, el segundo punto a tener en cuenta es que, además de que nosotros podamos entender nuestro propio código, este tiene que poder ser comprendido por el resto de las personas que forman parte del grupo de trabajo.

Difícilmente podamos lograr una solución integral con un buen estándar de calidad, si no podemos interpretar lo que nuestro compañero quiso codificar. No sólo porque deberemos integrarnos con lo que otros han desarrollado, sino porque además seguramente debamos modificar, extender y/o corregir bugs en código que no es nuestro y, si no lo podemos entender correctamente, es de esperar que no podamos resolver de manera eficiente lo que se nos pida.

Lo bueno es que para poder lograr esto, existen unas series de reglas que, si todos los miembros que formamos parte del equipo del proyecto respetamos, nos permitirán generar un código más homogéneo y de mayor calidad:

Es necesario contar con estándares de codificación definidos, aprobados, aceptados y conocidos por todas las personas que trabajamos en el mismo equipo. Estos pueden ser distintos en cada equipo, o ser definidos de manera global por un área técnica de la empresa, como sucede en el caso de Baufest.

El proyecto debe estar coordinado técnicamente por un Arquitecto o Technical Leader, que deberá velar por la correcta aplicación de los estándares adoptados. Una forma de garantizar esto, es mediante los code reviews.

Además, el código del proyecto debe estar fundado sobre una arquitectura diseñada para satisfacer los requerimientos planteados por el cliente. Sin una arquitectura de base, será muy difícil mantener el código ordenado y prolijo.

Cuando ingresa una nueva persona al equipo, lo ideal es que antes de ponerse a leer los requerimientos funcionales que luego deberá construir, primero se centre en conocer y adoptar los estándares de codificación y trabajo que se están usando en el proyecto.

Se deberá contar con una herramienta de análisis de código que permita analizar el nivel de adopción de los estándares. Es un complemento a los code reviews, pero mucho más potente, ya que permite realizar análisis completos en toda la solución y obtener métricas y reportes precisos sobre los puntos a mejorar. 

En Baufest, por ejemplo, para los proyectos de .Net contamos con SonarQube, integrado a Jenkins. Por lo que si el proyecto está correctamente configurado con integración continua, podremos acceder a estas métricas fácilmente, las cuales se actualizarán con cada checkin que hagamos.

Y... mañana por mí también

Y finalmente… ¿a quién no le ha pasado de volver a un determinado proyecto en el que estuvo hace un par de años atrás? ¿A quién no lo han llamado las personas que luego tomaron ese proyecto preguntándole acerca de algo desarrollado, pidiéndole una mano para implementar una nueva funcionalidad?

Es más común de lo que parece y, por ello, hay que estar siempre preparado. Más allá de pensar en que el código pueda ser entendido por uno mismo unos días después de haberlo escrito, o por el resto del equipo durante el proyecto, hay que pensar qué pasaría si dentro de unos años es necesario retomarlo, ya sea que estemos en el nuevo equipo o no.
Por ello, cuando generemos código, no sólo debe verse bonito, sino además, tiene que ser fácilmente entendible, tiene que estar documentado, organizado, seguir un patrón de diseño y estar asociado a estándares de programación más globales, que permitan al nuevo equipo poder entender rápidamente qué se quiso hacer y cómo.

Además, generar código de calidad hace que las aplicaciones se comporten de forma más predecible, tengan menos tasa de errores, sean más fáciles de mantener y evolucionar y, por otro lado, nos potencian como profesionales, ya que no sólo estaremos generando código, sino que lo estaremos generando bien.

Recuerden, ser prolijos al generar código no sólo nos ayudará a nosotros mismos, sino que además, ayudará a otras personas a entender qué quisimos hacer cuando escribimos esas líneas.

Bueno, es todo por hoy. Les dejo un cierre con un poco de humor referido al tema… 

Fuente: http://www.codecomics.com/

¡Hasta la próxima!

Ing. Ariel Martín Bensussán
.Net Practice Manager