Aprender a programar y no morir en el intento

mayo 15, 2013
By

En esta entrega, quiero compartir mi opinión sobre qué es programar, en qué consiste, cómo aprender y cómo convertirse en un buen programador de computadoras. Para empezar, habría que definir qué es programar. ¿Basta con saber codificar en un lenguaje de programación o hacer un sitio web (que ahora está de moda) para llamarse programador? ¿O los programadores son aquellos que tienen un pensamiento lógico conceptual y que son capaces de resolver un problema sin necesidad de escribir una línea de código? Más aún ¿cómo te conviertes en un buen programador? ¿Cuáles son los rasgos identificativo de uno?

“I think everybody in this country should learn how to program a computer because it teaches you how to think. Computer science should be a liberal art”

Steve Jobs.

Si buscamos la definición de programador en Wikipedia, obtendremos: “Un programador es aquella persona que escribe, depura y mantiene el código fuente de un programa informático, es decir, del conjunto de instrucciones que ejecuta el hardware de una computadora para realizar una tarea determinada

Ésta, en mi opinión, es una burda definición de “programador” con la cual, evidentemente, no estoy de acuerdo. Claro, entiendo por qué se define así y la respuesta la puede encontrar en la historia. La computación es posiblemente la más joven de todas las ciencias y en particular ha tenido un desarrollo exponencial en los últimos veinte años, propiciado por el aumento de la capacidad de cómputo (Ver Moore’s Law). El objetivo fundamental de la “computadora”, podemos decir que es la resolución de problemas computacionales (desde agilizar cálculos para, por ejemplo, obtener la nómina de los trabajadores en una empresa hasta generar los modelos 3D de las películas que actualmente todos disfrutamos). El problema consiste en que hace muchos años, cuando la entrada de las computadoras se hacía mediante tarjetas perforadas, existían dos categorías, el analista y el programador. El analista era el que resolvía el problema y diseñaba el algoritmo y el programador era aquel que codificaba e introducía el programa al computador. En ese entonces, programar era un trabajo mecánico y el analista era quien se llevaba todos los créditos. Luego, con el desarrollo de la computación y la llegada de los lenguajes de alto nivel, esta frontera se fue eliminando y el concepto de programador también incluyó el de analista.

De arquitectos, diseñadores, programadores y cibernéticos

Antes de definir mi visión de “programador” y poder hacer recomendaciones de cómo convertirse en uno bueno, quiero hablar de algunos términos que se manejan en la industria y que pueden confundir a alguien que quiere empezar.

Con la evolución de la computación, los sistemas (conjunto de programas) se fueron complejizando cada vez más (hoy en día nadie programa un sitio web en ensamblador) a tal punto, que la industria comenzó a realizar separaciones entre las habilidades de los programadores poniéndoles nombres: arquitecto, informático, ingeniero, diseñador, científico de la computación, etc. Esa separación, especializa la labor del “programador” pero, en mi opinión, crea una confusión horrible sobre lo que realmente es programar y las habilidades que un buen programador debería tener.

La industria le llama arquitecto o ingeniero de software a un programador que, además de programar, tiene la habilidad de diseñar un sistema (conjunto de programas) usualmente complejo, guiar su desarrollo y mantenerlo. Para llegar a ser arquitecto, no basta con ser buen programador. Hay que saber de patrones de diseño, buenas prácticas y en general, tener una visión global de cómo hacer un software y contar con una experiencia acumulada. Usualmente los arquitectos tienen un grado de master y son expertos reconocidos en la materia. Sin embargo, también se comenta que “los arquitectos no programan” y solo se dedican al diseño global de la aplicación. Esta, en mi opinión, es una mala concepción porque, para llegar a arquitecto, en primer lugar hay que saber programar bien para así conocer cómo funcionan los programas y entonces poder orquestar unos nuevos. Claro, en el mundo hay “buenos” y “malos” en todas las áreas, y como mismo hay excelentes arquitectos que son buenos programadores, hay algunos “vividores” que empañan el título. No obstante, aún sin escribir líneas de código, para realizar un buen diseño de una aplicación, hay que conocer tecnologías, su funcionamiento e inevitablemente saber programar.

En el caso de la academia, ésta define a los científicos de la computación como aquellos “programadores” que además estudian matemática (física o mecánica) y se dedican a la investigación, desarrollo de algoritmos, estructuras de datos, etc. Los cibernéticos serían aquellos especializados en el campo de la robótica y la interacción humano-máquina. Esto realmente es un gran estereotipo.

En el caso de los diseñadores, pudiera pensarse que no son programadores, pero ¿aquél que diseña los colores y estilos de un sitio web en HTML5 y CSS3 no estaría “programando” también? Hoy en día los “buenos diseñadores web” saben HTML y CSS y quizás un poco de JavaScript para así entregar estilos más ricos y aplicaciones web más vívidas.

Resumiendo, el factor común entre todos estos “títulos” podemos decir que es “programador” y las variaciones entre uno y otro, consisten en las habilidades (skills) y la función que desempeñan. Por tanto, pienso que parar ser “buen programador” deben aprenderse las habilidades básicas necesarias para cada una de estas “especializaciones” (vamos a llamarle así, especializaciones) sin importar luego el título que obtenga.

¿Aprender a programar?

Como vimos anteriormente, no basta con saber “codificar” un programa para convertirse en un buen programador. Hay que, necesariamente, prestarle atención a tres grupos de habilidades:

  • Lenguaje de programación
  • Algoritmia
  • Buenas prácticas y patrones de diseño

Con Lenguaje de Programación me refiero a conocer los conceptos básicos de los lenguajes de programación y no como tal un lenguaje en particular. Usted puede saber C o Python, pero un buen programador, podría, relativamente fácil, aprender a programar en otro lenguaje si tuviese estos conocimientos básicos bien aprendidos. Por ejemplo, todos los lenguajes tienen una forma para hacer “ciclos”, ya sea de manera imperativa y explícita, utilizando for (C, C++), foreach (Java, C#) o explotando la recursividad y el trabajo con listas de los lenguajes funcionales (Haskell). Algunos lenguajes como C++ tienen punteros a funciones que permiten pasar como argumento en una llamada a un método una función, y otros lenguajes como Python y C# tienen delegados y expresiones lambdas que permiten lograr el mismo objetivo de una forma más segura. Hay lenguajes que tienen tipado estático (C, C++, Java,C#) lo que le permite al compilador detectar errores desde temprano y otros lenguajes como Python, Ruby y JavaScript tienen tipado dinámico permitiendo una mayor libertad y expresividad a costa de que el programador sepa lo que está haciendo. Y así podríamos estar enumerando un conjunto de características de los lenguajes de programación que un buen programador podría utilizar para lograr un código más expresivo, legible, seguro y mantenible.

Por tanto, hoy en día “programar en un lenguaje” no es solo saber codificar que, dado unos parámetros de entrada, se produzca un resultado esperado; sino saber cómo hacerlo de forma tal que el código sea expresivo y tenga la calidad requerida. Note que con la cantidad de lenguajes con calidad que hoy en día existen, la selección de un lenguaje para resolver un problema en concreto puede ser decisivo en la calidad de la solución y el tiempo que se demora el programador en producir dicho programa. Por tanto, un buen programador no debe ligarse a un lenguaje en concreto y limitarse al mismo; hoy en día un programador debe ser polígloto y conocer las características de varios lenguajes. La programación no está ligada a un lenguaje en concreto; los conceptos y técnicas de programación que se deben aprender para convertirse en un “buen programador” pues son aplicables a más de un lenguaje de programación.

Entrando en la algoritmia, es imprescindible que un programador sepa desarrollar algoritmos, independientemente de a lo que se dedique. El usuario final espera que la aplicación (software/programa) responda rápido y que la interfaz sea agradable y sin cortes (seamless). Y esto no solo es responsabilidad de un diseñador que haga una interfaz bonita; si el algoritmo que está por detrás demora o bloquea la interfaz, entonces no hay mucho que hacer. Recuerde que estamos en la era de los dispositivos móviles, y en estos aparatos la respuesta en tiempo real y la sensación del usuario es clave. Podría pensarse que esto es responsabilidad del arquitecto, pero, si usted es un programador sin experiencia (junior programmer) y se le pide algo tan simple como determinar si en una lista ordenada se encuentra un elemento, la diferencia entre implementar una búsqueda lineal y una dicotómica (binaria) puede ser clave para el rendimiento de la aplicación. En este ejemplo, suponiendo que haya mil elementos, una búsqueda lineal recorrería todos los elementos, haciendo mil comparaciones, mientras que una búsqueda binaria solo haría siete comparaciones. Por tanto, es necesario conocer lo básico de estructuras de datos y análisis de algoritmos para poder escribir un código eficiente, independientemente de que usted sea un científico de la computación o no; éste (el análisis de la eficiencia del algoritmo) tiene que ser conocimiento general de cualquier buen programador.

Por último, y no menos importante, es necesario conocer de buenas prácticas y patrones de diseño. Es imperdonable que un buen programador no sepa qué es SOLID, así como qué es IoC, DI, Pruebas Unitarias y otros conceptos claves a la hora de desarrollar un sistema. Usted podría pensar que estos conceptos sólo lo debe conocer un arquitecto, pero realmente, las buenas prácticas y los patrones de diseño son la experiencia acumulada por los años de la comunidad y los expertos. ¿Ha oído la frase de que el hombre es el único animal que cae dos veces con la misma piedra? ¿Y aquella que dice “No reinventemos la rueda”? Pues de eso se trata, aprender de la experiencia. Por ejemplo, el Principio de Responsabilidad Única (de SOLID) dicta que no se debe tener una misma clase (en el caso de un lenguaje orientado a objetos) con dos responsabilidades, es decir, con dos métodos que conceptualmente no tributen a un mismo objetivo. Un programador inexperto pudiera pensar que tener en varias clases lo que se puede escribir en una pues es una pérdida de tiempo y resulta trabajoso. Sin embargo, a medida que se vaya complejizando el programa, el código resultante pues se convertiría en una chapuza en donde, arreglar cualquier error o agregar una nueva funcionalidad sí que sería trabajoso. ¿No le ha sucedido que recibe el código fuente de otra persona y prefiere re-implementarlo adecuadamente porque es una chapuza y no lo entiende? Pues las buenas prácticas, los patrones de diseño y estos principios de programación ayudan a que eso no suceda.

De manera general, como se dice popularmente “hay que ser músico, poeta y loco” para triunfar. Y para llegar a ser buen programador, usted debe conocer los principios y habilidades básicas de cada uno de estos grupos, aunque luego se especialice en alguno.

Entonces ¿Qué tengo que hacer para convertirme en un buen programador?

Esta francamente, es la pregunta del millón. En principio debe aprender: lenguaje, algoritmia y buenas prácticas. Pero el tiempo de aprendizaje es finito y está claro que TODO no se puede aprender. Por otro lado, no creo que se pueda ordenar linealmente el aprendizaje y trazar dependencias entre estos tres grupos.

¿Qué sabemos hasta ahora? Usted como programador necesita desarrollar el pensamiento lógico y diseñar algoritmos para resolver un problema en concreto. Puede empezar con problemas sencillos como dado una lista de números devolver el más grande e ir escalando en complejidad hasta donde desee según sus aspiraciones y ubicación laboral. Por ejemplo, si quiere trabajar como programador en una empresa que se dedique a asistencia en la vía, probablemente tenga que conocer que el mapa que se visualiza en el GPS del carro, se representa computacionalmente con un grafo donde las esquinas son vértices (V) y las calles son aristas (E) con peso según el tráfico y el moverse desde un punto A hasta un punto B, lo puede resolver en tiempo O(|E|log|V|) con el algoritmo de Dijkstra para caminos de costo mínimo desde un vértice inicial. Ahora, si se quiere dedicar a hacer sitios web, quizás ese conocimiento de grafos no le haga falta, pero sí va a necesitar trabajar de forma eficiente con listas y árboles para desarrollar códigos “responsivos” con JavaScript (en concreto plugins para jQuery u otro framework similar).

Pero esta algoritmia necesariamente tiene que materializarse en algún lenguaje de programación independientemente si usted está en un ámbito académico desarrollando un prototipo o en uno industrial regido por las reglas del mercado y los tiempos de producción. Un mismo algoritmo se escribe de forma diferente en un lenguaje dinámico, en uno funcional o en uno estaticamente tipado. La diferencia más evidente la puede encontrar con los lenguajes funcionales donde el pensamiento cambia de imperativo a declarativo. Entonces, no basta con aprender algoritmia en pseudo-código ya que cuando va a implementar dicho algoritmo en un lenguaje concreto, puede que se requiera reformular el algoritmo dado las condiciones particulares del lenguaje. Por ejemplo, en un lenguaje funcional las variables son inmutables, por lo que no se pueden implementar ciclos que cambien el valor de una variable.

Pero tampoco se puede aprender un lenguaje de programación sin saber de algoritmia. Es imperdonable implementar el problema de dado una lista de números devolver el más grande con una búsqueda lineal, porque todo desarrollador bueno sabe que si la lista de números es extensa entonces va a demorar la respuesta. Para llevarlo a la práctica y ver qué tanto se puede demorar ese simple problema, suponga que está implementando un directorio telefónico y quiere, dado un teléfono, determinar la ficha del abonado (Nombre, Dirección, etc). ¿Cuántos millones de habitantes hay en su país? Ya tiene su respuesta.

Pudiera pensarse que la solución es aprender algoritmia en un lenguaje de programación concreto y así se aprende el lenguaje y se gana en pensamiento lógico. Esto está bien para empezar pero solo con problemas simples. Ya cuando las estructuras de datos y los algoritmos se complejizan, pues el lenguaje de programación añade una complejidad adicional que impide el correcto aprendizaje del algoritmo. Lidiar con un sistema de tipos, declaración de variables, determinar si función o delegado y en general la especificidad de la sintaxis del lenguaje, pues no aporta al algoritmo, sin mencionar, que al cambiar de lenguaje cambian también estas características. Además, es un objetivo ser políglota, por lo que si se piensa el algoritmo como una suerte de pseudo-código simple, es más fácil luego portar dicho algoritmo hacia otros lenguajes. Incluso, esa acción de portar el código contribuye a mejorar las habilidades de codificación en el lenguaje particular al cual se está portando.

Pero cuando el programador sale de la academia (sabiendo algoritmia y lenguaje), el primer golpe que recibe en la industria es que le empiezan a exigir ciertas metodologías y formas de desarrollo a los cuales no estaba acostumbrado. Por ejemplo, varias compañías siguen la metodología de desarrollo ágil (XP) y el desarrollo se guía por pruebas (TDD) siguiendo el principio Rojo-Verde (Red-Green). Usualmente para que el software se pueda probar, en un lenguaje orientado a objetos sin herencia múltiple como Java o C#, se sigue el principio de hacer una interfaz que defina el contrato del tipo (Segregación de Interfaces de SOLID) y luego la implementación concreta se asocia utilizando IoC/DI (Inversion of Control / Dependency Injection). Entonces, ¿Es necesario que ese programador sepa cómo implementar una interfaz y los patrones y buenas prácticas que le muestren cómo hacerlo adecuadamente? En mi opinión, creo que es necesario un básico que le ayude luego a integrarse en la industria.

Por tanto, resumiendo, es necesario aprender algoritmia, saber cómo implementar estas estructuras de datos y algoritmos en algún (o algunos) lenguaje(s) de programación en concreto y esa implementación hacerla siguiendo algunos principios fundamentales como lo es SOLID en un lenguaje orientado a objetos. La vía que propongo para hacerlo es la siguiente:

  1. Seleccione un lenguaje de programación expresivo y dinámico como Python y empiece a resolver problemas computacionales simples. Esto le ayudará a formar el pensamiento lógico y a desarrollar la algoritmia debido a que el lenguaje (Python) no le impone muchas restricciones y el código fuente queda bastante escueto. Esto lo puede hacer en la etapa de adolescente (quizás se pueda decir que aprender programación es como tocar piano, hay que empezar desde una temprana edad).
  2. Cuando crea que tiene un conocimiento sólido que le permita solucionar problemas computacionales básicos, cambie de lenguaje, preferentemente a uno orientado a objetos y estáticamente tipado utilizado por la industria (C++, Java, C#) y en paralelo comience a estudiar Estructuras de Datos y Algoritmos con un buen libro escrito en pseudo-código (Personalmente recomiendo el Introduction to Algorithms, de Thomas H Cormen, aunque confieso que puede ser un poco intimidante para el principiante).
  3. Cuando estudie estructura de datos y algoritmos, analice la complejidad computacional de los mismos, cuestiónese su utilidad y busque en Internet ejemplos de problemas de la vida práctica que se solucionan con dichos elementos. Esto le formará la habilidad necesaria para cuando se enfrente a un problema nuevo, pueda tomar decisiones al respecto y solucionarlo (siempre que sea posible… y aléjese de los problemas NP-Completo y NP-Hard a menos que sepa lo que está haciendo).
  4. Involúcrese en un proyecto de producción real o, al menos, en uno simulado, pero trate de aplicar buenas prácticas y patrones de diseño como si estuviese en la industria (SOLID, IoC, DI, Service Locator, TDD, BDD, Red-Green, Unit Testing, etc). Esto le pulirá las habilidades de codificación que podrá reutilizar luego en producción.
  5. Estudie las características significativas de los lenguajes de programación (qué es un lenguaje dinámico, uno estático, qué es el sistema de tipos, por qué la necesidad de lenguajes funcionales, etc). Esto le brindará una visión global de lo que puede hacer y las formas más rápidas de codificarlo. Recuerde que hay problemas que se resuelven más fácil con unos lenguajes de programación que con otros.
  6. Una vez cumplidos los pasos del 1 al 5, entonces usted está listo para aprender programación. ¿Cómo? Sencillo, la práctica y la experiencia es quien realmente lo va a llevar por el camino del buen programador. Lo que claro, si logra una buena base (pasos 1-5), pues recibirá un aventón en este camino y no morirá en el intento.

Conclusiones ¿Cuándo se llega a ser un buen programador?

Pues no creo que haya un período fijo para ello o una meta explícita que alcanzar. Todos los días se aprende algo nuevo y cuando crees que lo sabes todo pues te das cuenta que sigues aprendiendo día a día. Para mí la computación es un arte (y una ciencia por supuesto). La palabra arte se deriva del latín ars que significa habilidad y hace referencia a la realización de acciones que requieren una especialización. La computación requiere además de conocimiento científico, la práctica constante de las habilidades adquiridas, el desarrollo de nuevas habilidades y el empeño, iniciativa y visión personal de cada programador. Un buen programador, en mi opinión, es aquel que siente el programa y hace fluir el código en contraposición del mal programador que simplemente codifica sin cuestionarse la calidad del código, estilo o eficiencia. Un buen programador no se fabrica sino “nace”. El estudio le puede proveer las herramientas básicas y el conocimiento, pero solo la dedicación, el esfuerzo propio y el interés de superarse usted mismo lo llevarán por el camino de buen programador.

Hay un post titulado “Seven traits of effective programmers” que habla de los rasgos que debería tener un buen programador, según la opinión del Autor (Justin James). Me pareció muy interesante, por lo que les dejo el link aquí http://www.techrepublic.com/blog/programming-and-development/seven-traits-of-effective-programmers/6750 y les resumo los 7 rasgos del “Buen programador”:

  1. Aprende habilidades tanto técnicas como no técnicas de forma autodidacta
  2. Es pragmático y no dogmático
  3. Sabe cómo investigar (en internet) por respuestas de forma autodidacta
  4. Le apasiona lo que hace
  5. Deja el ego en la puerta (es humilde)
  6. Tiene espíritu emprendedor y siente el programa como suyo
  7. Es cauteloso con la calidad del código, pero ágil a la hora de dar respuesta

Con esto termino. Espero que le haya gustado el artículo y me gustaría tener su opinión (añada un comentario) sobre cómo aprender programación y qué es lo importante, lo básico que todo programador debiera conocer.

4 Responses to Aprender a programar y no morir en el intento

  1. Arian Fornaris on mayo 16, 2013 at 12:28 am

    Hola Alejandro,

    Te felicito por el artículo aunque es bastante extenso :) , me dio mucha risa cuando dices que hay arquitectos infla globos (algo asi creo que era) pues en una ocasión me topé con uno que sabia mucho (y tenia muchos títulos y experiencia) pero no hacia nada, y todo se atrazaba y era un problema hasta que por fin se descubrió al majá y lo botaron. Mientras leia yo tomaba nota (como buscar qué es SOLID) y sobre algunos rasgos del buen programador pero los 7 puntos de Justin James abarcaron casi todos ellos. En mi experiencia de ya casi 8 años como desarrollador, lo que más me ha ayudado es la motivación (cosa que muchas veces depende del tipo de tarea que se realiza pues desdichadamente en ocaciones el trabajo es bastante tedioso) pero sobre todo la modestia, es decir, en varias ocaciones por ser inmodesto y no tener una mente abierta la cosa no ha salido bien. Lo peor es cuando entonces pasa a un plano personal y las personas se ofenden y se molestan. Te puedo decir que desarrollando software he cometido más y peores errores en el plano social que en el técnico (estos últimos casi siempre se pueden corregir), por suerte cada vez son menos pues uno va aprendiendo. Para terminar, yo le agregaria a los 7 puntos de Justin pues la cretividad, muchas veces se requiere de ser novedoso y con las habilidades y la algoritmia no es suficiente, claro, estas son requisito casi imprescindibles.
    Ah, otro consejo al programador que quiere ser buen programador: no tengas una sola mujer, o no tienes ninguna o tienes siempre una distinta (no sé cómo pues siempre vas a estar programando), pero si te enamoras, pecas, tendrás que dedicarte a otra cosa, como por ejemplo a lo del arquitecto majá, jajaja.

    Arian Fornaris

    P.D. Ah bueno, te puedes buscar una mujer que sepa programar.
    P.D.P.D. Que bueno saber que para ser buen programador no hace falta tender la cama todos los dias.
    P.D.P.D.P.D. Steve Jobs estaba perdido, lo que todo el mundo debe aprender es albañileria, carpinteria, electricidad y mover el esqueleto.

  2. Florencia on mayo 29, 2013 at 12:18 pm

    Saber programar puede ser de mucha utilidad teniendo en cuenta la gran cantidad de áreas en las que son imprescindibles los diseñadores web hoy en día.

  3. Michelle S. on septiembre 1, 2013 at 11:54 pm

    Que buen articulo, me gusto muchisimo. Soy autodidacta, y aunque empece en el mundo de la programacion hace solo dos años, para nada una adolescente jeje, creo que cualquiera puede aprender a programar, y justamente no se trata de manejar un lenguaje de programacion nada mas o escribir y depurar codigo, es por demas, muchisimo mas que solo eso. Me motivo a continuar en mi camino mejorando siempre. Gracias por los consejos! :)

  4. Marlon on septiembre 25, 2013 at 5:08 pm

    Muchas gracias amigo este articulo me ayudo a tomar consiencia, de lo que real mente debo hacer para aprender y cumplir objitivos ….
    desde luego nuevamente gracias

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Acerca del autor...

Alejandro Tamayo

Web: http://www.linkedin.com/in/atamayocastillo
Alejandro Tamayo
Professor, Researcher, Developer, Consultant and technology enthusiast. Master of Science (MSc) in Computer Science and member of Weboo Research Group.Leer completo