El otro día hablando con un amigo surgió el tema de seguir leyendo o estudiando sobre informática más allá de la carrera. Es evidente que 4 años no dan para aprender la totalidad de la informática (ni de ningún otro campo del saber) y que todavía queda mucho por aprender después de dejar la universidad. La parte en la que no estaba de acuerdo con él es en que dijo que él sólo lee sobre cosas cuando las necesita mientras que a mí me gusta leer sobre problemas que no tengo porque sí, porque son interesantes, y creo que el hacerlo es beneficioso.
Para empezar vamos a dejar una cosa clara: el conocimiento
para poder desempeñar un trabajo de programador en una empresa a un nivel suficiente como para sacar el trabajo adelante y no ser despedido es bastante pequeño. Con saber usar el lenguaje de programación que se pide y tener un mínimo conocimiento de cómo se resuelven problemas comunes se puede hacer mucho. El resto se improvisa o se busca en
. El seguir estudiando después de la carrera no obedece a una necesidad profesional sino a un interés personal. Si lo que uno quiere es solamente ganarse un dinero y olvidarse de la informática fuera de la jornada laboral nada de esto le interesa. Esta es una actitud perfectamente legítima y el objetivo de este texto no es en absoluto el criticarla.
Creo que hay principalmente tres argumentos a favor de que aprender más allá de lo estrictamente necesario para llevar a cabo las tareas de uno es beneficioso para mejorar como programador y en última instancia hacer esas tareas mejor.
El primero es el estar expuesto a otros campos, lo que se manifiesta en dos formas. Por un lado, puede ser que técnicas, algoritmos, patrones de diseño o ideas de otras ramas de la informática sean aplicables al campo de uno. Se da con cierta frecuencia que una tecnología que se desarrolla en, digamos, la compraventa automatizada de acciones resulta útil para resolver un problema en desarrollo de videojuegos o en navegadores o en páginas web. Sin embargo, es improvable que los desarrolladores de videojuegos o los programadores web estén hablando sobre esa tecnología, por lo que una persona buscando cómo resolver un problema concreto en videojuegos difícilmente se va a encontrar con ella. Este flujo de ideas entre campos se da sólo cuando los trabajadores de estos distintos campos leen lo que los demás están haciendo.
La segunda ventaja de aprender del resto de campos es el entender las capas sobre las que uno trabaja. Una persona haciendo un videojuego sobre Unreal o Unity no necesita saber cómo funciona un motor de videojuegos, qué partes tiene, qué hacen o cómo están escritas. Desde luego no necesita saber hacer uno. Lo único que necesita saber es cómo interactuar con la capa exterior: la API y la interfaz del editor. Tampoco necesita saber sobre el compilador, el sistema operativo, la tarjeta gráfica... más allá de lo estrictamente necesario para hacerlos funcionar como usuario. Se puede hacer juegos sin tener ninguno de estos conocimientos y eso es genial porque permite que gente sin un conocimiento altamente especializado haga videojuegos. Por otro lado, las capas sobre las que uno construye no son perfectas. Tienen limitaciones, asunciones, sesgos... Entender cómo están hechas estas capas nos permite tomar mejores decisiones y evitar meternos en charcos como bugs en estas capas, defectos de hardware o problemas de rendimiento por usarlas incorrectamente.
Es difícil buscar información sobre algo si no sabemos que existe. Tener un conocimiento amplio de qué tecnologías existen y los problemas que resuelven, aunque no se tenga un conocimiento profundo sobre cada una de ellas, puede facilitar mucho la búsqueda de información.
Un ejemplo de esto es la asignatura de estructuras de datos que se da en todas las carreras de informática. Por lo general en una asignatura así se dan una serie de estructuras de datos y algoritmos, se aprende cómo funcionan y cómo escribirlos y se estudia qué características tienen, como la complejidad asintótica de distintas operaciones. Por lo general un alumno al poco de cursar esta asignatura termina olvidando las implementaciones de casi todas estas estructuras de datos y algoritmos. Realmente esto da igual. Lo que es muy importante es recordar que existen y qué propiedades tienen. Uno no necesita saber de memoria cómo escribir un árbol rojo y negro. Esa información está en
. Pero necesita saber cuándo tiene que usar un árbol rojo y negro, porque si no no sabrá cuando buscar esa información en Wikipedia y cuando buscar otra cosa.
Lo mismo se aplica a conocimientos que no son de la carrera. Si no somos conscientes de qué tecnologías y técnicas existen ya, qué problemas resuelven y con qué propiedades, es posible que en el momento de buscar esa información que necesitamos pasemos por alto ideas relevantes porque al no saber que existen ni se nos ocurre leer sobre ellas.
Muchas veces, creemos que sabemos resolver un problema pero no es verdad. Nuestro conocimiento sobre el tema es parcial. Creemos que el campo es más simple de lo que es y no somos conscientes de la complejidad que realmente tiene. Es decir, no sabemos algo y no sabemos que no lo sabemos. Peor aún, creemos que lo sabemos. Por lo tanto, ni se nos pasa por la cabeza estudiar sobre este tema. Ya lo sabemos.
Recientemente me puse a leer sobre el espacio de color sRGB y la función gamma. Resulta que prácticamente todo el código que escribí en la carrera que manipulaba colores en la CPU estaba mal. Por supuesto, yo no tenía ni idea cuando lo escribí, ni mucho después de haberlo escrito. Es más, yo pensaba que estaba bien y lo seguí pensando durante años después. Si me hubieran pedido escribir código que manipulara colores no habría buscado información al respecto. Habría cometido los mismos errores y vuelto a pensar que lo estaba haciendo bien.
La única forma de desmontar estas asunciones es estudiando los conocimientos básicos. Muchas veces cuando buscamos conocimiento por necesidad, como parte de una tarea, buscamos una solución concreta a un problema concreto. ¿Cómo escribo código que haga X? Rara vez leemos sobre las bases sobre las que trabajamos. Los tipos de datos esenciales sobre los que luego se construyen todas estas soluciones concretas. Números, texto, colores, imágenes, archivos... Todos ellos son más complejos de lo que la mayoría de programadores piensan e informarse solamente sobre soluciones concretas a problemas concretos rara vez va a desmontar esas asunciones.
El problema de los errores causados por asunciones es que por lo general golpean tarde, cuando ya es difícil cambiarlos. Es muy fácil incrustar en el programa la asunción, por ejemplo, de que se puede acceder a una letra en un texto por índice. Y es muy fácil llenar el programa de sitios donde esta asunción es vital. Seguramente funcione durante meses. Es normal para alguien que no se lo vea venir que todos los datos de prueba sean ASCII, y también que lo sea la mayoría de texto que toca procesar al principio. Hasta que de repente alguien introduce en el sistema una tilde, una letra griega o un emoji y eso causa un error en algún lugar remoto en las entrañas del código. El problema es que ahora esa asunción está repartida por todo el programa y cambiarlo posiblemente lleve meses. La única forma de haberlo evitado habría sido ser consciente del problema de antemano, pero para eso hay que conocer el problema y eso requiere de antemano un conocimiento profundo de cómo se codifica el texto.
El texto es sólo uno de los muchos ejemplos de problemas que son mucho más complejos de lo que la mayoría de programadores creen. Otro son los paths, que no son isomórficos con las strings a pesar de la creencia generalizada. Los colores y las imágenes son otro campo en el que mucha gente asume que sabe cosas que luego resultan ser erróneas.
No comprender bien las abstracciones fundamentales sobre las que se trabaja lleva a introducir asunciones en el código que a la larga son muy difíciles de cambiar y que pueden llevar a que el programa sea en el futuro incapaz de hacer algunas cosas, tenga defectos inesperados o se requiera un esfuerzo hercúleo para hacer las modificaciones necesarias.
El conocimiento
para poder programar es muy poco, pero programar sólo con el conocimiento necesario lleva a que se escriba código de peor calidad. Hay lagunas de conocimiento que es casi imposible llenar buscando solamente soluciones concretas a problemas concretos y limitarse a informarse sólo de lo que sucede en el campo de uno puede llevar a pasar por alto conocimiento valioso. Es muy difícil saber qué es lo que no sabemos.