En diciembre de 2019, pedí que alguien se encargara de proporcionar paquetes AppImages para Darktable. El beneficio obvio habría sido habilitar pruebas tempranas, antes del lanzamiento, de personas que no pueden construir el código fuente por sí mismas, con la esperanza de proporcionar comentarios tempranos y ayudar a depurar antes del lanzamiento. Esto nunca ha sido una prioridad, lo que significa que estaba bien tener una prisa antes y posterior al lanzamiento para corregir errores.
No estaba bromeando cuando dije que Darktable era una fábrica de agotamiento, gestionada como las peores startups, excepto que nadie hará una salida y es básicamente una pérdida seca para todos los involucrados. Estoy aún más enojado porque se han desperdiciado muchas horas-hombre en llenar la interfaz con cosméticos, mientras que tener compilaciones nocturnas para uso general habría mejorado tanto la calidad del software como el confort y calidad de vida de sus mantenedores. Estos objetivos obviamente no importaban.
Entonces, ya que nadie te sirve mejor que tus propios errores, tuve que hacerlo yo mismo , y a mediados de diciembre de 2022, Ansel obtuvo scripts de compilaciones nocturnas de AppImage que Darktable reutilizó un mes después. Con las cohortes de chicos de TI “sin habilidades en matemáticas de píxeles” que deambulan por la moda de Darktable y preguntan cómo podrían ayudar, por supuesto, la mejor gestión de recursos posible fue desviar horas-hombre de uno de los pocos chicos con habilidades matemáticas disponibles a una tarea puramente de TI. Todo esto me llevó alrededor de 50 horas, porque tener un script funcionando localmente realmente no es lo mismo que susurrar scripts YAML a los oídos de Github Action, y tuve que aprenderlo mientras lo hacía. Ya que Ansel tarda 20 a 30 minutos en compilarse (o fallar) en las instancias de Github Action, tu jornada laboral es una larga sesión a trompicones de mal aprovechamiento del tiempo, mientras esperas que los cambios en tu script den un resultado remoto. Odio programar, y lo hago por matemáticas y física, pero ese tipo de configuración de servidor servil realmente es el peor tipo de programación que existe, en la medida en que no es ni creativa ni cognitivamente desafiante, es solo una forma que consume tiempo de trabajar alrededor de las limitaciones de diseño de APIs de terceros.
Finalmente, Ansel fue un proyecto de software semi-organizado, capaz de incluir una base de usuarios mayor que solo los geeks duros de pelar que miran con desprecio a todos los que no pueden conseguir que GCC y CMake se pongan en orden para compilar, con un gran botón de “descargar” en la página principal que siempre apuntaría a la última compilación, sin que los usuarios tengan que averiguar cuál era la última. Porque un software editor de fotos no debería filtrar usuarios basándose en su alfabetización informática, ya sea que provenga o no del mundo Linux (lo que realmente no es una excusa), o hay un memo de la Fundación de software libre que no recibí.
Pero el último gran problema era la falta de documentación para desarrolladores. En 2018, cuando comencé a contribuir a Darktable, tuve muchas dificultades para entender cómo estaban conectados los internos, solo leyendo el código. 7 años después, incluso con toda mi experiencia, todavía tengo que revertir mi camino a través del código, usando tanto grep
como mi intuición, porque el código no es modular, pocos lugares usan APIs, los comentarios son escasos, y una línea por línea culpable de Git no siempre permite volver en la historia de cambios de diseño cuando alguien cometió cambios (inútiles) de formato de código.
La falta de documentación para desarrolladores llevó a que muchas funciones se implementaran más de una vez, en varios lugares, por varios desarrolladores (y a veces incluso por el mismo, a lo largo de los años). Al momento de escribir esto, todavía hay 4 o 5 formas diferentes, en Ansel, de escribir un historial de imagen desde la base de datos de la biblioteca a un archivo XMP de sidecar. Algunas de estas formas se usan raramente, por lo tanto, apenas se prueban, y los errores allí podrían pasar desapercibidos durante años, hasta que alguien informe el error súper peculiar escondido en el bosque de opciones. Luego, para el mantenedor a cargo, es un juego tonto de averiguar por qué XMP fallan solo en algunas circunstancias, lo que requiere arqueología en la base de código para descubrir que no usa el método principal de escritura XMP. Los XMP son un ejemplo específico y aún actual, pero hubo muchos otros. Te haces la idea.
Había notado durante varios años que los archivos de cabecera C (antiguos) de Darktable tenían casi todos [docstrings de Doxygen](https://www.doxygen.nl/manual docblocks.html). Esta es una forma muy perezosa de hacer documentación: ejecuta el comando doxygen -g <config-file>
contra tu directorio de código fuente, y Doxygen te construirá un sitio web estático HTML de todas las APIs. Luego puedes volcar todos los archivos HTML a un directorio de servidor web, y llamarlo tus docs de desarrollador: la única parte tediosa es escribir el archivo de configuración, lo que haces solo una vez. Así que hice eso: dev.ansel.photos. La API que he reescrito (como selection.h
) está documentada a medida que avanzaba. Descripciones de nivel superior de la arquitectura de software están llegando.
Lo grandioso de Doxygen es que también produce gráficas de dependencias de “módulos” y APIs. Y ahí es donde realmente puedes ver por qué llamo al código de Darktable espagueti. Este es el gráfico de dependencias de accelerators.h
, la parte trasera de accesos directos de teclado y MIDI:
Eso te muestra que la parte trasera de aceleradores no es absolutamente modular: hereda todo el software. Así que cualquier cambio en otro lugar puede tener efectos imprevistos allí, y viceversa. Lo cual es aún más preocupante ya que este archivo tiene la mayor complejidad ciclómatica de todo el software , lo que lo convierte en el archivo más desafiante para mantener (ni siquiera me atrevo a decir ampliar, en ese punto sería irresponsable). Pero también está completamente retorcido en términos de dirección de inclusiones: los atajos son un bloque básico que debería incluirse (es decir, heredarse) en los lugares de la GUI que implementarán atajos (vistas de cuarto oscuro/ligero, deslizadores y combinadores, módulos). En cambio, el gráfico (y el archivo #include
de cabecera) muestra que los atajos también están incluyendo (heredando) a sus “hijos”, así que tenemos una doble dependencia y eso es la peor forma posible de hacerlo.
Es como construir una casa: la casa debería ser consciente de sus paredes, las paredes deberían ser conscientes de sus ladrillos. ¿Por qué? Porque la casa está hecha de paredes, y las paredes están hechas de ladrillos, así que cada sub-componente determina la naturaleza y el comportamiento del ensamblaje, por lo tanto, el ensamblaje tiene que conocer sus componentes inmediatos. No haces que los ladrillos sean conscientes de la casa, porque no cambiarán su naturaleza dependiendo del ensamblaje al que pertenezcan, y sería un diseño terriblemente defectuoso. Así como es un nivel innecesario de microgestión hacer que la casa sea consciente de los ladrillos: una vez que es consciente de sus paredes, depende de las paredes dar cuenta del comportamiento de sus ladrillos, y tal vez enviar información relevante a la casa. Los lenguajes orientados a objetos tienen formas incorporadas (y obligatorias) de manejar todo eso limpiamente. Pero es C, así que puedes hacer lo que te dé la gana. No significa que sea una buena idea, no significa que debas hacerlo. Y bueno, C no siendo un lenguaje intrínsecamente orientado a objetos no es un obstáculo para usar patrones de objetos, herencia y modularidad. Es solo que el desarrollador no obtendrá ayuda de la sintaxis del lenguaje para hacerlo.
Este es el mismo archivo después de mi reescritura completa de la parte trasera de accesos directos:
Eso muestra claramente que el nuevo manejador de accesos directos es un contenedor delgado sobre los accesos directos nativos de Gtk, no conoce el resto del software y no le importa. También podemos ver el archivo accelerators.c
:
Ahora, hay muchas inclusiones allí de darktable.h
, que se usa solo para obtener los ayudantes de depuración (deberían refactorizarse fuera de ese archivo), e incluye un montón de porquería innecesaria también. De todos modos, accelerators.c
solo tiene conocimiento de Gtk/Gdk, lo que significa que es un verdadero módulo: está completamente aislado del resto del software. Los widgets GUI que implementan accesos directos declararán su ruta de atajo, como Ansel/Global/Menu/File/Import
, sus teclas predeterminadas y una referencia (puntero) a ellos mismos. Las acciones sin widget que tienen accesos directos declararán una función de retorno de llamada y datos de entrada al manejador de accesos directos, en lugar de un puntero a un widget.
Guardamos/restauramos las asociaciones de rutas y teclas hacia/desde el archivo keyboardrc
, y eso es todo. Actualmente no hay una ventana para definir accesos directos en la GUI, pero hacer una solo tendría que listar (recorrer en bucle) las rutas conocidas y sus teclas asociadas. Cuando el manejador de accesos directos detecta una combinación de teclas conocida:
- para las acciones guiadas por widgets, enviará una señal
activate
de Gtk al widget relevante, y ese widget hará lo suyo a través de un callback (que es el mismo que maneja clics, así que el código es uniforme entre clics y activación mediante teclado), - para las acciones sin widget, llamará directamente a la función callback declarada sobre los datos declarados.
De cualquier manera, el módulo accelerators
se comunica con el resto de la aplicación a través de una interfaz que intercambia 4 campos de datos, de una manera completamente opaca. Mientras la interfaz no cambie, se pueden hacer cambios en todas partes: permanecerán contenidos en su módulo. Con habilidades adecuadas, esta lógica pudo haber sido extendida a soporte de dispositivos MIDI. Pero esa es la diferencia entre ingeniería y prototipos de prueba de conceptos que nunca deberían entrar en producción.
Desafortunadamente, esta es una marca de la forma de hacer las cosas de Darktable: el código de la GUI está incrustado por todas partes, incluso en el código SQL. Al revés también es cierto, el código SQL se encuentra en muchos lugares de la GUI (mesa de luz, gestión del historial, etiquetado de imágenes, etc.). Los gráficos de dependencias, incrustados en Doxygen, son un efecto secundario muy agradable que muestra la profundidad del problema y pone los espaguetis en evidencia, porque, aparentemente, los problemas no existen hasta que los ves por ti mismo.
Pero no se detiene ahí. Mientras escribía mi propio archivo de configuración de Doxygen, obtuve un error: Doxygen informó 2 archivos de configuración y estaba confundido. Resulta que Darktable tenía todo lo necesario para generación de documentación de desarrollador automatizada desde 2010 . Por qué nunca se puso en producción, y de hecho se alojó en algún servidor, no son simplemente prioridades equivocadas: es negligencia.
Por supuesto, no ayuda que el propietario del dominio darktable.org
no sea el mismo que el que gestiona el servidor donde realmente está alojado. Y la persona que tiene derechos de commit sobre el sitio web de darktable.org
es otra distinta. Lo más urgente que hay que hacer, cuando eres un proyecto de código abierto que hace cero dólares de ingresos, es reproducir todos los errores del mundo corporativo, desde la presión para liberar cosas a medio cocinar a una frecuencia irresponsable, hasta la dispersión de responsabilidades entre “servicios” que realmente no se comunican entre sí (o con grandes retrasos). Porque, en software (ya sea de código abierto o no), los errores están destinados a ser reproducidos. Y dado que el software se ha apoderado del mundo, incluso en lugares donde no se necesitaba, eso dice mucho sobre el mundo en el que vivimos.
Sin embargo, lo que todavía no entiendo del todo es: ¿por qué la urgencia? ¿Por qué seguir trabajando tan mal dada la falta de presión o incentivo financiero para hacerlo? El código abierto es (podría haber sido) el único lugar donde realmente podríamos trabajar correctamente y tomarnos el tiempo necesario para producir calidad a largo plazo. E incluso allí, la miopía del capitalismo se ha apoderado.
Si tan solo los usuarios supieran el estado de profunda mierda en el que cayó este proyecto y cómo todas las horas-hombre invertidas en él lo están empeorando activamente…
Translated from English by : ChatGPT. In case of conflict, inconsistency or error, the English version shall prevail.