Reescribir desde cero los atajos de teclado (aceleradores)
—
—
GUI
Usabilidad
En mi artículo fundacional, Darktable: estrellándose contra el muro a cámara lenta, presenté el desastre que era el nuevo «gran turducken MIDI». El propósito de este turducken1 era reescribir el sistema de atajos de teclado para ampliarlo a los dispositivos MIDI.
A día de hoy, sigo furioso por esta empresa de destrucción masiva; aquí tienes un resumen de las razones:
- en 2021 reemplazó un sistema de atajos de teclado que era bastante bueno, funcionalmente completo, bien probado, estable y programado en menos de 1500 líneas (comentarios incluidos),
- …para añadir compatibilidad con dispositivos MIDI y mandos de PlayStation (!?!)…
- …pero en mi encuesta de Darktable de 2022, un año después de esta nueva función, de más de 1251 usuarios que participaron:
- el 81% de los usuarios no tenía un dispositivo MIDI ni pensaba conseguir uno,
- el 2% ni siquiera sabía lo que era un dispositivo MIDI.
- el 8% de los usuarios tenía un dispositivo MIDI pero no lo usaba con Darktable,
- el 6% se planteaba quizás conseguir un dispositivo MIDI en el futuro,
- el 2% de los usuarios tenía un dispositivo MIDI que realmente usaba en Darktable,
- el código era absolutamente terrible, en términos de:
- calidad del código: sentencias
if/switch-caseilegibles anidadas en 4 niveles, en medio de funciones de 1000 líneas (publiqué fragmentos de ejemplo en mi artículo), - volumen de código:
- 3546 líneas de código para Darktable 4.0,
- 4397 líneas de código para Darktable 5.0,
- el aumento de volumen es una consecuencia directa de intentar corregir errores en una arquitectura que no se puede arreglar porque su complejidad fomenta más complejidad. Todo eso surge del diseño, pero resolver los problemas creados por la complejidad añadiendo más complejidad no es una solución.
- complejidad del código:
- complejidad ciclomática :
- 1088 para Darktable 4.0,
- 1245 para Darktable 5.0 (detalles ),
- complejidad cognitiva :
- 1885 para Darktable 4.0,
- 2098 para Darktable 5.0 (detalles ).
- es con diferencia la función más compleja del software, aunque no opera sobre imágenes. A modo de comparación, la segunda función más compleja es la decodificación de metadatos EXIF, que tiene una complejidad cognitiva de 1348.
- complejidad ciclomática :
- calidad del código: sentencias
- no decodifica los modificadores de teclas por diseño, sino que solo trata las pulsaciones de teclas físicas, lo que significa que:
- la entrada «1» del teclado numérico se decodifica como
Keypad End, - la entrada «1» de un teclado francés AZERTY se decodifica como
Shift+&, oShift+"en BÉPO, - por lo tanto necesitas duplicar todos tus atajos basados en números para cada forma de introducir un número, y prepararte para que la ventana de configuración de atajos no contenga ningún número real en las combinaciones de teclas.
- la entrada «1» del teclado numérico se decodifica como
- el diseño de cara al usuario es absolutamente terrible, con demasiadas acciones y emulaciones que configurar («efectos»), que ni siquiera están completamente documentadas 4 años después (¿qué es «ctrl-toggle»? ¿«right-activate»?), y la configuración de atajos usa una extraña ventana dividida que no tiene ningún sentido,
- la implementación también es terrible: la función conoce toda la GUI del software, y la GUI del software conoce el código de los atajos. Aquí no hay modularidad, y cambiar cualquier cosa en el código de los atajos puede tener efectos inesperados e indeseados en cualquier parte del software.2 Basta con ver el grafo de dependencias de abajo,
- se pueden asociar varios «atajos» (o asignaciones MIDI) a la misma acción, lo que significa que cada interacción del usuario tiene que recorrer toda la lista de acciones disponibles, provocando una gestión de atajos muy ineficiente, retardos en la GUI en algunos casos y falsos positivos de «combinación de teclas desconocida» en casos peculiares.


El grafo de dependencias de src/gui/accelerators.c (el gran turducken MIDI) antes de la reescritura. Adivina por qué lo llamamos «código espagueti »… Esto deja claro que hay una dependencia bidireccional entre el código de los aceleradores y el resto del código de la GUI. Esto es una pesadilla de mantener.