Hay una tendencia en el desarrollo de software que lleva años cristalizando en el desarrollo de software, la de hacer que un programa dependa en gran medida de una única biblioteca enorme que tiene como objetivo cubrir la mayor parte de necesidades del programa. A falta de un término mejor, las llamaremos plataformas por usar el término que usa Roc.
también es un término común para describir a este tipo de bibliotecas. Hablamos de Unreal y Unity, de React y Angular, de Qt, de Ruby on rails y Node.js, por poner unos pocos ejemplos. Por proximidad la mayor parte de ejemplos de este texto serán sobre Unreal, pero son extrapolables a cualquiera. Me gusta el término “plataforma” porque es cierto que a ojos del programador estas bibliotecas abstraen la plataforma real hasta tal punto que en la práctica operan como la plataforma siendo programada. El programa medio que usa Unreal es totalmente indisociable de Unreal, hasta el punto de que cada estructura de datos, clase y función de ese programa sin excepción en algún momento se entrelaza con código de Unreal.
Es evidente que usar cualquiera de estas plataformas tiene numerosas ventajas, siendo la más evidente la enorme cantidad de funcionalidad que traen ya hecha que no hace falta rehacer de forma casera. También es cierto que estas bibliotecas suelen destacar mucho en algunos aspectos, y es conocido por ejemplo que el renderizado y la iluminación de Unreal requiere el trabajo de meses o años de varios expertos para escribirlo, cosa que no está al alcance de la mayoría de empresas. Otra ventaja notable es la cantidad de conocimiento colectivo que existe sobre estas bibliotecas, ya sea en documentación oficial, foros de preguntas, tutoriales, charlas, vídeos de YouTube. También existen expertos en usar estas herramientas que pueden enseñar a sus compañeros, y contratarlos es atractivo ya que pueden empezar a producir muy pronto porque conocen de antemano la tecnología con la que van a trabajar.
La situación es que depender de estas plataformas es tan atractivo que la mayoría de desarrollos no pueden permitirse no hacerlo. La ventaja comercial es demasiada. De nuevo, todo el trabajo que ahorran y sobre todo los expertos en distintos temas que no hace falta contratar porque ese código ya ha sido escrito por otros es suficiente para que la mayoría de empresas simplemente no puedan permitirse otra alternativa. Exceptuando desarrollos pequeños con una dirección muy clara y un equipo muy técnico como pueden ser los de Thekla Inc, o empresas gigantes que pueden permitirse desarrollar su propia tecnología desde cero como EA o Ubisoft, para la mayoría de empresas no tiene sentido renunciar a todas estas ventajas.
Además, la situación no va a cambiar. En todo caso irá a más, ya que tiende a retroalimentarse. Los desarrollos en Unreal forman a expertos en Unreal, lo que hace que por un lado quieran seguir usándolo, aunque se muevan a otra empresa, y por otro a las empresas les interese usar Unreal ya que facilita la contratación de personal ya formado. De la misma forma, más usuarios de Unreal implica más dinero para la empresa que puede invertir en desarrollar todavía más funcionalidad y tecnología más sofisticada para aumentar todavía más la brecha de diferencia entre usarlo o no. Que en los últimos 10 años estemos viendo lanzamientos de grandes juegos triple A hechos en Unreal no es más que la culminación de este proceso.
Todo esto hace que sea especialmente importante ser consciente de los problemas de usar estas grandes plataformas, ya que, si usarlas es inevitable, entonces también lo es tragar con sus defectos. Y el mayor de ellos es sin duda que estas grandes plataformas tienen bugs. Tienen errores que hacen que un usuario haciendo un uso en teoría correcto puede obtener sin embargo un resultado incorrecto. Y estos bugs son especialmente problemáticos, desde luego mucho más de los que cualquiera escribe en su día a día, porque desde el punto de vista del usuario están en el código de otro. Cuando uno escribe un bug y más tarde este aflora, lo más común es ir y arreglarlo. Esto es relativamente sencillo ya que ese bug está en el código que uno ha escrito, de forma que tiene un conocimiento del código y más facilidad para entenderlo, y también poder para transformarlo. Cuando uno choca con un bug dentro de la plataforma, sucede todo lo contrario. Por un lado, nadie en el equipo ha escrito el código defectuoso. Nadie lo conoce. Uno puede ir y leérselo, pero entenderlo en su totalidad va a llevar muchas horas. Sobre todo cuando se trata de un sistema complejo e interconectado con otros sistemas igual de complejos. Pero es que además uno no puede arreglarlo así sin más. Modificar la plataforma de la que uno depende es peligroso ya que en el futuro será mucho más difícil de actualizar a una versión nueva. También hay menos garantía de que ese arreglo vaya a ser correcto, ya que lo está realizando alguien con una experiencia más superficial de lo deseable. Además, puede que el trabajo necesario para arreglar ese bug sea mucho. Puede que haya que reescribir partes sustanciales del sistema para lidiar correctamente del problema, y nadie tiene la experiencia ni la confianza necesarios para hacer esto.
Lo que lleva a que la mayoría de las veces en las que uno encuentra un bug en la plataforma, lo que hace es buscar la forma de bordearlo lo mejor posible. Resulta que si configuras esto así y llamas a esta función con tal parámetro asá ya no sucede el problema. Lo das por bueno y a la siguiente tarea. Sin embargo, esto es peligroso. Cuando un sistema complejo está siendo usado de una forma que no es la intencionada, es común que genere problemas en otro lado. Conforme un proyecto empieza a acumular este tipo de soluciones improvisadas a problemas de la plataforma, éstas empiezan a chocar entre ellas y producir problemas unas en presencia de otras. Resulta que ese arreglo de configuración para que no se diera el bug en el sistema A, cuando se junta con un uso creativo de la interfaz del sistema B para sortear otro bug, producen un nuevo problema. Cuando uno no puede solucionar los problemas de raíz y sólo puede parchear por encima, sobre todo con escasa comprensión de lo que está produciendo los problemas en realidad, hay un margen bastante limitado de acción antes de que los problemas empiecen a aflorar inevitablemente.
Además, estas situaciones suceden también cuando no hay errores en la plataforma, pero sí un uso indebido de algún sistema por parte del equipo. Cuanto más complejo e interconectado es un sistema, mayor es la probabilidad de que el usuario cometa un error al usarlo o al configurarlo que luego repercuta en otras partes aparentemente poco relacionadas. Si en el equipo no hay ningún experto en las tripas del sistema que es capaz de detectar estos usos indebidos y sus posibles ramificaciones, es más fácil que los desarrolladores cometan errores y que el resultado sean bugs crípticos en partes aparentemente no relacionadas del programa.
Cabría preguntarse también cómo hemos llegado hasta aquí. ¿Por qué puede Unreal permitirse un estado tan defectuoso de algunos de sus sistemas? ¿Cómo es que eso no afecta a su base de usuarios? Y volvemos a lo que decíamos antes, la cantidad de funcionalidad que Unreal aporta es tal que compensa sus defectos, medido en número de horas de trabajo. Incluso con todo el tiempo desperdiciado solucionando y parcheando problemas, se ahorra tiempo. Por lo que siguen teniendo una ventaja competitiva y no pierden clientes. Esto lleva a que arreglar bugs sea una prioridad más bien baja para Epic, ya que no hay un verdadero incentivo económico detrás. Además, lo que capta usuarios nuevos no es la calidad de la experiencia de usuario, es la tecnología chula de gráficos con la que se pueden hacer trailers espectaculares.
Además, tampoco es que las empresas que han desarrollado un motor propio lo hayan hecho mucho mejor. Si uno escucha anécdotas sobre los motores caseros de diferentes estudios de videojuegos no es difícil cruzarse con verdaderas historias de terror. Lo trágico es que Unreal y Unity posiblemente sean los mejores motores disponibles, y que el mayor volumen de quejas simplemente se deba al mayor volumen de usuarios.
Sin embargo, uno no puede dejar de preguntarse si tiene que ser así. Hay un tipo de plataforma que, a pesar de tener un problema muy difícil y una base de usuarios inmensa, apenas tiene bugs. Los compiladores. En casi siete años que un servidor lleva programando, ha reportado exactamente dos bugs al compilador de C++ de Microsoft, y ninguno a GCC y Clang. Uno puede fácilmente encontrarse dos bugs de Unreal en una mala semana. Además, esos bugs estaban en código extremadamente raro que en nada se parece a lo que se escribe en el día a día, o en código que ponía a prueba y llevaba al extremo los añadidos nuevos a las más recientes revisiones del estándar, y que eran relativamente recientes en el compilador. Los compiladores tienen unos estándares de calidad tan altos que la mayoría de las empresas no tienen ningún experto en lenguajes de programación, y muchas veces ni siquiera alguien capaz de leer código de ensamblador, porque no hace falta. La mayor parte de la gente nunca se ha leído el código de su compilador, y nunca ha sentido la necesidad de hacerlo. Uno puede programar con casi total confianza de que el compilador va a generar el código que uno ha escrito, y que si algo va mal la culpa ha sido del programador y no de la máquina. Esto no significa que los compiladores no tengan bugs, pero son tan raros que podemos tratarlos como si no los tuvieran.
Es curioso cómo dependiendo del campo los estándares de calidad de qué se considera una cantidad de errores aceptable fluctúe tantísimo. No sé cómo llegaron los compiladores a la situación en la que están ahora. Posiblemente tuviera que ver con que tienen una importante competencia de compiladores open source donde el dinero no es un motivante, y por lo tanto pueden perseguir unos estándares de calidad distintos no guiados por la maximización de los beneficios económicos, y esto lleva al resto de compiladores a tener que adaptarse y ceder ya que la experiencia de usuario de un software sin bugs es incompatible. Tal vez los motores de videojuegos necesiten algo parecido, pero esto no es más que una hipótesis al azar.
Lo que está claro es que ahora mismo muchas producciones de software están obligadas a depender de tecnología defectuosa, situación muy notable pero en absoluto exclusiva en los videojuegos, lo que lleva a que los videojuegos salgan al mercado con bugs y que los desarrollos dediquen una parte desproporcionada de su tiempo a arreglarlos en lugar de a no meterlos en primer lugar. También parece que al menos de momento no hay alternativa, así que toca resignarse.