martes, 6 de enero de 2015

¿Soy un programador o un depurador?

De las múltiples actividades de las que consta el día día de un programador, en mi caso (y en el de muchos) tipear código o dibujar diagramas de clases (por dar un par de ejemplos de actividades "estereotípicas") no es lo que más me ocupa. La mayor parte de mi tiempo como programador se me va "depurando". No es que le reste importancia a las etapas previas (todo lo contrario, cada vez las valoro más), ni que sea tan animal que por cada linea de código que escriba cometa tres errores. Pero es así. Y esto se contradice un poco bastante con lo que a uno le enseñan en la universidad, sobre primero pensar, diseñar, analizar, bosquejar en papel, y solo luego sentarse a codificar. Se puede argumentar que tanto depurar es consecuencia de saltarse o apurarse en las etapas previas. Entonces: ¿es una muy mala señal pasar más tiempo depurando prototipos erróneos o incompletos, que pensando primero y escribiendo luego las cosas bien, sin tantos defectos? Creo que no necesariamente.

Me hice esta pregunta a raíz de una observación de Paul Graham, entre muchas otras, en uno de sus ensayos, e intenté responderla antes de continuar leyéndolo. En realidad tenía en la cabeza también algunas lecturas sobre qué es un buen lenguaje de programación, y qué cosas nos debe permitir hacer. Y creo que por allí pasa la respuesta. Es sin duda muy necesario planificar bien la arquitectura de un sistema, en función de sus objetivos y requerimientos (que también hay que saber encontrar, no son nada obvios) antes de codificar. Es imprescindible tener una idea de hacia donde van las cosas antes de querer implementarlas definitivamente. Es obviamente imposible decirle a una PC cómo resolver un problema (de eso se trata en gran parte codificar) sin antes saber uno mismo cómo hacerlo. Es inevitable proponer algunos prototipos y que estos fracasen antes de converger en un diseño viable para un proyecto relativamente complejo (ndr: complejo no es necesariamente grande). Es, es, es... Todas esas cosas que se dice que son buenas hacer antes de ir a codificar, son 200% reales, y la experiencia me lo verifica, con todo lo que he sufrido en el largo plazo por omitir etapas en el corto. Entonces, digamos que estoy totalmente de acuerdo en que hay que (resumiendo) pensar (independientemente de la codificación) antes de lanzarse a codificar.

"Nos apresuramos a pasar por alto los pasos
previos a la programación, para tener
tiempo de arreglar los errores cometidos por
apurarnos a pasar a la programación."
Como no encontré imágenes adecuadas, pongo un par de citas para cortar el texto. Esta es de G. Myers.

Y entonces, ¿cómo se pega esto con que igualmente siga lanzándome casi directamente a codificar cada vez que empiezo un proyecto? Mi respuesta, (mi opinión, no tiene por qué ser correcta) es muy simple: porque a esta altura de mi carrera C++ resulta ser (para mi) el lenguaje más natural y directo con el cual puedo plasmar mis pensamientos (en lo que a diseño e implementación de software se refiere). Me es más fácil, más rápido, y más libre de pérdidas en la conversión, si traduzco mis ideas a código (C++ en este caso), antes que a cualquier otro pseudo-lenguaje o diagrama que pueda escribir en papel. Es decir, la etapa donde pienso, "antes" de programar, sigue siendo la más importante. Pero resulta que la mayoría de las veces (cuando el problema es de ingeniería de software, o algorítmico) el lenguaje de programación que más conozco es por lejos la mejor herramienta que tengo para ordenar esos pensamientos.

Entonces, de ahí que como resultado de mi etapa de pensar obtenga un prototipo en código, y no una pila de papeles garabateados. Y de ahí que la siguiente etapa sea muchas veces acomodar ese código, y no escribirlo de cero. Y acomodar implica corregir un prototipo hecho antes de tener las ideas claras, implica hacer refactory, implica separar lo que finalmente resulta útil de las pruebas descartables, saber cuando tirar algo y hacerlo de nuevo, etc. Y toda esa edición, tanto del diseño como de la implementación, me requiere de mucha mucha "depuración", para que las cosas sigan andando luego de tamaña transformación. En un mundo ideal, con las ideas claras editar no traería tanto depurar, pero no soy de los que escriben código correcto a la primera. Y así, mi forma de trabajo es más bien iterativa, y en cada iteración, las pequeñas mejoras al código consumen grandes espacios de tiempo depurando, para corregir los errores que el mal diseño inicial tenía, para entender cuanto impacta un cambio antes de hacerlo, para analizar hasta donde se acoplan las partes al intentar independizarlas, para corregir los errores nuevos luego del cambio, etc. Pero lo importante es que desde las primeras iteraciones el código me ayuda a bosquejar y ordenar las ideas.

No se confundan, esto no es una argumentación a favor de C++. Podría (tal vez debería) haber sido otro lenguaje (aunque no cualquiera). Simplemente resulta que C++ es el lenguaje que uso a diario desde hace más de 10 años y sobre el cual leo todo lo que puedo para seguir aprendiendo y manteniéndome actualizado. Luego, que me sienta más cómodo en este lenguaje que en cualquier otro, y que ya tenga una caja de herramientas basadas en él lo suficientemente completa, es solo una consecuencia obvia del paso del tiempo. Y creo que de todo ese tiempo, solo el último año puedo decir que me siento 99% cómodo con el lenguaje, y empiezo a entender lo suficiente como para justificar usarlo de esta manera, porque empiezo a conocer y entender los verdaderos porqués que hay atrás de cada aspecto importante del mismo.

"Un importante, pero también esquivo, aspecto
de cualquier herramienta es su influencia en los
hábitos de quienes la usan. Si la herramientas es
un lenguaje de programación, esta influencia
está, nos guste o no, en nuestra forma de pensar."
Lo que hago puede ser muy "peligroso", como bien lo expresaba el gran Edsger Dijkstra.

Por eso, a los que están aún aprendiendo, o haciendo sus primeras experiencias en proyectos grandes, les recomendaría que hagan su etapa previa en papel, o en cualquier otra herramienta con la que se sientan cómodos, pero no codificando. Para que puedan separar los problemas producto  de las limitaciones del lenguaje y de una implementación particular, de los problemas y las limitaciones propias del diseño que están pensando y analizando. Con el tiempo, luego de haber cometido muuuchos errores (que es sin dudas la mejor forma de aprender), uno empieza a sentirse con la confianza suficiente como para ir fusionando las etapas. Y sólo con más tiempo y más errores, empieza a hacerlo realmente con cierto éxito.

P.D.: Luego de terminar este post y continuar leyendo el ensayo que le dio origen, veo que el autor tiene una visión muy similar a la que acabo de desarrollar. Y aunque por sus comentarios estoy seguro de que el autor pensaría al escribir eso que C++ era un pésimo lenguaje para esta tarea, hoy pienso que los cambios en C++11 y C++14 le podrían hacer cambiar de opinión.

No hay comentarios:

Publicar un comentario