Durante una de las clases estuvimos hablando acerca de las razones por las que las soluciones de software tienen una calidad relativamente baja si las comparamos con los productos que suelen producir otras ingenierías. Y me parece un tema interesantísimo.
Creo que hay muchas razones por las que esto ocurre. Principalmente estimo que se debe a una poca profesionalización dentro del mundo del desarrollo de software. La cual estimo es perjudicial. Si quieres entender la cultura de un grupo no hay mejor manera que ver su humor. Pásate por /r/programmerhumor.
Pienso que la programación está más cerca de un arte que de un proceso industrial. Resolver problemas es una actividad principalmente creativa, y teclear la solución no tiene un gran valor en comparación. La dificultad de programar es descubrir el diseño de la solución y para ello hay que explorar tecleando.
El trabajo de los desarrolladores no es escribir código, es solucionar problemas. Todas las métricas relacionadas con el código producido son absurdas. Lo “limpio” que sea el código (¿qué significa limpio?), el estilo con el que escribes las variables (camelCase, snake_case, …), cuántas líneas tiene una función, el número de argumentos de una función, longitud de las líneas, etc. todo esto son banalidades. Cuestiones que no creo merezcan libros.
El trabajo como ingenieros es elegir los tradeoffs adecuados en cada situación.
No silver bullet
En la programación no existe una solución que valga para todo. Cada sistema tiene unas limitaciones y unos requisitos distintos. Por eso es casi imposible desarrollar código que vaya a funcionar bien en todas las situaciones.
El desarrollo del software consiste en gestionar la complejidad. Desde cómo diseñar el sistema hasta que nombres ponerles a las variables es un trabajo de gestión de la complejidad.
La complejidad se puede dividir en dos categorías: esencial y accidental. La complejidad esencial es la intrínseca que requiere el problema que se va a resolver. La accidental es toda aquella que no entra en la categoría anterior. Las herramientas de desarrollo, los lenguajes de programación, las librerías, etc. contribuyen principalmente a las complejidad accidental. Y más que eliminarla o aumentarla lo que suele ocurrir es que se traslada la complejidad a otra parte del proyecto.
Malas herramientas
Las herramientas de las que se dispone a la hora de desarrollar software no están todo lo avanzadas que podrían. Las herramientas llevan 30 años estancadas sin tener mejoras sustanciales que ayuden a un desarrollo más rápido y eficiente.
Para empezar los lenguajes de programación llevan sin innovar considerablemente mucho tiempo. No han evolucionado significativamente en los últimos 50 años, no son más que pequeñas iteraciones de Algol 68. Diría más, los lenguajes han ido perdiendo poder expresivo y han crecido en complejidad. Los lenguajes de programación más populares ahora mismo se diseñaron para los ordenadores de hace 30 años en el mejor de los casos. Para ordenadores que disponían de poca memoria y no más de un procesador. Se han tomado decisiones cuestionables en los lenguajes de programación que se han convertido en el estándar.
Por ejemplo, HTML era un lenguaje aceptable para su función original, CSS no está bien diseñado (Lo que a los estilos se refiere es aceptable pero, que un lenguaje que tiene que expresar posicionamiento no haya manera de decir “encima de”, “a la izquierda de”, …). JavaScript es un lenguaje que se diseñó para pequeños scripts en el cliente. Ninguna de estas 3 tecnologías son adecuadas para el uso que se le dá ahora a la web.
La prevalencia de los lenguajes interpretados y sin tipar, también se están usando para tareas que no fueron pensados inicialmente introduciendo muchos problemas. Desde el rendimiento a la memoria y a la creación de nuevas metodologías para lidiar con fallos por la falta de tipos y la naturaleza dinámica de los lenguajes (lo sé, inesperado).
Se ha seguido una tendencia hacia los lenguajes “con ruedines”. Se ve al programador como alguien a quien hay que limitar las posibilidades porque si no va a hacer algo perjudicial. La evolución de los lenguajes de programación ha ido restringiendo el conjunto de acciones posibles que puede ejecutar un programador con la premisa que de esta manera cometerá menos fallos. Sin embargo, aunque se cubren ciertos fallos no existe ninguna manera de evitar los fallos en la lógica del producto. En lugar de tener herramientas avanzadas para los programadores más experimentados que saben lo que hacen se les trata a todos por igual como principiantes. De esta manera no se saca todo el provecho que se podría de los desarrolladores más expertos.
Los entornos de desarrollo, herramientas de debugueo, las librerías, … tampoco son todo lo buenos que podrían ser. Faltan cosas conceptualmente sencillas como herramientas que muestren los eventos de un sistema distribuido centralizados y ordenados en un único lugar, editores inteligentes que nos muestren los resultados del código según lo estamos escribiendo [9], lenguajes de programación que nos permitan metaprogramar.
*Pregunta, ¿Por qué programamos en texto todavía? ¿Y si programásemos en el AST directamente?
Esto hace que los tiempos de iteración sean mucho más lentos de lo que podrían ser dificultando la exploración de la solución.
*Preguntas, ¿Por qué asociamos lenguajes de programación a algunas tareas/ámbitos? ¿Por qué creemos que hay cosas que “solo” se pueden hacer en cierto lenguaje? ¿Por qué incluimos la librería estándar cuando hablamos de un lenguaje?
Industrialización
Cuando hablamos de industrializar el software nos referimos a crear piezas que se puedan usar y combinar de manera sencilla para facilitar el desarrollo de software futuro.
Primero tenemos que empezar por definir que es una pieza de software. Y ya se nos complica. ¿A qué nos referimos? ¿Dónde ponemos el límite? Una pieza es, ¿una función, un algoritmo, una librería o un sistema? Dependiendo del “tamaño” que definamos como pieza elegimos más rendimiento o menos. La filosofía Unix dice:
Haz que cada programa haga una cosa bien. Para hacer un nuevo trabajo, construye de nuevo en lugar de complicar los viejos programas añadiendo nuevas «características».
Doug McIlroy
Sin embargo, las limitaciones del mundo real, de la máquina en la que se ejecutan los programas hace que esta filosofía no se pueda realizar [3].
Segundo, tenemos que hacer que las piezas se entiendan entre sí. Hay que estandarizar las interfaces, la comunicación entre las piezas. Esto supone no solo una pérdida de rendimiento sino que es una decisión que va a tener consecuencias durante muchos muchos años. O sea si se comete algún error ¿cómo se va a lidiar con la retrocompatibilidad? Empieza a crecer la complejidad.
Tercero, la gestión de distintos lenguajes de programación, librerías, “ecosistemas”. La mayoría de lenguajes no exponen una manera sencilla de operar con otros lenguajes de programación. Pocos lenguajes tienen las funcionalidades necesarias para realizar estas comunicaciones de manera eficiente. La complejidad sigue creciendo.
Cuarto, las abstracciones y la composición de programas no escala bien. Las abstracciones como su nombre indica ocultan los detalles de las capas inferiores. Parece que esto reduce la complejidad del sistemas pero solo la traslada a otro lugar. Ahora en vez de tener un solo problema (un sistema que entender) hay dos [1]. Y sigue creciendo la complejidad.
Quinto, reutilizar código se parece más a un trasplante que a unir piezas de Lego [2]. El código siempre toma se adapta al problema y a la situación para la que se ideo. Cuando tomamos ese código y lo introducimos en otro proyecto (que no sea muy similar) es necesario introducir una capa de traducción o reescribir y adaptar casi todo el código copiado. Y seguimos complicando más la solución.
Sexto, ¿Se puede programar sin diseñar o diseñar sin programar? Si bien teclear es la parte sencilla de la programación, la atención al detalle que requiere esa acción ayuda a diseñar mejores soluciones. Diseñando en abstracto es muy complicado percatarse de todas las interacciones entre los diferentes sistemas que componen la solución.
Malas metodologías
Hay muchas presiones externas a la programación que reducen la calidad de lo que se produce. La necesidad de ser los primeros en sacar un producto al mercado está en contraposición con hacer un producto de calidad. El resultado suele ser productos incompletos que se van a seguir desarrollando progresivamente. Pero una vez llegado al mercado es casi imposible realizar un cambio estructural grande, por lo que la solución se queda atrapada en el espacio que ha explorado.
Aunque se ponga mucho énfasis en la calidad, la verdad es que no lo parece. Esto son cosas que he ido recogiendo durante la última semana.
Esta es la primera impresión que te llevas de KnowledgeLeader.
Un autocompletado que ordena mal las opciones.
La DGT que ante un error te muestra toda la información de desarrollador con el agujero de seguridad que es eso y la mala imagen que le transmite al usuario.
Referencias
[0] There is no Silver Bullet,
https://en.wikipedia.org/wiki/No_Silver_Bullet
[1] The law of leaky abstractions,
https://www.joelonsoftware.com/2002/11/11/the-law-of-leaky-abstractions/
[2] LEGO blocks and organ transplants,
https://www.johndcook.com/blog/2011/02/03/lego-blocks-and-organ-transplants/
[3] Where the Unix philosophy breaks down,
https://www.johndcook.com/blog/2010/06/30/where-the-unix-philosophy-breaks-down/
[4] Jonathan Blow on Software Quality, part 1,
https://www.youtube.com/watch?v=oJ4GcZs7y6g
[5] Jonathan Blow on Software Quality, full talk,
https://www.bilibili.com/video/av21278220/
[6] Preventing the collapse of civilization,
https://www.youtube.com/watch?v=ZSRHeXYDLko
[7] Reboot Develop 2017 – Jonathan Blow, Thekla Inc. / Making Game Programming Less Terrible,
https://www.youtube.com/watch?v=De0Am_QcZiQ
[8] The thirty million line problem,
https://www.youtube.com/watch?v=kZRE7HIO3vk
[9] Dion systems,
https://media.handmade-seattle.com/dion-systems/
[10] Whitebox,
https://azmr.itch.io/whitebox
Falta de interés
Quiero aprovechar este último post para acabar de contar algunas de las cosas que se han quedado pendientes por la falta de tiempo y otros motivos.
Cuando se nos preguntó sobre qué mejoraríamos de las clases dije “no asumas que tenemos interés”. Creo que quedó un poco brusco por la falta de tiempo y no puede expresar adecuadamente todo lo que quería decir. Aun así, pienso que sintetiza bastante bien un sentimiento compartido con mis compañeros por lo que me dijeron al acabar la clase.
La mayoría de mis quejas están dirigidas al sistema educativo, no creo que la universidad ni los profesores estén haciendo un mal trabajo dentro de las restricciones que se les imponen. En este aspecto envidio la universidad americana en la que no hay asignaturas ni están organizadas por año, sino que hay cursos y cada cual elige los que quiere cursar.
Volviendo al interés, ¿Cuál es el perfil del estudiante de informática? ¿Qué hace aquí? Me baso únicamente en mi experiencia personal.
El estudiante universitario de ingeniería informática puede ser:
- Alguien con interés en la tecnología y/o los videojuegos. En este caso, lo normal es que haya elegido el grado porque quiere aprender a programar, habilidad que necesita para hacer juegos más sofisticados que lo poco que ha trasteado con las herramientas gratis y de programación visual o scripts básicos copiados de un tutorial.
- Alguien con interés en la inteligencia artificial. Aquí también es raro que haya trasteado mucho por su cuenta. En la mayoría de casos conocerá los algoritmos de moda como “deep learning” o “redes neuronales”.
- Alguien con interés en seguridad. O porque quiere ser “hacker” o porque le han dicho que es un perfil muy solicitado. Habrá “hackeado” a algún amigo siguiendo un tutorial en Youtube.
- Alguien que quiere hacer una página web y hacerse rico. No, este tampoco ha investigado mucho por su cuenta como se hacen estas cosas.
- Alguien que quería hacer una ingeniería pero no sabía cuál y ha acabado aquí.
Es raro encontrarse con estudiantes que tengan experiencia en los temas que se van a tratar — muy pocos saben siquiera programar algo. Creo que el perfil ha cambiado bastante, ya no existe el perfil del “hacker” no se puede trastear con los ordenadores actuales, tampoco sabe mucho de seguridad (porque hoy en día no es tan importante para el usuario como lo fue cuando los chats irc), son sistemas muy cerrados. Hablando con profesores, los nuevos estudiantes cada año necesitan más clases extras de Programación I. Sin embargo, muchos profesores esperan que sepamos de sus temas cuando no hemos sido expuestos a ellos nunca.
A menudo nos encontramos con que los profesores piensan que tenemos interés en la asignatura y hemos buscado información, aprendido cosas por nuestra cuenta o que tenemos experiencia en esos ámbitos.
Por otro lado está el problema de la universidad que no tiene claro si quiere formar a investigadores y expertos, o trabajadores. El grado de informática es una extraña mezcla entre asignaturas teóricas, rigurosas y matemáticas (pero no demasiado) y, asignaturas empresariales y de proyectos (pero no demasiado y centrado en empresas enormes). El viaje resulta muy superficial sobre “la informática” y no sientes ser experto en ninguna de las áreas al acabar. Las expectativas a menudo no se cumplen.
Volviendo otra vez al interés, (elijo esta asignatura por cercanía pero se puede aplicar a cualquier otra) ¿qué se supone que tenemos que aprender sobre sistemas de información empresarial? Afortunadamente nuestro profesor ha rellenado la asignatura con temas muy interesantes. Pero en lo que al núcleo de la asignatura se refiere, ¿qué tiene que saber un estudiante?
- ¿Tenía que aprender el significado de la infinidad de siglas, CRM, ERP, GIS, SCM, …?
¿Qué valor hay en eso?
- ¿Tenía que aprender que existen herramientas BI y las características de estas? ¿Y el año que viene cuando salgan nuevas?
¿Cuánto va a durar este conocimiento? - ¿Qué tengo que aprender acerca de la planificación estratégica de una empresa? ¿Qué hay que tener sentido común y alinear los objetivos de los demás departamentos?
¿Cuánto se tarda en enseñar eso?
Muchas de estas cosas ya las hemos visto en otras asignaturas. Es increíble cuánto se repiten entre sí las asignaturas.
Resumiendo, los estudiantes de informática solemos tener unos intereses muy concretos, muchas asignaturas son muy superficiales y no se llega a las partes interesantes (ni siquiera en las que estamos interesados). Los estudiantes a menudo no tenemos experiencia, ni laboral, ni en esa asignatura. Eso es lo que pretendía transmitir con lo del interés.