Im Dezember 2019 habe ich darum gebeten, dass jemand die Erstellung von AppImages-Paketen für Darktable übernimmt. Der offensichtliche Vorteil wäre gewesen, frühe Tests zu ermöglichen, vor der Veröffentlichung, von Menschen, die den Quellcode nicht selbst erstellen können, um hoffentlich frühes Feedback zu liefern und beim Debuggen vor der Veröffentlichung zu helfen. Dies war nie eine Priorität, was bedeutet, dass es in Ordnung war, einen Vorveröffentlichungs- und eine Nachveröffentlichungsspur zu haben, um Bugs zu beheben.
Ich machte keinen Witz, als ich sagte, dass Darktable eine Burnout-Fabrik ist, die wie die schlimmsten Startups verwaltet wird, außer dass niemand einen Exit machen wird und es im Grunde ein trockener Verlust für alle Beteiligten ist. Ich bin darüber umso wütender, dass viele Mannstunden damit verschwendet wurden, die Benutzeroberfläche mit Kosmetik zu überladen, während nächtliche Builds für den allgemeinen Gebrauch sowohl die Qualität der Software als auch den Komfort und die Lebensqualität ihrer Wartenden verbessern würden. Diese Ziele waren offensichtlich nicht wichtig.
Also, da man nie besser bedient wird, als durch eigene Fehler, musste ich es selbst machen , und Mitte Dezember 2022 bekam Ansel AppImage-Nächtebau Skripte, das Darktable einen Monat später genutzt hat. Mit der Kohorte von IT-Leuten, „ohne Pixelmathematikfähigkeiten“, die um Darktables Hype herum streifen und fragen, wie sie helfen könnten, natürlich war das beste Ressourcenmanagement, Mannstunden von einem der wenigen Mathematiker wegzulenken, die für eine rein IT- Aufgabe verfügbar waren. Es dauerte mich ungefähr 50 Stunden, weil es wirklich nicht dasselbe ist, ein lokal funktionierendes Skript zu haben, wie YAML Skripte ins Ohr von Github Action zu flüstern, und ich musste es lernen, während ich es tat. Da Ansel 20 bis 30 Minuten auf Github Action-Instanzen braucht (oder scheitert), ist Ihr Arbeitstag eine lange Stottersitzung ineffizienten Multitaskings, während Sie auf die Remoteergebnisse Ihrer Skriptänderungen warten. Ich hasse Programmieren, und ich mache es für Mathematik und Physik, aber diese Art von Arbeit am Server konfigurieren ist wirklich die schlimmste Art von Programmierung, sogar insofern, als dass sie weder kreativ noch kognitiv herausfordernd ist, es ist nur eine zeitaufwendige Art, an Designbeschränkungen von Drittanbieter-APIs vorbei zu arbeiten.
So, schließlich war Ansel ein halborganisiertes Softwareprojekt, das in der Lage war, eine Benutzerbasis einzubeziehen, die größer war als nur die hartnäckigen Geeks, die auf jeden herabschauen, der nicht in der Lage ist, GCC und CMake zum Laufen zu bringen, mit einem großen „Download“-Button auf der Startseite, der immer auf die neueste Version zeigt, ohne dass Benutzer herausfinden müssen, welche die neueste ist. Denn Fotobearbeitungssoftware sollte keine Benutzer nach ihrer Computerliteratur filtern, egal ob sie aus der Linux-Welt kommt (was wirklich keine Ausrede ist), oder es gibt ein Memorandum von der Free Software Foundation, das ich (nicht) bekommen habe.
Aber das letzte große Problem war das Fehlen einer Entwicklerdokumentation. Im Jahr 2018, als ich anfing, zu Darktable beizutragen, hatte ich große Schwierigkeiten zu erfassen, wie die inneren Abläufe nur durch das Lesen des Codes verbunden waren. 7 Jahre später muss ich immer noch meinen Weg durch den Code rückentwickeln, mit ebenso viel grep
wie meinem Intuition, da der Code nicht modular ist, an wenigen Stellen APIs verwendet werden, Kommentare fehlen, und Zeilenweise Git blame nicht immer erlaubt, in die Geschichte der Designänderungen zurückzugehen, wenn jemand (unnötige) Code-Formatierungsänderungen begangen hat.
Der Mangel an Entwicklerdokumentation hat dazu geführt, dass viele Funktionen mehr als einmal, an verschiedenen Stellen, von mehreren Entwicklern (und manchmal sogar von denselben im Laufe der Jahre) implementiert wurden. Zum Zeitpunkt des Schreibens gibt es immer noch 4 oder 5 verschiedene Möglichkeiten, in Ansel, um eine Bildgeschichte von der Bibliotheksdatenbank in eine Sidecar-XMP-Datei zu schreiben. Einige dieser Möglichkeiten werden selten verwendet, daher kaum getestet, und Bugs dort könnten jahrelang unbemerkt bleiben, bis jemand den super-spezifischen Bug meldet, der im Wald der Optionen versteckt ist. Dann ist es für den zuständigen Maintainer ein albernes Spiel, herauszufinden, warum XMP nur unter bestimmten Umständen versagt, was eine archäologische Untersuchung in der Codebasis erfordert, um herauszufinden, dass es nicht die Haupt-XMP-Schreibmethode verwendet. XMP ist ein spezifisches und noch aktuelles Beispiel, aber es gab viele andere. Sie verstehen die Idee.
Ich hatte seit mehreren Jahren bemerkt, dass ( alte) Darktable-C-Header-Dateien ziemlich alle Doxygen-Dokumentationsstränge hatten. Dies ist eine sehr faule Art der Dokumentation: Führen Sie den Befehl doxygen -g <Config-Datei>
gegen Ihr Quellverzeichnis aus, und Doxygen erstellt Ihnen eine statische HTML-Website für alle APIs. Dann können Sie alle HTML-Dateien in ein Webserververzeichnis kippen und das Ihre Dev-Dokumente nennen: der einzige mühsame Teil ist das Schreiben der Konfigurationsdatei, die Sie nur einmal schreiben. Also habe ich das getan: dev.ansel.photos. APIs, die ich umgeschrieben habe (wie `selection.h ) sind dokumentiert, wie ich Fortschritte gemacht habe. Höhere Beschreibungen der Softwarearchitektur sind im Kommen.
Das großartige an Doxygen ist, dass es auch Abhängigkeitsgraphen von “Modulen” und APIs erstellt. Und dort kann man tatsächlich sehen, warum ich Darktable’s Code Spaghetti nenne. Dies ist der Abhängigkeitsgraph von accelerators.h
, dem Backend für Tastatur- und MIDI-Verknüpfungen:
Das zeigt, dass das Backend für Verknüpfungen absolut nicht modular ist: Es erbt die gesamte Software. Jede Änderung anderswo kann dort unvorhergesehene Effekte haben, und umgekehrt. Dies ist umso beunruhigender, da diese Datei die höchste zyklomatische Komplexität der gesamten Software aufweist, was sie zur am schwersten zu wartenden Datei macht (ich wage nicht einmal zu sagen erweitern, an diesem Punkt wäre es unverantwortlich). Aber es ist auch völlig verdreht in Bezug auf die Richtung der Includes: Verknüpfungen sind ein grundlegender Block, der einbezogen werden sollte (alias geerbt) in der GUI, die Verknüpfungen implementieren wird (Dunkelkammer/Leuchttisch-Ansichten, Schieberegler und Kombinationsfelder, Module). Stattdessen zeigt der Graph (und die Datei #include
-Header), dass Verknüpfungen auch ihre “Kinder” einbeziehen (erben), also haben wir eine doppelte Abhängigkeit, und das ist der schlechteste mögliche Weg, es zu tun.
Es ist wie beim Bau eines Hauses: Das Haus sollte von seinen Wänden wissen, die Wände von ihren Ziegeln. Warum? Weil das Haus aus Wänden besteht und die Wände aus Ziegeln, sodass jede Unterkomponente die Natur und das Verhalten des Ganzen bestimmt. Daher muss das Ganze seine unmittelbaren Komponenten kennen. Man macht die Ziegel nicht auf das Haus aufmerksam, denn sie werden ihre Natur nicht ändern, je nach dem, zu welchem Bauwerk sie gehören, und das wäre ein furchtbar fehlerhaftes Design. Ebenso ist es ein unnötiges Level von Mikromanagement, wenn man das Haus auf die Ziegel aufmerksam macht: Sobald es von seinen Wänden weiß, liegt es an den Wänden, das Verhalten ihrer Ziegel zu berücksichtigen und vielleicht relevante Informationen an das Haus weiterzuleiten. Objektorientierte Sprachen haben eingebaute (und obligatorische) Methoden, um all das sauber zu regeln. Aber es ist C, also kannst du tun, was du willst. Das bedeutet nicht, dass es eine gute Idee ist, es bedeutet nicht, dass du es tun solltest. Und, nun, dass C nicht intrinsisch objektorientiert ist, ist kein Hindernis, Objektmuster, Vererbung und Modularität zu verwenden. Es ist nur so, dass der Entwickler keine Hilfe von der Syntax der Sprache bekommt, um dies zu tun.
Das ist die gleiche Datei nach meiner vollständigen Neuschreibung des Verknüpfungs-Backends:
Das zeigt deutlich, dass der neue Verknüpfungshandler ein dünner Wrapper über Gtk-nativen Verknüpfungen ist, er kennt den Rest der Software nicht und interessiert sich nicht dafür. Wir können uns auch die Datei accelerators.c
ansehen:
Jetzt gibt es dort viele Includes aus darktable.h
, die nur verwendet werden, um die Debug-Helfer zu erhalten (sie sollten von dieser Datei umgestaltet werden), und enthält auch viel unnötigen Müll. Jedenfalls ist accelerators.c
nur auf Gtk/Gdk aufmerksam, was bedeutet, dass es ein echtes Modul ist: Es ist komplett vom Rest der Software isoliert. GUI-Widgets, die Verknüpfungen implementieren, werden ihren Verknüpfungspfad deklarieren, wie Ansel/Global/Menu/File/Import
, ihre Standardtasten und eine Referenz (Zeiger) auf sich selbst. Widget-lose Aktionen, die Verknüpfungen haben, werden eine Callback-Funktion und Eingabedaten an den Verknüpfungshandler deklarieren, anstatt eines Zeigers auf ein Widget.
Wir speichern/stellen die Pfade und Tastenassoziationen in/aus der Datei keyboardrc
und das war’s. Zu diesem Zeitpunkt gibt es kein Fenster, um Verknüpfungen in der GUI zu definieren, aber um eines zu erstellen, müsste nur eine Liste (Schleife über) bekannter Pfade und deren zugeordnete Tasten erstellt werden. Wenn der Verknüpfungshandler eine bekannte Tastenfolge abfängt:
- für die an Widgets gebundenen Aktionen sendet er ein
activate
Gtk-Signal an das entsprechende Widget, und dieses Widget tut sein eigenes Ding über ein Callback (was das gleiche ist wie das Callback, das Klicks behandelt, sodass der Code zwischen Klicks und Tastaturaktivierungen einheitlich ist), - für die Widget-losen Aktionen wird direkt die deklarierte Callback-Funktion über die deklarierten Daten aufgerufen.
Auf beiden Wegen kommuniziert das accelerators
Modul mit dem Rest der Anwendung über eine Schnittstelle, die 4 Datenfelder in einer vollständig undurchsichtigen Weise austauscht. Solange sich die Schnittstelle nicht ändert, können überall Änderungen vorgenommen werden: Sie bleiben innerhalb ihres Moduls enthalten. Mit den richtigen Fähigkeiten hätte diese Logik auf die Unterstützung von MIDI-Geräten erweitert werden können. Aber das ist der Unterschied zwischen Ingenieurwesen und dem Prototyping von Konzeptnachweisen, die niemals in die Produktion gelangen sollten.
Dies ist leider ein Markenzeichen von Darktable’s Vorgehensweise: GUI-Code ist überall eingewoben, sogar im SQL-Code. Umgekehrt wird SQL-Code an vielen GUI-Orten gefunden (Leuchttisch, Verlaufsverwaltung, Bildmarkierungen usw.). Abhängigkeitsgrafiken, eingebettet in Doxygen, sind eine sehr nette Nebenwirkung, die das Ausmaß des Problems zeigt und das Spaghetti sehr offensichtlich macht, weil Probleme anscheinend nicht existieren, bis man sie selbst tatsächlich sieht.
Aber damit endet es nicht. Während ich meine eigene Doxygen-Konfigurationsdatei schrieb, bekam ich einen Fehler: Doxygen meldete 2 Konfigurationsdateien und war verwirrt. Es stellt sich heraus, dass Darktable seit 2010 alles verkabelt hatte, um eine automatische Entwicklerdokumentation zu generieren . Warum es nie in die Produktion ging und tatsächlich auf einem Server gehostet wurde, ist nicht nur falsche Priorisierung: Es ist Fahrlässigkeit.
Natürlich hilft es nicht, dass der Typ, dem die Domain darktable.org
gehört, nicht derselbe ist wie derjenige, der den Server verwaltet, auf dem sie tatsächlich gehostet wird. Und der Typ, der tatsächlich die commit-Rechte auf der darktable.org
Website hat, ist ein anderer. Der dringendste Punkt, den es zu tun gibt, wenn man ein Open-Source-Projekt ist, das null Dollar Einkommen macht, ist, alle Fehler der Unternehmenswelt zu reproduzieren, vom Druck, halbfertigen Mist in verantwortungsloser Frequenz zu veröffentlichen, bis zur Verteilung von Verantwortungen zwischen “Diensten”, die wirklich nicht miteinander kommunizieren (oder mit großen Verzögerungen). Denn im Softwarebereich (egal ob Open-Source oder nicht) sind Fehler dazu da, reproduziert zu werden. Und da Software die Welt übernommen hat, sogar an Orten, die sie nicht brauchten, sagt das viel über die Welt aus, in der wir leben.
Das eine, was ich immer noch wirklich nicht verstehe, ist: warum die Dringlichkeit? Warum weiterhin so schlecht arbeiten, angesichts des Fehlens von Druck oder finanziellen Anreizen, auszusteigen? Open-Source ist (hätte sein können) der eine Ort, an dem wir tatsächlich richtig arbeiten und die nötige Zeit nehmen könnten, um langfristige Qualität zu produzieren. Und selbst dort hat die Kurzsichtigkeit des Kapitalismus überhandgenommen.
Wenn die Nutzer nur wüssten, in welch tiefem Schlamassel dieses Projekt gefallen ist und wie alle darauf investierten Mannstunden es aktiv verschlimmern…
Translated from English by : ChatGPT. In case of conflict, inconsistency or error, the English version shall prevail.