lunes, 23 de junio de 2014

Lo que todo Computista debería saber (en Teoría)

Últimamente he visto muchos artículos sobre las herramientas o lenguajes que debería conocer todo computista. Generalmente son artículos muy buenos y con buenos consejos. Por ejemplo: Saber usar debbugers y profilers, saber expresiones regulares, saber control de versiones, etc. Sin embargo, hoy me gustaría compartir con ustedes cuales son los conocimientos teóricos que, en mi opinión, debería tener todo computista.

Árboles Rojo-Negro, FTW!!!

A continuación aquellas áreas que me parecen más relevantes para un profesional de la computación:
  • Lógica y Matemáticas Discretas: Indiscutiblemente el más importante de los conocimientos que debe tener un computista. Nadie dudaría que un mecánico deba saber de física; de la misma forma un computista debe saber de matemáticas (en particular las discretas). Para un mecánico la física es la estática (lo que define el mundo) y la dinámica el movimiento (como evoluciona e interactúa la estática). Para un computista la construcción es análoga, aplicada al mundo abstracto. La matemática es la estática y la algoritmia es la dinámica.
  • Algoritmia: Un computista no debe ser solo un programador, debe conocer de estructuras de datos diferentes y algoritmos que las utilicen astutamente. En particular, debe conocer de listas y sus variantes (pilas, colas, colas de prioridad, etc.), árboles en todas sus presentaciones, grafos, programación dinámica, metaheurísticas y demás. Es imprescindible que un buen computista sepa realizar análisis de eficiencia, tanto teóricos (con notación asintótica) como empíricos (usando análisis de desempeño).
  • Autómata: Aunque aplicados al reconocimiento de lenguajes, el tipo de pensamiento que proporciona el conocer de autómatas se aplica a casi cualquier proceso en computación. Se tiene una entrada que se consume, un conjunto de estados conectados por transiciones y un estado final al que se desea llegar. Conocer sobre analizadores sintácticos y sus adentros es quizá ya más un extra que un conocimiento básico, sin embargo también ayuda a programar mejor y usar las bondades de los compiladores.
  • Sistemas de Operación: Desde hace décadas que la mayoría de los programadores se desenvuelven en una capa de abstracción sobre la máquina, que proporciona muchísimas facilidades: un sistema de operación. Es importante saber como funcionan estos sistemas para aprovecharlos de la mejor manera posible. ¿Qué hace a un buen sistema de archivos? ¿Como se crean, manipulan y destruyen procesos? ¿Que es la fragmentación, la paginación y como puede afectar el rendimiento de los programas? Todas estas son preguntas que todo computista debería poder responder fácilmente.
  • Bases de Datos: La cantidad de información que se manipula en el mundo actual es abrumadora y los datos asociados lo son aún más. Un computista debe saber como definir y crear bases de datos (no solo relacionales, sino en otros paradigmas como el objeto-relación o bases de datos de grafos). Además, debe saber manipular y acceder eficientemente a estos datos. Para esto, es conveniente saber de Álgebra Relacional, de Índices y del uso de metadatos en un DBMS. Es importante no ligarse fuertemente a un manejador en particular, sino comprender estos conceptos de la forma más general posible.
  • Estadística: Ohhh si, la temible estadística. Pero no la que nos enseñan en los cursos que compartimos con las demás carreras en las diferentes universidades, sino una versión mucho más orientada a computación. Lo que nos hace falta saber es análisis de desempeño. Un profesor y amigo una vez me dijo: "Lo que no se mide, no se gerencia" y es una cita excelente y totalmente acertada. Saber realizar una buena medición de los programas que se desarrollan, ya sea en el consumo de recursos, calidad de las soluciones, etc. es fundamental para un buen computista. No hablo de conocer las fórmulas para las funciones de distribución clásicas; pero si, por ejemplo, saber realizar un proceso de cross-validation para probar soluciones o calcular una desviación estándar en tiempo de ejecución.
  • Inteligencia Artificial: Muchos de los grandes problemas a resolver están asociados con la inteligencia artificial. Y con esto no me refiero a robótica, sino a técnicas de búsqueda eficiente en espacios combinatorios, aprendizaje de máquina, optimización, etc. Al menos conocer los conceptos es necesario, saber lo que significa un conjunto de entrenamiento y un conjunto de prueba, conocer acerca de minería de datos y sus posibles aplicaciones, etc.
  • Ingeniería de Software: Cualquier programa que pase más allá de un ejemplo sintético en un salón de clase, necesita pasar por un buen diseño y planificación antes de pasar a implementación. Un computista debe ser capaz de diseñar abstractamente sin pensar en detalles de implementación, organizar su flujo de trabajo, evaluar las herramientas a su disposición, conocer de patrones de diseño, pruebas unitarias, mantenibilidad de código y buena documentación. Quien se rige por la filosofía de "fue difícil de escribir, debe ser difícil de entender" sólo colabora con su propio ego y no con el desarrollo del conocimiento y avance tecnológico de la humanidad.
Cualquiera que me conozca se quedará extrañado de que esta lista no incluya Lenguajes de Programación, pero esto tiene una explicación. La lista que propongo es sobre conocimientos teóricos fundamentales. La "teoría" asociada a lenguajes de programación es más que todo semántica formal en sus diferentes sabores (axiomática, operacional y denotacional) y las diferentes teorías que sustentan los lenguajes de programación como el lambda-cálculo, los modelos de Herbrand, monoides de instrucciones, etc. A pesar de ser un gran plus, pues un computista con estos conocimientos está preparado para abordar los problemas con una visión mucho más abstracta y flexible, no lo considero un conocimiento fundamental. La práctica en Lenguajes de programación (paradigmas, herramientas, estructuras de datos y control de flujo, etc.) es algo sumamente necesario, pero eso es material quizá para otra entrada.

Se podría discutir que otras áreas del conocimiento como Redes, Big Data, Computación Gráfica, Seguridad, etc. son también fundamentales. Sin embargo, a mi me parece que dichas áreas ya son especializaciones. Un computista debería poder conversar a un nivel técnico moderado con especialistas en estas áreas, pero no tiene por que manejarlas a profundidad.

Y esto, a menos que se me escape algo (que seguramente así será), es lo que en mi opinión todo computista debería saber en cuanto a teoría se refiere. Claro, recordando que ningún conocimiento es en vano y mientras más áreas se dominen mejor profesional se terminará siendo. La intención es continuar aprendiendo y mejorando. Pero ningún computista puede estar realmente completo sin un buen conocimiento de las áreas que mencioné arriba (claro, todo esto es desde mi punto de vista limitado a mi poca experiencia, pues aún me queda demasiado por aprender). Con esto los dejo hasta una próxima entrada.

4 comentarios:

  1. OK, ya casi soy un computista completo jajaja. Me falta saber de bases de datos y ya tengo todos los items en tu lista, al menos un conocimiento basico de cada punto :)

    Muy buena lista por cierto :)

    ResponderEliminar
    Respuestas
    1. Casi un computista hecho y derecho pues, jajaja. ¡Excelente man! :D

      Y bueno, lo que te falte por aprender queda muchísimo tiempo aún. ¡Nunca es tarde para aprender!

      Eliminar
  2. se parece a http://matt.might.net/articles/what-cs-majors-should-know/ con el que me topé hace unos años, (por andarme quejando del pensum de la USB) exepto que el señor Matt se pasó de especifico, nada más le falta colocar un "programa de clases" formal para cada materia jaja!

    creo que te faltó "arquitectura del computador" a menos que lo incluyas con sistemas de operación, lo que me recuerda un paper muy bueno al respecto donde explican el oscuro paradigma del exokernel, lectura recomendada: http://www.stanford.edu/~engler/hotos-jeremiad.ps

    ResponderEliminar
    Respuestas
    1. ¡El artículo de Matt Might es bastante bueno! Pero se centra más en habilidades prácticas que teóricas (que era la intención de este post). De hecho, cuando decía al principio que había leído muy buenos artículos, ese era uno de los que tenía en mente. XD

      Arquitecture del computador podría ser un buen área que agregar, la verdad no se me había ocurrido en el momento. Aunque el computista está cada día más lejos del hierro, dejando eso a electrónicos más bien. :P

      Eliminar