A menudo cuando aprendemos a programar, se nos enseña mediante pequeños proyectos que dan soluciones a pequeños problemas: hacer una calculadora, una lista de la compra, un registro de estudiantes... De este modo, trabajamos con nuevas herramientas y entendemos su forma de funcionar de forma aislada. Paso a paso y a base de estos pequeños proyectos podemos ir completando nuestro abanico de habilidades y acercándonos más al dominio del lenguaje.

Pero un día salimos al mundo real y de pronto nos encontramos con proyectos complejos cuya solución requiere de un magma estructurado de muchos de esos conocimientos. Es entonces cuando empezamos a entender verdaderamente que significa el desarrollo de un proyecto.

En este breve artículo voy a enumerar 7 de estos problemas con los que todos debemos lidiar en algún momento de nuestro camino de desarrolladores novatos hacia desarrolladores más experimentados.

 

Empezar sin trazar un plan

Sabemos a dónde queremos llegar pero nos enfrentamos a una pantalla en blanco con una única brújula que nos indica la dirección hacia donde queremos ir. Nada más.

Nuestro instinto nos pide empezar a teclear cuanto antes. Todo parece bastante claro y creemos tener todo el conocimiento necesario para llegar al final del camino sin nada más que nuestros conocimientos. Pero ¿es realmente cierto? La respuesta acertada suele ser NO.

Uno de los errores que más he cometido como desarrollador novato es sentarme delante de la pantalla y empezar a teclear sin antes trazar un plan.

Nunca hay una sola forma de resolver un problema y cuando no planificamos, las prisas nos empujan a elegir siempre la solución que tenemos más a mano, la que se nos ocurre primero, que no es siempre la mejor. Planificar nos permite valorar opciones y elegir en función de nuestro objetivo final valorando el proyecto como conjunto y teniendo en cuenta criterios: velocidad, eficiencia, etc. Además nos obliga a revisar nuestros conocimientos teniendo en cuenta nuevas herramientas y funcionalidades que van apareciendo con cada nueva especificación de los lenguajes con los que vamos a trabajar.

Es importante pues trazar unos objetivos finales, dividir el proyecto en fases y en pequeñas tareas marcándonos unos plazos realistas y que tengan en cuenta los posibles contratiempos que nos pueden ir apareciendo durante el desarrollo.

Es importante también marcar un escala de prioridades basándonos en las prestaciones que esperamos o que consideramos más importantes en nuestro producto final: rendimiento, eficiencia, diseño, peso, velocidad de implementación, costo... Tener claras estas prioridades será clave a la hora de tomar buenas decisiones en nuestras tareas o hitos y mejorará mucho la eficiencia a la hora de llegar a nuestro objetivo ahorrándonos verdaderos quebraderos de cabeza o pérdidas de tiempo reescribiendo código.

 

Planificar demasiado o atascarnos

Paradójicamente este es otro de los errores que para mi son más importantes a la hora de desarrollar un proyecto, ya que en algunos momentos del desarrollo e incluso al principio, nuestro propio desconocimiento nos genera inseguridades a la hora de tomar decisiones respecto a que camino tomar. Esto ocurre porque a menudo sabemos a donde queremos llegar más o menos, pero se trata de un producto final difuso y desdibujado, o bien incompleto que se debe ir concretando a medida que vamos ampliando nuestros conocimientos o encajando las piezas, por lo que la única forma es empezar a andar para ir revisando nuestro plan a medida que vamos alcanzando hitos. No hay otra forma: investigar, planificar, desarrollar, evaluar y vuelta a empezar.

 

Legibilidad y estructura

Este es un punto clave que distingue un buen trabajo de uno excelente y es que un código bien estructurado y legible es más fácil de mantener, modificar, compartir, integrar y testear.

Dentro de este punto podemos hablar de aspectos como:

 

  • Modularidad: Este es un aspecto muy presente en las arquitecturas SOLID, que tienen muy presente el principio de responsabiliad única. Un principio muy a tener en cuenta a la hora de realizar testeos. Esta propiedad como en otros aspectos de ingeniería relacionados con los sistemas, confiere al código mucha flexibilidad y escalabiliadad. Cada módulo, idealmente debe recibir unos parámetros de entrada y devolver unos de salida sin tener en cuenta todo lo demás. De modo que un módulo puede ser usado indistintamente por muchas partes del código indiferentemente. Un módulo debe hacer una tarea concreta y sencilla y hacerla bien.

 

  • Seguir convenciones: Estandarizadas o Particulares. Esto siempre ayuda a la legibilidad del código y permite que otras personas, si es el caso de trabajar en equipo, puedan entender rápidamente código ajeno e integrar fácilmente el suyo, sin que el resultado final parezca una ensaladilla de parches.

 

  • Naming entendible: Este aspecto del código nos permitirá sintetizar mucho código ya que evitará tener que abusar de los comentarios. El uso de nombres entendibles, descriptivos y breves ayuda mucho a la legibilidad y ahorra muchas líneas innecesarias y descripciones o aclaraciones. Vale la pena tomar un tiempo a la hora de dar nombres.

 

  • Síntesis: Este aspecto está muy relacionado con el anterior. Si nuestros nombres no se entienden y nuestra distribución es mala: sin dejar espacios de forma regular y proporcional, etc. El código se puede acabar volviendo ilegible incluso para uno mismo. Y si además caemos en la repetición e ineficiencia añadiendo código innecesario y lioso, aún más. Es importante por ello revisar nuestro código ya escrito de tanto en cuanto para añadir posibles modificaciones o actualizaciones que nos permitan mejorar la síntesis y por tanto la calidad de nuestro código.

 

  • Abuso de comentarios: Algo que en mi opinión denota una mala calidad del código o una falta de experiencia. Algo que va a menos a medida que se va ganando agilidad y experiencia y que , no olvidemos, añade líneas al código totalmente prescindibles para su compilación. Un código con demasiadas aclaraciones o explicaciones, está mal estructurado o mal escrito.

 

Dejar los tests para el final

Pensar que un código que compila es correcto es otro de las trampas en las que se puede caer como novato. Es importante testear con cierta frecuencia el código implementado y no dejar todas las pruebas para el final. Como hemos comentado anteriormente, el código modular es de gran ayuda, dado que nos permite testear módulos por separado. Y por ellos nos permite hacer tests de forma asilada.

El código que no es testado con cierta frecuencia, tiende a propagar errores, obligándonos a realizar grandes esfuerzos si esos errores son detectados en fases avanzadas de nuestro proyecto sobretodo en proyectos con diseños no muy modulares y escalables.

Es por tanto un punto clave en cuanto a eficiencia.

Una forma en la que prefiero hacerlo es en la evaluación de un hito. Es decir, Una vez terminamos un hito, evaluamos su funcionamiento módulo a módulo y luego testeamos su comportamiento general.

 

No generar datos de prueba

Algunos proyectos que lidian con cantidades de datos considerables o entidades que se relacionan entre ellas, pueden presentar dificultades en el momento en que sus bases de datos son rellenadas.

De repente encontramos que hay relaciones mal especificadas o que hay datos que no están suficientemente bien acotados en cuanto a los valores que se pueden esperar, dando pie a modificaciones del proyecto en fases ya avanzadas.

Otras veces aparecen problemas de velocidad dado que nos damos cuenta que el código que funcionaba de maravilla con un ejemplo simple, se vuelve horrorosamente lento y pesado al tener que trabajar con alta cantidad de registros.

 

Querer innovar en exceso

Como suele decir "la rueda ya esta inventada" y a menos que nos enfrentemos a problemas realmente nuevos, siempre habrá alguien en algún lugar del mundo que ya se ha enfrentado a ellos antes. Me atrevería a decir que seguramente hay más de uno y de dos. Por eso es importante investigar bien antes de reinventar la rueda. Para ello disponemos de comunidades en internet que nos pueden ayudar a ello, como por ejemplo stackoverflow o github.

 

No usar control de versiones

Este tipo de programas, cuyo máximo exponente es Git, nos aportan versatilidad y capacidad de maniobrar o probar distintos caminos. Además son una herramienta imprescindible a la hora de trabajar en equipo de forma remota y descentralizada. 

Y no solo eso, sino que debemos tener en cuenta otras funcionalidades que añaden algunos portales de managing de Git como GitHub o Bitbucket, como por ejemplo marcar hitos o comunicar errores. Estos portales permiten abrir el proyecto a otras personas anónimas, cosa muy a tener en cuenta en programas colaborativos con licencias libres o open source. Ya que permiten compartir el código limitando el acceso a las necesidades de nuestro proyecto.

También facilitan mucho el trabajo en servidores remotos ya que permiten subir cambios o volver a versiones anteriores de forma muy rápida y aportando seguridad ofreciendo en cualquier momento la capacidad de recuperar la versión que sea necesaria.