Was passiert, wenn eine Gruppe von Amateurfotografen, die zu Amateurentwicklern wurden, zusammen mit einer Reihe von Back-End-Entwicklern, die Bibliotheken für Entwickler entwickeln, entscheiden, ohne Methode oder Struktur an einer Industriessoftware für Endbenutzer zu arbeiten, deren Kernkompetenz (Kolorimetrie und Psychophysik) irgendwo zwischen einem College-Abschluss in Fotografie und einem Master-Abschluss in angewandten Wissenschaften liegt, während sie versprechen, zwei Veröffentlichungen pro Jahr ohne Projektmanagement zu liefern? Ganz zu schweigen davon, dass die Gründer und die erste Generation von Entwicklern weitergezogen und geflüchtet sind?

Rate mal!

Grundlegende Funktionen verschlechtern

Die 2020er sind 40 Jahre zu spät, um die Interaktionsparadigmen zwischen Benutzer und Computer neu zu erfinden, sei es, wie wir eine Tastatur und eine Maus verwenden, um die Schnittstelle zu steuern, oder das Verhalten eines Dateibrowsers. Seit den 1980er Jahren haben sich alle allgemein verwendbaren Computergeräte mehr oder weniger auf vereinheitlichte Semantiken geeinigt, bei denen die Escape-Taste die aktuelle Anwendung schließt, ein Doppelklick Dateien öffnet und das Mausrad die aktuelle Ansicht scrollt. Darktable[1] gönnt sich eine unangebrachte Freude daran, all das zu ignorieren, und die jüngsten Änderungen verschlimmern die Dinge: Es ist jetzt zwingend erforderlich, die Dokumentation zu lesen, um Aufgaben so einfach wie das Sortieren von Dateien oder das Zuweisen von Tastaturkürzeln zu GUI-Aktionen zu erfüllen.

Modulgruppen

Alles beginnt mit der Überarbeitung der Modulgruppen  im Jahr 2020, die die Entscheidung nicht entscheidet , eine einheitliche Modulreihenfolge festzulegen.

image

Seit 2018  kämpfe ich darum, die grafische Benutzeroberfläche von Darktable zu bereinigen, insbesondere die Modulorganisation. Eine grafische Benutzeroberfläche sollte bewährte Verfahren fördern, indem sie Werkzeuge in der typischen Reihenfolge anordnet, in der sie verwendet werden sollten. Schlechte Praktiken sind solche, die das Risiko von farbmetrischen Inkonsistenzen oder von zirkulärer Bearbeitung erhöhen, bei der man zurückgehen muss, um Änderungen, die später vorgenommen wurden, erneut zu berücksichtigen, obwohl schlechte Praktiken in einfachen Fällen funktionieren können. Im Kontext der Bildbearbeitung, einer hochtechnischen Aufgabe, bei der viele Dinge den Endbenutzern unter der Oberfläche der Benutzeroberfläche verborgen bleiben, ermöglichen bewährte Verfahren auch schwach qualifizierten Personen, die Software auf eine Weise zu verwenden, die die Fehlerwahrscheinlichkeit reduziert.

Diese Anwendungsreihenfolge wird größtenteils von technischen Überlegungen wie der Reihenfolge der Anwendung von Modulen in der Pipeline-Sequenz und der Verwendung von gezeichneten und parametrischen Masken diktiert, deren Effekt von den vorhergehenden Modulen abhängt. Diese Überlegungen zu ignorieren, ist gleichbedeutend mit der Suche nach Problemen, obwohl der heiße Trend in den 2010er und 2020er Jahren ist, zu glauben, dass digitale Technologien sich nur auf die materiell Realität zum Wohl des Benutzers abkoppeln.

Beispielsweise führt der auferlegte Zwang, die Pipeline-Design zu ermöglichen, um eine beliebige Modulreihenfolge zu zulassen, zu mathematisch unlösbare Problemen  in Bezug auf die Berechnung von Maskenkoordinaten, und es gibt keine programmierte Lösung (außer der Entspannung dieser Einschränkung), weil die Mathematik nein sagt.

Außerdem bleibt ein bedeutender Teil der programmierenden Benutzer, die sich um das Projekt auf Github und auf der Entwickler-Mailingliste drehen, überzeugt, dass es keinen guten oder schlechten Workflow gibt, sondern nur persönliche Vorlieben, was wahrscheinlich dann wahr ist, wenn man Kunst ohne Zeitbeschränkung, Budgetbeschränkung oder Ergebnisbeschränkung praktiziert. Dementsprechend sollten Module in der Pipeline oder im Workflow beliebig neu geordnet werden können. Die Verwirrung entsteht aus der Tatsache, dass nicht-destruktives Bearbeiten fälschlicherweise als asynchron betrachtet wird (was es fast wäre, wenn wir keine Masken oder Mischmodi verwenden würden), während die Pixel-Pipeline sequenziell ist und näher an einer Schichtlogik liegt, wie wir sie in Adobe Photoshop, Gimp, Krita usw. finden.

Das Entkoppeln der Modulordnung in der Benutzeroberfläche von der Pipeline-Ordnung ist gleichbedeutend damit, jede Verwendung, selbst pathologische, zu ermöglichen, und zwingt dazu, Seite um Seite Dokumentation  zu schreiben, um zu warnen, zu erklären, was zu tun ist, wie und warum; Dokumentation, die niemand lesen wird, um am Ende jede Woche dieselben Fragen in jedem Forum in Schleife zu stellen.

Bei dieser Geschichte verliert jeder durch ein Interface-Design, das so flexibel ist, dass es nicht sicher und robust standardmäßig gemacht werden kann. Im menschlichen Körper hat jedes Gelenk einige Freiheitsgrade entlang bestimmter Achsen; wenn jedes Gelenk 340 ° um jede Achse des 3D-Raums drehen könnte, wäre die Struktur instabil, weil sie zu flexibel ist, und nicht in der Lage, mit hohen Lasten zu arbeiten. Die Metapher hält sich in der Industrie-Software. Wir schwimmen im FLOSS-Cargo-Kult , wo Menschen die Illusion der Wahl lieben, dass ihnen viele Optionen angeboten werden, von denen die meisten unbrauchbar oder gefährlich sind, auf Kosten der Einfachheit (KISS ), und wo die Mehrheit der Benutzer die Implikationen jeder Option nicht versteht (und nicht das geringste Interesse hat, sie zu verstehen).

In Ermangelung eines Konsenses über die Interface-Modulordnung wurde Ende 2020 ein kompliziertes, zerbrechliches und schwergewichtiges Werkzeug eingeführt, das jedem Benutzer erlaubt, das Layout von Modulen in Tabs zu konfigurieren. Es bietet viele nutzlose Optionen und speichert das aktuelle Layout in der Datenbank, indem es den übersetzten Namen von Modulen verwendet, was bedeutet, dass das Ändern der UI-Sprache Ihre Voreinstellungen verliert. Vollständig konfigurierbar, lässt es Benutzer entscheiden, wie sie sich selbst schaden können, ohne jeglichen Leitfaden für bewährte Vorgehensweisen. Dieser Müll ist mit 4000 Zeilen fröhlich Mischende SQL-Anfragen in der Mitte des Interface-GTK-Codes  kodiert, und Voreinstellungen werden durch redundante Compiler-Makros  erstellt, während Module schon ewig ein binäres Flag  haben, das in der Lage ist, ihre Standardgruppe modular zu setzen.

Noch wichtiger ist, dass es eine einfache und effektive Funktion ersetzt, die bis Darktable 3.2 verfügbar war:

image

Ein Klick auf den Modulnamen aktiviert es, ein zweiter fügt es zur Spalte der Favoriten hinzu, ein dritter verbirgt es aus der Benutzeroberfläche. Alles ermöglicht Voreinstellungen und speichert das aktuelle Layout in einfachem Text in der Datei darktablerc. Einfach und robust, mit 688 lesbar und gut strukturiert  codiert, war die Funktion daher nicht amüsant genug für den Hobbyentwickler mittleren Alters, und es war dringend erforderlich, es durch ein labyrinthartiges System zu ersetzen.

Tastenkürzel

2021 wurde hinzugefügt, was ich den großen MIDI-turducken  nenne. Das Ziel ist es, die Schnittstelle der Tastenkürzel zu erweitern (bereits 2019 erweitert, um “dynamische Kürzel” zu unterstützen, die Tastatur- und Mausaktionen kombinieren), um MIDI-Geräte und… Videospielcontroller zu unterstützen.

Ende 2022, also eineinhalb Jahre nach dieser Funktion, haben in der Umfrage, die ich durchgeführt habe , weniger als 10% der Benutzer ein MIDI-Gerät, und nur 2% verwenden es mit Darktable. Zum Vergleich mit den 45% der Benutzer, die ein Grafiktablett (wie Wacom) besitzen, dessen Unterstützung in Darktable immer noch so mangelhaft ist, dass nur 6% es verwenden. Ungeachtet der mangelhaften Priorisierung tolerieren ich hier nicht die Randwirkungen, die durch diese Änderung eingeführt wurden und die globalen Kosten, beginnend mit der Tatsache, dass es keine benutzerdefinierten Tastenkürzel aus Versionen vor 3.2 importiert, und es macht die Konfiguration neuer Kürzel furchtbar kompliziert.

Vor dem großen Turducken konnte nur eine begrenzte Liste von GUI-Aktionen Tastenkürzeln oder gemischten Verknüpfungen (Tastatur + Maus) zugeordnet werden. Diese Liste wurde manuell von Entwicklern kuratiert. Der große MIDI-Turducken ermöglicht, alle GUI-Aktionen Tastenkürzeln zuzuweisen und stellt den Benutzern eine Liste von mehreren Tausend konfigurierbaren Einträgen zur Verfügung, in der es schwierig ist, die einzigen drei zu finden, die Sie wirklich brauchen, und die Textsuchmaschine ist zu rudimentar, um hilfreich zu sein:

image

Beachten Sie die Verwendung von “Effekten”, über die die Dokumentation  nicht hilft. Nur durch deduktion (weil der Code auch nicht kommentiert ist ) habe ich am Ende verstanden, dass sie Emulationen typischer Desktop-Interaktionen (Maus und Tastatur) für die Verwendung mit MIDI-Geräten und Gamepad-Controllern sind (aber Sie müssen mir dennoch erklären, was Ctrl-Toggle, Right-Activate oder Right-Toggle in Bezug auf typische Desktop-Interaktionen bedeuten).

Was inakzeptabel ist, ist, dass die Verwendung des Ziffernblocks von Haus aus  fehlerhaft ist, insbesondere um nummerierte Bewertungen (Sterne) auf Miniaturansichten im Lighttable zuzuweisen. In der Tat werden die Schalter (NumLock und CapsLock) von der Sache nicht richtig decodiert und Zahlen werden anders behandelt, ob sie vom typischen “Text”-Tastatur oder dem Ziffernblock eingegeben werden. So wird die 1 von der Tastatur als Keypad-End decodiert, unabhängig vom Zustand des Numlocks. So musste ich Zahlentastenkürzel auf einem französischen BÉPO-Keyboard konfigurieren und die Konfiguration für den Ziffernblock duplizieren:

image

Sie müssen sich nur merken, dass Shift+" und Kp End beide 1 bedeuten und alle Shortcuts für den Ziffernblock und dem Rest der Tastatur duplizieren. Kurz gesagt, wir brechen eine grundlegende Benutzererwartung und senden Designkritiken zum Teufel. Die Regression wird in allen Darktable-Foren erwähnt, scheint aber niemanden zu stören.

Der Fix dieses Fehlers dieser Funktion wurde in Ansel  gemacht und die NumPadtasten werden direkt im Code auf Standardtasten umprogrammiert , für insgesamt 100 Codezeilen einschließlich Kommentaren. Denn diese Korrektur war sehr schwer in der Tat: Ich las die Gdk-Dokumentation  und nahm ihr Beispiel Zeile für Zeile. 2 Jahre verbracht, nur um darauf zu warten…

Das i-Tüpfelchen ist, dass wir ein weiteres Mal 1306 Zeilen klaren und strukturierten Codes  durch ein Monstrum von fast 4400 Zeilen  ersetzt haben, mit Juwelen wie :

  1. die while-Schleife des Todes (Quelle ) :
 1  gboolean applicable;
 2  while((applicable =
 3           (c->key_device == s->key_device && c->key == s->key && c->press >= (s->press & ~DT_SHORTCUT_LONG) &&
 4           ((!c->move_device && !c->move) ||
 5             (c->move_device == s->move_device && c->move == s->move)) &&
 6           (!s->action || s->action->type != DT_ACTION_TYPE_FALLBACK ||
 7            s->action->target == c->action->target))) &&
 8        !g_sequence_iter_is_begin(*current) &&
 9        (((c->button || c->click) && (c->button != s->button || c->click != s->click)) ||
10         (c->mods       && c->mods != s->mods ) ||
11         (c->direction  & ~s->direction       ) ||
12         (c->element    && s->element         ) ||
13         (c->effect > 0 && s->effect > 0      ) ||
14         (c->instance   && s->instance        ) ||
15         (c->element    && s->effect > 0 && def &&
16          def->elements[c->element].effects != def->elements[s->element].effects ) ))
17  {
18    *current = g_sequence_iter_prev(*current);
19    c = g_sequence_get(*current);
20  }
  1. Der switch-case, der if-Anweisungen auf 2 Ebenen verschachtelt (Quelle ) :
 1  switch(owner->type)
 2  {
 3  case DT_ACTION_TYPE_IOP:
 4    vws = DT_VIEW_DARKROOM;
 5    break;
 6  case DT_ACTION_TYPE_VIEW:
 7    {
 8      dt_view_t *view = (dt_view_t *)owner;
 9
10      vws = view->view(view);
11    }
12    break;
13  case DT_ACTION_TYPE_LIB:
14    {
15      dt_lib_module_t *lib = (dt_lib_module_t *)owner;
16
17      const gchar **views = lib->views(lib);
18      while(*views)
19      {
20        if     (strcmp(*views, "lighttable") == 0)
21          vws |= DT_VIEW_LIGHTTABLE;
22        else if(strcmp(*views, "darkroom") == 0)
23          vws |= DT_VIEW_DARKROOM;
24        else if(strcmp(*views, "print") == 0)
25          vws |= DT_VIEW_PRINT;
26        else if(strcmp(*views, "slideshow") == 0)
27          vws |= DT_VIEW_SLIDESHOW;
28        else if(strcmp(*views, "map") == 0)
29          vws |= DT_VIEW_MAP;
30        else if(strcmp(*views, "tethering") == 0)
31          vws |= DT_VIEW_TETHERING;
32        else if(strcmp(*views, "*") == 0)
33          vws |= DT_VIEW_DARKROOM | DT_VIEW_LIGHTTABLE | DT_VIEW_TETHERING |
34                 DT_VIEW_MAP | DT_VIEW_PRINT | DT_VIEW_SLIDESHOW;
35        views++;
36      }
37    }
38    break;
39  case DT_ACTION_TYPE_BLEND:
40    vws = DT_VIEW_DARKROOM;
41    break;
42  case DT_ACTION_TYPE_CATEGORY:
43    if(owner == &darktable.control->actions_fallbacks)
44      vws = 0;
45    else if(owner == &darktable.control->actions_lua)
46      vws = DT_VIEW_DARKROOM | DT_VIEW_LIGHTTABLE | DT_VIEW_TETHERING |
47            DT_VIEW_MAP | DT_VIEW_PRINT | DT_VIEW_SLIDESHOW;
48    else if(owner == &darktable.control->actions_thumb)
49    {
50      vws = DT_VIEW_DARKROOM | DT_VIEW_MAP | DT_VIEW_TETHERING | DT_VIEW_PRINT;
51      if(!strcmp(action->id,"rating") || !strcmp(action->id,"color label"))
52        vws |= DT_VIEW_LIGHTTABLE; // lighttable has copy/paste history shortcuts in separate lib
53    }
54    else
55      fprintf(stderr, "[find_views] views for category '%s' unknown\n", owner->id);
56    break;
57  case DT_ACTION_TYPE_GLOBAL:
58    vws = DT_VIEW_DARKROOM | DT_VIEW_LIGHTTABLE | DT_VIEW_TETHERING |
59          DT_VIEW_MAP | DT_VIEW_PRINT | DT_VIEW_SLIDESHOW;
60    break;
61  default:
62    break;
63  }
  1. Die verschachtelten switch-case des Dämons, mit geschickt versteckten Zusatzklauseln (Quelle ) :
 1case DT_ACTION_ELEMENT_ZOOM:
 2    ;
 3    switch(effect)
 4    {
 5    case DT_ACTION_EFFECT_POPUP:
 6      dt_bauhaus_show_popup(widget);
 7      break;
 8    case DT_ACTION_EFFECT_RESET:
 9      move_size = 0;
10    case DT_ACTION_EFFECT_DOWN:
11      move_size *= -1;
12    case DT_ACTION_EFFECT_UP:
13      _slider_zoom_range(bhw, move_size);
14      break;
15    case DT_ACTION_EFFECT_TOP:
16    case DT_ACTION_EFFECT_BOTTOM:
17      if((effect == DT_ACTION_EFFECT_TOP) ^ (d->factor < 0))
18        d->max = d->hard_max;
19      else
20        d->min = d->hard_min;
21      gtk_widget_queue_draw(widget);
22      break;
23    default:
24      fprintf(stderr, "[_action_process_slider] unknown shortcut effect (%d) for slider\n", effect);
25      break;
26    }

Programmierer verstehen, wovon ich spreche; für die anderen: Seien Sie sich einfach bewusst, dass ich auch nicht mehr verstehe als Sie, was das soll: es ist Mistcode, und wenn dort nicht mehrere Bugs versteckt sind, ist das pures Glück. Bugs in diesem Schlamassel zu jagen, ist wie Archäologie im Abwasserkanal, umso mehr, da Darktable keine Entwicklerdokumentation besitzt und in Abwesenheit sinnvoller Kommentare im Code jede Änderung des oben genannten Codes zwangsläufig mit einer Rückwärtsingenieurphase beginnt, die mit der Zeit immer schwieriger wird.

Das eigentliche Problem bei solchem Code ist, dass man ihn nicht verbessern kann, ohne ihn mehr oder weniger vollständig neu zu schreiben: Um ihn zu reparieren, muss man ihn zuerst verstehen, aber der Grund, warum er repariert werden muss, ist genau, dass er unverständlich und langfristig gefährlich ist. Wir nennen das technische Schulden . Kurz gesagt, jede in dieses Feature investierte Arbeit wird zusätzliche Arbeit schaffen, weil es unvernünftig ist, solchen Code inmitten einer Codebasis aus mehreren Hunderttausend Zeilen zu behalten und darauf zu hoffen, dass er uns nicht eines Tages ins Gesicht explodiert.

Es ist umso lächerlicher, im Kontext einer Open-Source-/kostenlosen Anwendung, bei der der Großteil des Personals nicht ausgebildete Programmierer sind. Clevere Entwickler schreiben Code, der von Idioten verstanden wird, und umgekehrt.

Sammlungsfilter

Bis Darktable 3.8 wurden die Sammlungsfilter oben auf der Leuchtplatte verwendet, um die Ansicht einer Sammlung vorübergehend einzuschränken. Die Sammlung ist ein Extrakt der Fotodatenbank basierend auf bestimmten Kriterien, das häufigste davon ist, den Inhalt eines Ordners zu extrahieren (was Darktable als „Filmrolle“ bezeichnet, um alle zu verwirren, weil eine Filmrolle tatsächlich der Inhalt eines Ordners ist, der als flache Liste statt als Baum angezeigt wird - viele Leute denken fälschlicherweise, dass Darktable keinen Dateimanager hat).

Als jahrelanger Darktable-Nutzer habe ich eine Datenbank von über 140.000 Einträgen. Das Extrahieren einer Sammlung unter diesen 140.000 Bildern ist eine langsame Operation. Aber meine Ordner enthalten selten mehr als 300 Bilder. Das Filtern, z. B. der Bilder mit 2 oder mehr Sternen, in einer Sammlung von 300 Dateien, ist schnell, weil es sich um einen Teilbereich von 300 Elementen handelt. Und das Umschalten von einem Filter auf einen anderen geht auch schnell. Der Filter ist nur eine partielle oder vollständige Ansicht einer Sammlung, die für einen schnellen und vorübergehenden Start-und-Stopp-Gebrauch optimiert ist.

Unter dem Vorwand, den Filter-Code zu überarbeiten, der insgesamt 550 Zeilen  umfasste, hat der Chef Gaston Lagaffe  es sich zur Berufung gemacht, dieses Modell zu brechen, um Sammlungsfilter in einfache Sammlungen zu verwandeln, durch mehr als 6.000 Zeilen Code , ganz zu schweigen von den zahllosen Bugfixes, die nur noch mehr Zeilen hinzugefügt haben 1. All das, wie üblich, hoch konfigurierbar und redundant mit dem klassischen Sammlungsmodule , das dort geblieben ist, und von Symbolen bedient, die so kryptisch sind, dass man Text-Tooltips beim Überfahren hinzufügen musste, um zu klären, was sie bedeuten..

In diesem Qualitätscode finden wir die endlose while unter der switch case im if im if im for (Quelle ) :

 1for(int k = 0; k < num_rules; k++)
 2  {
 3    const int n = sscanf(buf, "%d:%d:%d:%d:%399[^$]", &mode, &item, &off, &top, str);
 4
 5    if(n == 5)
 6    {
 7      if(k > 0)
 8      {
 9        c = g_strlcpy(out, "<i>   ", outsize);
10        out += c;
11        outsize -= c;
12        switch(mode)
13        {
14          case DT_LIB_COLLECT_MODE_AND:
15            c = g_strlcpy(out, _("AND"), outsize);
16            out += c;
17            outsize -= c;
18            break;
19          case DT_LIB_COLLECT_MODE_OR:
20            c = g_strlcpy(out, _("OR"), outsize);
21            out += c;
22            outsize -= c;
23            break;
24          default: // case DT_LIB_COLLECT_MODE_AND_NOT:
25            c = g_strlcpy(out, _("BUT NOT"), outsize);
26            out += c;
27            outsize -= c;
28            break;
29        }
30        c = g_strlcpy(out, "   </i>", outsize);
31        out += c;
32        outsize -= c;
33      }
34      int i = 0;
35      while(str[i] != '\0' && str[i] != '$') i++;
36      if(str[i] == '$') str[i] = '\0';
37
38      gchar *pretty = NULL;
39      if(item == DT_COLLECTION_PROP_COLORLABEL)
40        pretty = _colors_pretty_print(str);
41      else if(!g_strcmp0(str, "%"))
42        pretty = g_strdup(_("all"));
43      else
44        pretty = g_markup_escape_text(str, -1);
45
46      if(off)
47      {
48        c = snprintf(out, outsize, "<b>%s</b>%s %s",
49                     item < DT_COLLECTION_PROP_LAST ? dt_collection_name(item) : "???", _(" (off)"), pretty);
50      }
51      else
52      {
53        c = snprintf(out, outsize, "<b>%s</b> %s",
54                     item < DT_COLLECTION_PROP_LAST ? dt_collection_name(item) : "???", pretty);
55      }
56
57      g_free(pretty);
58      out += c;
59      outsize -= c;
60    }
61    while(buf[0] != '$' && buf[0] != '\0') buf++;
62    if(buf[0] == '$') buf++;
63  }

und andere if, die auf 2 Ebenen innerhalb eines switch-case verschachtelt sind, die notwendig sind, um die Tastaturkürzel zu unterstützen (Quelle ).

Diese letzte verdammte Scheiße war der Tropfen, der das Fass zum Überlaufen brachte und mich dazu brachte, Ansel zu forken. Ich weigere mich, an einer tickenden Bombe zu arbeiten in einem Team, das das Problem nicht sieht und in ihrer Freizeit mit Code herumspielt. Programmieren mag sie unterhalten, mich nicht. Und Scheiße zu reparieren, die von unverantwortlichen Kindern gemacht wurde, die doppelt so alt sind wie ich, besonders wenn sie Dinge kaputt machen, die ich vor 3 oder 4 Jahren aufgeräumt habe, macht mich wütend.

Leuchtplatte

Die Leuchtplatte wurde fast vollständig zweimal umgeschrieben, das erste Mal Anfang 2019 und das zweite Mal Ende 2019, was viele fragwürdige Funktionen wie die Sichtungsansicht  hinzufügte.

Kurz gesagt, der Sichtungsmodus ist in 2 Untermodi unterteilt: dynamisch und statisch, die die Anzahl der Bilder unterschiedlich verwalten. Viele Benutzer haben den Unterschied 4 Jahre später immer noch nicht verstanden. Wir haben daher die Standardansicht (Dateimanager), die zoombare Leuchtplatte (die niemand benutzt), die statische Sichtung, die dynamische Sichtung und den Vorschaumodus (ein einzelnes Vollbildbild).

Dann werden der Leuchtplatten-Miniaturansichten weitere Anzeigeoptionen hinzugefügt, die es ermöglichen, Overlays zu definieren: grundlegende permanente Overlays, erweiterte EXIF-permanente Overlays, dasselbe aber nur beim Überfahren, und schließlich die zeitgesteuert überfahrenen Overlays (mit einem konfigurierbaren Timer).

Der UI-Code, der Miniaturansichten und ihre Overlays rendert, muss daher 5 verschiedene Ansichten und 7 Anzeigevarianten  berücksichtigen, das sind 35 mögliche Kombinationen. Der Code, der eine korrekte Größenänderung der Miniaturansichten sicherstellt, benötigt daher insgesamt 220 Zeilen .

Aber damit nicht genug, denn der Code zum Rendern der Miniaturansichten-GUI wird auch mit der unteren Filmleiste „Filmstrip“ geteilt, was tatsächlich 36 mögliche Kombinationen im Rendern von Miniaturansichten ergibt. Multipliziert mit 3 GUI-Themen in verschiedenen Grundfarben ergibt das 108 Sets von CSS-Anweisungen, um die GUI vollständig zu gestalten… von denen viele beim Grafiküberholungsprozess von Darktable 4.0 vergessen wurden , und wie könnte es anders sein ?

In Darktable 2.6 hatten wir 4193 Zeilen für das Paket, das nur die Dateimanager-, zoombare Leuchtplatte- und Vollbild-Anzeigenansichten hatte, mit nur 2 Modi von Miniaturansicht-Overlays (immer sichtbar oder sichtbar beim Überfahren) :

  • 2634 Zeilen views/lighttable.c  für die Leuchtplatte und das Rendern der Miniaturansicht,
  • 1124 Zeilen in libs/tools/filmstrip.c  für den Filmstreifen, der den Code der Leuchtplatte für das Rendern der Miniaturansicht teilweise dupliziert,
  • 435 Zeilen in libs/tools/global_toolbox.c , für das Schaltflächenmenü, das es ermöglicht, die Miniaturansicht-Overlays zu aktivieren oder zu deaktivieren.

Nach Darktable 3.0 und der Hinzufügung der Sichtungsmodi erhalten wir 6731 Zeilen :

Nach Darktable 3.2 und den Ergänzungen der 7 Varianten hoch konfigurierbarer Overlays und einiger Code-Refaktorisierungen, erhalten wir 8380 Zeilen :

In Darktable 4.2, nach der Korrektur vieler Bugs, kommen wir auf insgesamt 9264 Zeilen :

Die Anzahl der Zeilen (insbesondere in Code, der ein unangebrachtes Vergnügen daran findet, Programmierbestpraktiken zu ignorieren) ist ein direkter Indikator für die Schwierigkeit, alles darin zu debuggen, aber auch ein indirekter Indikator (im spezifischen Fall von GUI-Code) für die benötigte CPU-Last, um die Software auszuführen.

In der Tat, wenn Sie darktable -d sql starten und mit dem Mauszeiger über eine Miniaturansicht in der Leuchtplatte fahren, erhalten Sie in der Konsole :

 1140.8252 [sql] darktable/src/common/image.c:311, Funktion dt_image_film_roll(): prepare "SELECT folder FROM main.film_rolls WHERE id = ?1"
 2140.8259 [sql] darktable/src/common/image.c:387, Funktion dt_image_full_path(): prepare "SELECT folder || '/' || filename FROM main.images i, main.film_rolls f WHERE i.film_id = f.id and i.id = ?1"
 3140.8271 [sql] darktable/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 4140.8273 [sql] darktable/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 5140.8275 [sql] darktable/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 6140.8277 [sql] darktable/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 7140.8279 [sql] darktable/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 8140.8280 [sql] darktable/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 9140.8282 [sql] darktable/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
10140.8284 [sql] darktable/src/common/tags.c:635, Funktion dt_tag_get_attached(): prepare "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms, COUNT(DISTINCT I.imgid) AS inb FROM main.tagged_images AS I JOIN data.tags AS T ON T.id = I.tagid WHERE I.imgid IN (104337) AND T.id NOT IN memory.darktable_tags GROUP BY I.tagid  ORDER by T.name"
11140.8286 [sql] darktable/src/common/tags.c:635, Funktion dt_tag_get_attached(): prepare "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms, COUNT(DISTINCT I.imgid) AS inb FROM main.tagged_images AS I JOIN data.tags AS T ON T.id = I.tagid WHERE I.imgid IN (104337) AND T.id NOT IN memory.darktable_tags GROUP BY I.tagid  ORDER by T.name"
12140.9512 [sql] darktable/src/common/act_on.c:156, Funktion _cache_update(): prepare "SELECT imgid FROM main.selected_images WHERE imgid=104337"
13140.9547 [sql] darktable/src/common/act_on.c:156, Funktion _cache_update(): prepare "SELECT imgid FROM main.selected_images WHERE imgid=104337"
14140.9550 [sql] darktable/src/common/act_on.c:288, Funktion dt_act_on_get_query(): prepare "SELECT imgid FROM main.selected_images WHERE imgid =104337"
15140.9552 [sql] darktable/src/libs/metadata.c:263, Funktion _update(): prepare "SELECT key, value, COUNT(id) AS ct FROM main.meta_data WHERE id IN (104337) GROUP BY key, value ORDER BY value"
16140.9555 [sql] darktable/src/common/collection.c:973, Funktion dt_collection_get_selected_count(): prepare "SELECT COUNT(*) FROM main.selected_images"
17140.9556 [sql] darktable/src/libs/image.c:240, Funktion _update(): prepare "SELECT COUNT(id) FROM main.images WHERE group_id = ?1 AND id != ?2"
18140.9558 [sql] darktable/src/common/tags.c:635, Funktion dt_tag_get_attached(): prepare "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms, COUNT(DISTINCT I.imgid) AS inb FROM main.tagged_images AS I JOIN data.tags AS T ON T.id = I.tagid WHERE I.imgid IN (104337) AND T.id NOT IN memory.darktable_tags GROUP BY I.tagid  ORDER by T.name"

Das bedeutet, dass 18 SQL-Anfragen gegen die Datenbank durchgeführt werden, um Bildinformationen abzurufen, und jedes Mal ausgeführt werden, wenn der Cursor über eine neue Miniaturansicht fährt, ohne Grund, da sich die Metadaten seit dem vorherigen Drüberfahren nicht geändert haben.

In Ansel, indem die meisten Optionen entfernt wurden, habe ich es geschafft, 7 Anfragen zu sparen, was immer noch keine doppelten Anfragen verhindert, aber die Zeiten trotzdem etwas verbessert (Zeitstempel sind die Zahlen, die jede Zeile beginnen) :

 112.614534 [sql] ansel/src/common/image.c:285, Funktion dt_image_film_roll(): prepare "SELECT folder FROM main.film_rolls WHERE id = ?1"
 212.615225 [sql] ansel/src/common/image.c:356, Funktion dt_image_full_path(): prepare "SELECT folder || '/' || filename FROM main.images i, main.film_rolls f WHERE i.film_id = f.id and i.id = ?1"
 312.616499 [sql] ansel/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 412.616636 [sql] ansel/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 512.616769 [sql] ansel/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 612.616853 [sql] ansel/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 712.616930 [sql] ansel/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 812.617007 [sql] ansel/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
 912.617084 [sql] ansel/src/common/metadata.c:487, Funktion dt_metadata_get(): prepare "SELECT value FROM main.meta_data WHERE id = ?1 AND key = ?2 ORDER BY value"
1012.617205 [sql] ansel/src/common/tags.c:635, Funktion dt_tag_get_attached(): prepare "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms, COUNT(DISTINCT I.imgid) AS inb FROM main.tagged_images AS I JOIN data.tags AS T ON T.id = I.tagid WHERE I.imgid IN (133727) AND T.id NOT IN memory.darktable_tags GROUP BY I.tagid  ORDER by T.name"
1112.617565 [sql] ansel/src/common/tags.c:635, Funktion dt_tag_get_attached(): prepare "SELECT DISTINCT I.tagid, T.name, T.flags, T.synonyms, COUNT(DISTINCT I.imgid) AS inb FROM main.tagged_images AS I JOIN data.tags AS T ON T.id = I.tagid WHERE I.imgid IN (133727) AND T.id NOT IN memory.darktable_tags GROUP BY I.tagid  ORDER by T.name"

Das Problem ist, dass der Quellcode SQL-Befehle in Funktionen verschachtelt, die die GUI zeichnen, und dieses Durcheinander durch die verschiedenen Schichten zu entwirren, die von „Refactoring“ (angeblich zur Vereinfachung des Codes, aber tatsächlich nein) geerbt wurden, ist erneut Archäologie. Und hätte das Problem behoben worden, als der Code 6700 Zeilen über 3 Dateien betrug, würden wir nicht 4 Jahre später nach den Ursachen in 2500 zusätzlichen Zeilen suchen, die nun auf 7 verschiedene Dateien verteilt sind (ohne .h Dateien zu zählen).

Wir befinden uns in dem Paradebeispiel, wo „Refactoring“ tatsächlich den Code verkompliziert hat und wo das Zusammenführen von Miniaturansicht-Code zwischen Filmstreifen und Leuchtplatte nur mehr interne if (Verzweigungen) auf mehreren Ebenen verschachtelt hat, was die Struktur noch weiter verkompliziert, nur um blindlings dem Code-Wiederverwendungsprinzip  zu folgen, das hier mit dem Modularitätsprinzip  in Konflikt steht, das ein fähiger Entwickler mit Vererbung  gelöst hätte, denn auch wenn es in C nicht einfach ist, ist es durchaus möglich (tatsächlich verwendet Darktable dieses Prinzip in Code von 2009-2010).

Kosmetik übertrumpft Stabilität

Darktable 4.2 führt die Stilevorschau im Darkroom ein. Das wäre großartig, wenn Stile nicht tief gebrochen wären, wenn sie mit nicht standardmäßiger Pipelinesortierung und mehreren Modulinstanzen verwendet werden. Das Problem ist, dass eine saubere und langfristige Lösung die Theorie gerichteter Graphen  beinhaltet, und hier verlieren wir unsere geliebten Copy&Paste-Code-Pisser.

Im gleichen Geist haben wir große Inkonsistenzen beim Kopieren und Einfügen von Verlauf im Überschreibungsmodus, wenn auch Benutzerstandardsvoreinstellungen verwendet werden (insbesondere im Weißabgleichsmodul). Aber es macht viel mehr Spaß, die Oberfläche zu verunstalten, also wird es dort noch lange bleiben.

Darktable 3.6 und 3.8 führten viele Varianten des Histogramms ein: Vektorskop, vertikale Wellenform, erweiterte und exotische Farbräume. Außer, dass wenn man darktable -d perf im Terminal startet und den Darkroom öffnet, man eine Menge sieht

123.748084 [histogram] brauchte 0.003 Sek. (0.000 CPU) Scope-Zeichnung
223.773753 [histogram] brauchte 0.005 Sek. (0.004 CPU) Scope-Zeichnung
323.783284 [histogram] brauchte 0.001 Sek. (0.000 CPU) Scope-Zeichnung

jedes Mal, wenn man den Mauszeiger im Fenster bewegt (und nicht einmal über das Histogramm). Es ist das Histogramm, das bei jeder Interaktion zwischen Mauszeiger und Fenster neu gezeichnet wird. Das gleiche Problem betrifft viele benutzerdefinierte grafische Widgets  und seine Ursache ist unidentifiziert. Beachten Sie, dass es Ansel nicht betrifft, so dass die Ursache irgendwo in den 23.000 Zeilen Code verborgen sein sollte, die ich entfernt habe.

Zweimal versuchte ich, das Chaos, das aus diesem Feature wurde  zu überarbeiten, aber jedes Mal wurde ein neues, dringenderes Feature vorangetrieben, das meine Arbeit ungültig machte. Ich habe einfach aufgegeben.

Der verrottende Zustand des Histogramms ist so, dass ein vollständiger Neuschreiben weniger Zeit benötigen würde als eine Überarbeitung, zumal das Histogramm viel zu spät in der Pipeline abgetastet wird, im Bildschirmfarbraum, was die Definition eines Histogramm-Farbraums null macht, da der Farbraum im Bildschirmfarbraum unabhängig davon beschnitten wird. Aber raten Sie mal… Darktable 4.4 wird noch mehr Optionen haben, mit der Fähigkeit, Farbharmonien zu definieren (grundlegend für Geeks, die nach Zahlen malen und Histogramme bearbeiten).

Es bleibt, dass, jedes Mal, wenn man den Mauszeiger bewegt, eine große Anzahl unnötiger Berechnungen ohne Grund gestartet wird. Wie schlimm ist es? Ich hatte die Idee, den CPU-Verbrauch meines Systems zu messen, wenn es im Leerlauf ist, mit dem Linux-Werkzeug powertop. Das Protokoll ist ziemlich einfach: ein Laptop (Intel Xeon Mobile CPU 6. Generation), betrieben mit Akku im Energiesparmodus, Hintergrundbeleuchtung auf Minimum eingestellt, die App öffnen und nichts für 4 Minuten berühren, dann während der 5. Minute den globalen CPU-Verbrauch des Systems überwachen, wie von powertop berichtet :

  • Basissystem (keine App geöffnet, außer powertop läuft in einem Terminal): 3,0 bis 3,5 % CPU
  • Ansel:
    • geöffnet auf der Leuchtplatte: 2,9 bis 3,4 % CPU,
    • geöffnet im Darkroom: 3,8 bis 4,5 % (bevor die Modulgruppen auf Darktable 3.2 zurückgesetzt wurden),
    • geöffnet im Darkroom: 3,0 bis 3,5 % (nachdem die Modulgruppen zurückgesetzt wurden),
  • Darktable:
    • geöffnet auf der Leuchtplatte: 6,6 bis 7,1 % CPU,
    • geöffnet im Darkroom: 30,9 bis 44,9 % CPU _ (nein, das ist kein Kommafehler)_,

Ich verstehe nicht, was Darktable berechnet, wenn man es offen lässt, ohne den Computer zu berühren, weil es nichts zu berechnen gibt. Darktable in der Leuchtplatte konsumiert allein so viel wie das gesamte System (Fedora 37 + KDE-Desktop + Passwortmanager und Nextcloud-Client, die im Hintergrund laufen), und es verbraucht 10-mal so viel wie das gesamte System, wenn es im Darkroom geöffnet ist.

All dies weist auf sehr fehlerhaften grafischen Schnittstellencode hin. In Ansel habe ich einen Großteil des schmutzigen Codes entfernt, ohne etwas anderes zu optimieren, und diese Zahlen bestätigen nur meine Wahl: Schmutziger Code verbirgt Probleme, die durch Lesen nicht erkannt werden können, und wir können auf diesem Weg einfach nicht weitermachen.

Anscheinend bin ich der einzige, der es für unakzeptabel hält, der Pixelleitung ein Drittel bis die Hälfte der CPU-Leistung zu berauben, um eine dumme Schnittstelle zu malen. Wie auch immer Sie es formulieren, es gibt keinen validen Grund dafür, dass eine Software, die offen bleibt, ohne daran zu rühren, den Computer in einen Toaster verwandelt, besonders seitdem wir kein russisches Gas mehr kaufen.

Wir arbeiten gegen uns selbst

Wir sind Fotografen. Die Tatsache, dass wir einen Computer brauchen, um Fotografie zu betreiben, ist eine Neuheit (20 Jahre alt), die mit der digitalen Bildgebungstechnologie verbunden ist, die aus diversen Gründen (guten und schlechten) eine 160 Jahre alte Technologie ersetzt hat, die bekannt und beherrscht ist. Im Prozess ist die Tatsache, dass wir einen Computer und eine Software brauchen, um Bilder zu erzeugen, purer und einfacher Overhead . Menschen, die keine Computer verstehen, zu zwingen, sie zu nutzen, um Aufgaben auszuführen, die sie zuvor manuell perfekt bewältigen konnten, ist auch eine Form der Unterdrückung, und dies als technischen Fortschritt zu verbergen, ist eine Form psychologischer Gewalt.

Software erfordert Entwicklung, Wartung, Dokumentation und Projektmanagement. Das sind mehrere Schichten von Overhead auf den vorherigen drauf. Doch die Tatsache, dass die Arbeitskraft in Open-Source-Projekten keine Entschädigung verlangt, sollte nicht den Fakt behindern, dass die auf Software, seine Nutzung, seine Entwicklung, seine Wartung verbrachte (verlorene?) Zeit an sich ein nicht rückgängig zu machender Kostenfaktor ist.

Die wenigen obigen Beispiele geben einen Überblick über die Komplexität des Quellcodes, aber auch über seine Verschlechterung im Laufe der Zeit in Bezug auf die Qualität, weil einfache und robuste Funktionen durch Spaghetti-Code  ersetzt werden, verwirrend und heimlich fehlerhaft. Hinter diesem Problem der Lesbarkeit liegt das eigentliche Problem, dass die mittelfristige Wartbarkeit erschwert wird, was dem Projekt mit der Genehmigung des Betreuers eine düstere Zukunft verspricht.

Seit 4 Jahren arbeite ich Vollzeit auf Darktable, 2022 ist das erste Jahr, in dem ich mich praktisch unfähig finde, die Ursache der meisten Schnittstellen-Bugs zu identifizieren, denn die Arbeitslogik ist sehr obskur geworden und der Code unverständlich. Die Zahl der behobenen Bugs ist ebenfalls in konstanter Abnahme, sowohl in absoluten Zahlen als auch im Verhältnis der gemergten Pull-Requests, während das Volumen des Code-Traffics ungefähr konstant bleibt (Anmerkung 1: Die folgenden Zeilenanzahlen umfassen nur C/C++/OpenCL und generative XML-Dateien und schließen Kommentare aus 2) (Anmerkung 2: Die Anzahl der geöffneten Probleme wird für die Lebensdauer der vorherigen Version gezählt) :

3.0 (Dezember 2019, ein Jahr nach 2.6)
  • 1049 Probleme geöffnet , 66 Probleme geschlossen / 553 Pull-Requests gemergt (12 %),
  • 398 Dateien geändert, 66 k Einfügungen, 22 k Löschungen, (netto: +44 k Zeilen),
3.2 (August 2020)
  • 1028 Probleme geöffnet , 92 Probleme geschlossen / 790 Pull-Requests gemergt (12 %),
  • 586 Dateien geändert, 54 k Einfügungen, 43 k Löschungen (netto: +2 k Zeilen),
3.4 (Dezember 2020)
  • 981 Probleme geöffnet , 116 Probleme geschlossen / 700 Pull-Requests gemergt (17 %),
  • 339 Dateien geändert, 46 k Einfügungen, 23 k Löschungen (netto: +23 k Zeilen),
3.6 (Juni 2021)
  • 759 Probleme geöffnet , 290 Probleme geschlossen / 954 Pull-Requests gemergt (30 %),
  • 433 Dateien geändert, 53 k Einfügungen, 28 k Löschungen (netto: +25 k Zeilen),
3.8 (Dezember 2021)
  • 789 Probleme geöffnet , 265 Probleme geschlossen / 571 Pull-Requests gemergt (46 %),
  • 438 Dateien geändert, 41 k Einfügungen, 21 k Löschungen (netto: +20 k Zeilen),
4.0 (Juni 2022)
  • 632 Probleme geöffnet , 123 Probleme geschlossen / 586 Pull-Requests zusammengeführt (21 %),
  • 359 Dateien geändert, 30 k Einfügungen, 15 k Löschungen (netto : +15 k Zeilen),
4.2 (Dezember 2022)
  • 595 Probleme geöffnet , 60 Probleme geschlossen / 409 Pull-Requests zusammengeführt (15 %),
  • 336 Dateien geändert, 14 k Einfügungen, 25 k Löschungen (netto : -11 k Zeilen),
  • (Löschungen sind vor allem durch die Entfernung des SSE2-Pfades im Pixel-Code bedingt, was die Leistung typischer Intel i5/i7-CPUs zugunsten von AMD Threadripper-CPUs beeinträchtigt),
4.4 (Juni 2023)
  • 500 Probleme geöffnet , 97 Probleme geschlossen / 813 Pull-Requests zusammengeführt (12 %),
  • 479 Dateien geändert, 57 k Einfügungen, 41 k Löschungen (netto : +16 k Zeilen),

Um den Vergleich zu erleichtern, lassen Sie uns sie auf ein Jahr hochrechnen :

  • 2019: 1049 neue Probleme, 66 geschlossen, 88k Änderungen, +44k Zeilen,
  • 2020: 2009 neue Probleme, 208 geschlossen, 166k Änderungen, +25k Zeilen,
  • 2021: 1548 neue Probleme, 555 geschlossen, 143k Änderungen, +45k Zeilen,
  • 2022: 1227 neue Probleme, 183 geschlossen, 84k Änderungen, +4k Zeilen.

Es scheint, ich bin nicht der Einzige, der feststellt, dass die Bugs von 2022 viel schwieriger zu bewältigen sind, da deutlich weniger von ihnen im Vergleich zu 2021 behoben wurden, und auch 2023 zeigt bisher denselben Trend. Das Verhältnis von Pull-Requests (tatsächlich erledigte Arbeit) zu geschlossenen Problemen (tatsächlich gelöste Probleme) ist einfach lächerlich.

Zwischen Darktable 3.0 und 4.0 wuchs der GUI-Code um 53 %, von 49k auf 75k Zeilen3 (Kommentare und Leerzeilen ausgenommen) und erreichte 79k Zeilen in 4.4. Abgesehen von der schlechten Qualität bin ich mir nicht sicher, ob dies die Benutzbarkeit der Software um 53 % verbessert hat. Tatsächlich bin ich ziemlich überzeugt vom Gegenteil. In Ansel habe ich den GUI-Code bislang auf 53k Zeilen reduziert, während ich nur wenig Funktionalität entfernte.

Das alles ist einfach zu viel und zu schnell für einen Haufen Hobbyentwickler, die abends und am Wochenende ohne Struktur und Planung arbeiten. Das Darktable-Team arbeitet gegen sich selbst, indem es sich zu viel aufhalst, zu viele verschiedene Optionen unterstützt, Code produziert, dessen Ergebnis von zu vielen Umgebungsvariablen abhängt, und in zu vielen verschiedenen Wegen interagieren kann. All das, um Designentscheidungen zu vermeiden, die einige beleidigen könnten, indem sie Funktionen und verfügbare Optionen einschränken. Auf der Seite der Endbenutzer führt dies zu kontextabhängigen Bugs, die auf anderen Systemen unmöglich zu reproduzieren sind, und daher überhaupt nicht behoben werden können.

Es ist einfach: Die geleistete Arbeit kostet immer mehr Arbeit und die Wartung ist nicht gewährleistet, wie der Rückgang der geschlossenen Probleme zeigt, weil es einfach zu viel ist. In einem Unternehmen ist dies der Zeitpunkt, an dem man die Blutung stoppen muss, bevor man die Tresore geleert hat. Aber ein Team von Amateuren, das nicht verpflichtet ist, ein Ergebnis zu liefern, kann eine unendliche Menge an Verlusten verkraften. Nur die Arbeit, die die Arbeit erzeugt, wird im Laufe der Zeit mühsamer, frustrierender und schwieriger, und Endbenutzer werden von einer Bande selbstgefälliger Idioten als Geiseln genommen und werden es durch GUI-Komplexität, unnötige CPU-Auslastung und die Notwendigkeit, mindestens einmal im Jahr zu lernen, wie man grundlegende Aufgaben mit der Software bewältigt, bezahlen.

Eigentlich erwarte ich, dass das derzeitige Massenzerstörungsteam bequem weniger und weniger Freizeit finden wird, um zum Projekt beizutragen, da sie erkennen, dass sie sich in einer Sackgasse mit einem Sattelschlepper gefangen haben und ihren Mist den nächsten überlassen. Aber je früher sie aufgeben, desto weniger Schaden werden sie anrichten.

Der Ausschweif an Optionen und Vorlieben, der die Darktable-Strategie ist, um (nicht) Designunterschiede zu managen, schafft super kontextabhängige Anwendungsfälle, bei denen kein Benutzer dieselben Optionen aktiviert hat und bei dem es unmöglich ist, Bugs in einer anderen Umgebung zu reproduzieren. Und zu verlangen, dass Benutzer die darktablerc-Konfigurationsdatei an Bug-Berichte anhängen, würde auch nicht helfen, da diese Datei derzeit 1287 praktisch unlesbare Zeilen hat.

Merkwürdige und schwer reproduzierbare Bugs häufen sich, sogar auf System 76 -Computern, die speziell für Linux entwickelt wurden, wo wir keine Treiberprobleme vorschieben können. Viele inkonsistente und zufällige Bugs, die ich beim Geben von Bearbeitungslektionen erlebt habe, sind nicht auf dem Bugtracker gelistet, und es ist ziemlich klar, dass sie irgendwo in den Feinheiten der if- und switch-case-Ausschweifungen liegen, die seit 2020 in alarmierendem Tempo hinzugefügt wurden.

Diese merkwürdigen und kontextabhängigen Bugs zu beheben, kann nur durch Vereinfachung des Kontrollflusses des Programms und daher durch Begrenzung der Anzahl von Benutzerparametern erfolgen. Aber das Rudel von Geeks, das auf dem Projekt herumschlägt, wird nichts davon wissen wollen und, schlimmer noch, die Bug-„Fixes“ fügen im Allgemeinen nur noch mehr Zeilen hinzu, um sich einzeln mit pathologischen Fällen zu befassen.

Tatsächlich leidet Darktable unter mehreren Problemen:

  1. Ein harter Kern von eher mittelmäßigen Entwicklern, die viel Freizeit haben, um zufällige Dinge zu tun, getrieben von den besten Absichten der Welt, aber unbewusst der Schäden, die sie verursachen, (mittelmäßige Menschen sind immer die verfügbarsten)
  2. Die Nachsicht des Maintainers, der schmutzigen Code durchgehen lässt, um nett zu sein,
  3. Ein kritischer Mangel an Fähigkeiten in reiner Mathematik, Algorithmik, Signalverarbeitung, Farbwissenschaft und allgemein in abstraktem Denken, die erforderlich sind, um über Pixelverarbeitungscode hinaus Funktionen zu vereinfachen und zu faktorisieren,
  4. Eine verachtenswerte Gewohnheit, durch Kopieren und Einfügen von Code zu „entwickeln“, der anderswo im Projekt oder in anderen FLOSS-Projekten gefunden wurde, die eine andere Pipeline-Architektur verwendeten, aber ohne diese entsprechend anzupassen (Anpassung setzt Verständnis voraus, und das ist zu viel verlangt…),
  5. Eine faire und offene Ablehnung, Funktionen zu beschneiden, um Platz für neue zu schaffen und ein gewisses Gleichgewicht zu bewahren,
  6. Ein Stichprobenverzerrung, bei dem die einzigen Benutzer, die mit der Entwicklung über Github interagieren, Programmierer und Englischsprachige sind. Fakt ist, das allgemeine Publikum versteht nicht, was ein Codeforge ist, und es ist schwierig, Nicht-Programmierer zu ermutigen, ein Github-Konto zu eröffnen, um Bugs zu melden. Wir sprechen von einer Nutzerstichprobe, die aus mehr als 44 % von Programmierern besteht](https://eng.aurelienpierre.com/2023/01/who-are-the-dt-are-the-darktable-users/#Conclusion-of-this-part ) und von mehr als 35% von Universitätsabsolventen (sie sind jeweils 6 % und 15 % in der allgemeinen Bevölkerung),
  7. Ein Entwicklung im Eilmarsch, ohne Planung oder Dialog, bei dem jeder Github-Benutzer Diskussionen mit einer ungebildeten Meinung zur aktuellen Arbeit verschmutzen kann. In der Tat scheint die Bildverarbeitung einfach und harmlos, so sehr, dass sich jede Person, die in der Lage ist, einen Logarithmus zu berechnen, kompetent fühlt. Denn die grundsätzlichen Fehler in der Darktable-Farbmetriekette erinnern uns täglich an das Gegenteil.
  8. Ein Mangel an projektweiten Prioritäten hinsichtlich der zu refaktorisierenden, stabilisierenden oder erweiternden Funktionen: Alle Projekte werden gleichzeitig geöffnet, auch wenn sie miteinander im Widerspruch stehen.
  9. Eine Menge an Aktivität (E-Mails und Benachrichtigungen), die unmöglich zu verfolgen ist, zwischen Kommentaren, themenfremden Diskussionen, Bugs, die es nicht sind, Änderungsvorschlägen für den Code, tatsächlichen Codeänderungen, die sich möglicherweise auf Ihre eigene Arbeit in Arbeit auswirken, was bedeutet, dass man überall gleichzeitig sein muss; es gibt viel zu lesen, wenig zu behalten; Diskussionen um ihrer selbst willen behindern die Produktivität und der Mangel an Arbeitsstruktur ist die Hauptursache dafür,
  10. Nicht blockierende Bugs, die hastig versteckt werden, bevor wir fertig sind, sie zu verstehen, anstatt sie wirklich zu beheben und an ihrer Wurzel anzugehen, was langfristig Probleme verschiebt oder sogar verschlimmert, ohne Spuren in irgendeiner Form von Dokumentation zu hinterlassen,
  11. Ein Veröffentlichungskalender, den wir um jeden Preis einhalten, auch wenn er nicht realistisch ist, obwohl niemand ihn uns aufzwingt,
  12. Codeänderungen, die jederzeit überall stattfinden können, was bedeutet, dass wir auf Treibsand arbeiten und dass wir so schnell und so schlecht wie die anderen arbeiten müssen, um nicht hinter dem Volumen und der Frequenz der Änderungen (Commits) zurückzubleiben,
  13. Neue Funktionen, die die Benutzerfreundlichkeit verschlechtern und die Verwendung erschweren, ohne ein bestimmtes Problem zu lösen und als Freizeitprojekte für Entwickler ohne Design-/Ingenieurstraining dienen.

Aber das ärgerlichste ist diese Hartnäckigkeit, einfache und funktionale Funktionen durch Schrecken der Über-Ingenieurwesen zu ersetzen, die dazu bestimmt sind, abweichende und marginale Verwendungen zu erfreuen, während sie jedem das Leben mit endlosen Listen gedankenloser Optionen erschweren. Der beste Ort, um einen Baum zu verstecken, ist inmitten des Waldes, und viele haben es immer noch nicht gelernt.

Verwechslung von Bewegung mit Aktivität

Jeder Wähler kritisiert gerne die Abweichung, die in der Politik besteht darin, situative Gesetze, schlecht geschrieben, zu erlassen, um die öffentliche Meinung nach einem besonderen Ereignis zu beschwichtigen und zu zeigen, dass wir handeln, während ähnliche Gesetze bereits existieren und nicht oder nicht vollständig angewendet werden, weil es an Mitteln mangelt. Wir nennen das Agitation: Das sieht aus wie Action, hört sich nach Action an, hat die Kosten der Action, führt aber zu nichts Greifbarem oder Praktischem.

Das Team von Amateuren ohne Projektmanagement, die sich über Darktable aufregen, produziert nur zukünftige Probleme. In der Vergangenheit wurde Darktable einmal im Jahr mit etwa 1500 bis 2000 Commits  vor der vorherigen Version veröffentlicht. Das ist jetzt das Änderungsvolumen, das in 6 Monaten erreicht wird. Ein „Arbeits“volumen, das so schnell wächst, ohne zu Teamarbeit zu führen, einschließlich klarer Prioritäten für jede Veröffentlichung und Aufgabenverteilung, und ohne Softwarequalitätskontrolle basierend auf objektiven Metriken (Anzahl der Schritte oder verstrichene Zeit zur Erreichung einer bestimmten Aufgabe), es bedeutet nur, dass Personen sich gegenseitig im Weg stehen, während sie ihre eigene Agenda durchziehen, ohne sich um andere, das Projekt oder die Benutzer zu kümmern.

Darktable ist zum Highschool-Computerclub geworden, wo Geeks ihren Spaß haben. Es ist global eine Zusammenfassung aller schlimmsten Geschichten von IT-Unternehmen, mit dem Unterschied, dass das Projekt keinen Cent verdient, was es dringend macht, sich zu fragen, warum wir uns das antun: Es gibt keine Gewinne zu teilen, aber jeder teilt die Kosten. Es ist ein chaotisches und giftiges Arbeitsumfeld, das nur zu Burn-Outs führen würde, wenn die Teilzeitamateure verpflichtet wären, Ergebnisse zu liefern und Vollzeit arbeiten müssten. Als einziger Vollzeit-Typ auf diesem Projekt können Sie sich den Stress und den Energieverlust vorstellen, um mit der permanenten Kakophonie auf dem Laufenden zu bleiben, nur um sicherzustellen, dass ich nicht die 2 %, die für mich wirklich relevant sind, im Lärm der unregulierten Diskussionen verpasse.

Auf der Benutzerseite loben wir die Euphorie des Darktable-Projekts (ja, es gibt Bewegung), ohne zu realisieren, dass der Commit-Runaway keine Aktivität ist, sondern Agitation, und insbesondere technisches Schulden, die zu zahlen wir-nicht-wissen-wann von wir-nicht-wissen-wer. Die Schönheit eines Projekts, bei dem niemand Verantwortung für seinen Mist übernehmen muss, weil niemand für nichts verantwortlich ist: Es steht in der GNU/GPL-Lizenz. Wir können daher die Arbeit der Vorgänger mit totaler Straflosigkeit versauen.

Wir haben den Anfang einer Qualitätskontrolle durch die Integrationstests, die den Wahrnehmungsfehler über Referenzbildverarbeitungen messen, aber sie lösen keine Reaktion aus, wenn wir ein durchschnittliches Fehlerdelta E von 1,3 (klein) sehen, während die Natur der Änderung ein strikt null Delta E haben sollte. Wenn der einzige Test besteht (weil wir ein einzelnes SDR-Bild über eine Studioaufnahme testen), werden keine Fragen gestellt, ob die Theorie stimmig und robust ist. Wir haben den Test in eine Entlastung verwandelt, solange die Metrik unter dem Validierungsschwellenwert bleibt…

Mit der Veröffentlichung von Darktable 4.0 — Geektable — sah ich auf Youtube, dass Menschen anfingen zu beklagen, dass diese Veröffentlichung nicht sehr aufregend war. Nach Jahren des Doping von Menschen mit Superlativ-Veröffentlichungen, die vollgepackt mit neuen Funktionen sind, die wir nicht Zeit haben, richtig zu testen (6-8 Typen, die jeden 6 Monate 38-50k Zeilen pinkeln, während sie nur abends und Wochenenden arbeiten, träumen Sie immer noch?), haben wir sie süchtig nach dem überladenen Weihnachtsbaum gemacht, um sicherzustellen, dass der Tag, an dem wir anfangen, verantwortungsbewusst zu sein und stabile Versionen zu veröffentlichen (also langweilig), das gegen uns gehalten wird.

Der Grund für dieses frenetische Veröffentlichungstempo ist, dass Pull-Requests, die älter als 3 Monate sind, systematisch in Konflikt mit dem Master-Zweig stehen, da dieser jeden Monat für „generalisierte Tests“ erschüttert wird. Aber die seltenen Benutzer, die den Master-Zweig bauen, haben keine Ahnung, was sie im Besonderen testen müssen, es sei denn, sie sezieren die Git-Commit-Historie, was die Beherrschung beider der C-Sprache und der Auswirkungen der Änderungen in der Praxis auf die Software voraussetzt.

Um lang lebende Zweige zu begrenzen, die unvermeidlich in Konflikt mit dem Master enden werden, fanden wir eine brillante Lösung: Wir veröffentlichen 2 Versionen jedes Jahr und machen die Entwicklung im Eilmarsch basierend auf unvollständigem und kaum getesteten Code zu einer Lebensweise, ohne jemals zu realisieren, dass das Kernproblem zuerst der Mangel an Planung, sondern auch, dass Mitwirkende beginnen zu codieren, bevor sie fertig sind, das zu lösende Problem zu definieren (wenn es ein wirkliches Problem zu lösen gibt, nicht nur ein Typ, der aufwachte wie „es wäre cool, wenn …“), parallel an beiden Teilen ohne Kommunikation arbeitend.

Der Staub hat keine Zeit sich zu setzen, dass wir den Code erneut erschüttern, ohne Phasen der Stabilisierung zu erzwingen, in denen wir nur Bugs bereinigen (und ich spreche nicht von dem Monat des Feature-Freeze vor der Veröffentlichung, sondern von Veröffentlichungen, die sich nur dem Code-Cleaning widmen). Der Bugtracker explodiert in den 3 Wochen nach jeder Veröffentlichung, weil ein erheblicher Teil der Nutzer nur die vorgefertigten Pakete verwendet, die mit Weihnachten und Sommerferien zusammenfallen, in der ich persönlich bessere Dinge zu tun habe, nach dem ohnehin schon stressigen Sprint, der der Monat vor der Veröffentlichung ist.

Seit 2021, wenn ich mein Git-Repository mit den neuesten Änderungen des Darktable-Masters aktualisiere, frage ich mich immer, was sie diesmal gebrochen haben. Wir brechen schneller, als wir reparieren, und die meiste Zeit brechen die Fixes etwas anderes. Die einzigen Benutzer, die Darktable stabil finden, sind eigentlich diejenigen, die es sehr einfach verwenden, was ironisch ist für eine App, deren Verkaufsargument es ist, fortschrittlich zu sein.

Und dann wird mir gesagt, dass es kostenlose Arbeit ist, als ob das eine Entschuldigung wäre. Aber es ist eigentlich ein erschwerender Umstand: Warum setzen wir uns solchen Arbeitsbedingungen aus, wenn es nicht einmal rentabel ist??? Zusätzlich zu der Tatsache, dass diese freie Arbeit mir jedes Jahr nach der Veröffentlichung einen Burnout beschert, kostet sie immer mehr in der Wartung, und die Wartung ist immer verabscheuungswürdiger zu tun. Es ist keine kostenlose Arbeit, es ist schlimmer: es ist Arbeit, die kostet, ohne zu bezahlen.

Wie auch immer, die Arbeit wird von Menschen geleistet, die begrenzte Zeit und Energie haben. Wenn die Ressource begrenzt ist, schneidet den Unsinn: Wir sind in denselben Rentabilitätszwängen wie ein Unternehmen, abzüglich der Sozialabgaben, außer dass unser Tauschgeld Zeit ist und nicht rückerstattbar ist. Ohne Prioritätenmanagement werden wir von technischer Schuld überrannt, die wir nicht die Ressourcen haben, um zu warten.

Worauf warten wir, um glücklich zu sein?

Die Tatsache, dass Darktable ein Dampfhammer im Fluchtmodus und ohne Fahrer ist, der eine zunehmende Menge an Arbeit erzeugt, ist ein schlechtes Zeichen für ein 15 Jahre altes Projekt. Normalerweise verlangsamt sich ein reifes Projekt, weil es vollständig genug ist, um benutzbar zu sein, und weil die Menschen, die daran arbeiten, ihre Kreuzfahrtgeschwindigkeit und effizienten Arbeitsmethoden gefunden haben.

Ich arbeite seit 2018 Vollzeit daran, für ein monatliches Einkommen zwischen 800 und 900 €, und es ist eine Untertreibung zu sagen, dass es schlecht bezahlt ist, die katastrophalen Folgen von unorganisierten Amateuren zu ertragen, die versuchen, ihren Spaß auf Kosten der Qualität des Endprodukts und seiner Benutzbarkeit durch Computer-Muggel zu haben. Außerdem sind Muggel auch aus Prinzip verachtet.

Wenn ich einen Monat unter einem Felsen krieche, um einen perceptuellen Farbraum zu entwickeln, komme ich heraus, um das neue labyrinthinische System zu entdecken, das das View-Model-Controller-Paradigma etwas mehr verletzt, und mir wird gesagt, dass ich zu spät komme, um es abzulehnen. Wenn ich im August 3 Wochen Urlaub mache, entdecke ich, dass der Maintainer (noch einmal) meine Überprüfung auf eine mathematische Änderung am erwähnten Farbraum umgangen hat, die erfordert, ruhig zu sitzen und nachzudenken, alles, weil … wir mussten uns beeilen? Für welchen Notfall genau?

Ich habe wahrscheinlich die Benachrichtigung irgendwo in der Mitte der 2234 E-Mails, die Github mir zwischen Januar und August 2022 geschickt hat (im Jahr 2021 waren es 4044), ohne die Benutzer zu erwähnen, die mich überall pingten, auf Youtube, Reddit, Matrix, Github, Telegram, direkt per E-Mail und zuvor auf pixls.us (693 E-Mails im Jahr 2022, 948 im Jahr 2021). All dies für Leute, die völlig aus dem Takt sind, die nicht realisieren, dass ich das die ganze Woche mache, dass Fotografie vielleicht ihr Hobby ist, aber mein Job ist, und dass ich es einfach gerne hätte, wenn Leute mir am Wochenende und an den Feiertagen vom Hals bleiben. Sie können sich vorstellen, dass die nervigsten nicht diejenigen sind, die meine Arbeit finanzieren. Menschen respektieren Arbeit nur, wenn sie dafür einen hohen Preis gezahlt haben.

Ich habe keine Zeit, Forscher, Designer und dazu noch Sekretär zu sein, während ich technisches Babysitten für ein Team von Gaston Lagaffe mache, die sowohl geschult als auch überwacht werden müssen, weil sie nicht können:

  1. Eine Entwicklungsplanung machen mit einer Liste von Prioritäten neuer Features, an denen gearbeitet werden soll,
  2. Ein Lastenheft von Bedürfnissen und Problemen bereitstellen, mit einem echten Anwendungsfall, bevor sie sich in ihren Code-Editor stürzen und was auch immer tun, um ein neues Feature zu entwickeln, das nach einem Problem sucht, das gelöst werden sollte.
  3. Die Wartungskosten der Änderung evaluieren, bevor sie die bionische Speckpumpe mit umgekehrter Osmose erfinden, die nur an geraden Tagen funktioniert, wenn Jupyter mit dem Saturn außer Phase ist,
  4. die Ausgaben begrenzen und die Verluste reduzieren, wenn sie sich in Design-Sackgassen fangen, die Regressionen einführen, die schlimmer sind, als die hypothetischen erwarteten Vorteile,
  5. sich zusammenreißen und eine Veröffentlichung verschieben, wenn der Code offensichtlich nicht bereit ist (oder ich habe nichts verstanden und die Aktionäre werden unsere Köpfe verlangen, wenn wir verspätet veröffentlichen???).

Management (oder Teammanagement) ist ein Overhead, der eine gewisse Arbeit kostet, aber das Darktable-Team hat eine Größenordnung erreicht, in der das Fehlen von Management tatsächlich mehr Arbeit kostet, insbesondere wenn keiner der Projektgründer mehr im Team ist, und die ursprünglichen Design-Blaupausen müssen jedes Mal mit grep im Code rückentwickelt werden, wenn etwas geändert werden muss. Das war tragbar mit einem reduzierten Team, in dem jeder sich kannte, aber Darktable ist während der Covid-Lockdowns zu einem Projekt mit hohem Verkehrsaufkommen geworden, und diese Arbeitsweise ist nicht tragbar mit dem aktuellen Personal.

Schaut euch einfach den Code an! Vergleicht den Branch darktable-2.6.x mit darktable-4.2.x, Datei für Datei, und genießt!

All I have heard so far are canned sentences like “it’s like many other opensource projects” and “there is nothing we can do about it”. People are afraid by the amount of work that a fork is (I got emails trying to convince me it was dividing productivity), without realizing the amount of resources currently wasted by the Darktable project and the permanent stress of having to base your work on an unstable code base shaken up all the time. So far, Ansel cost me less fatigue and I solved a significant number of problems among which some were reported since 2016 without signs of interest from the bloody “community”.

Außerdem bietet Ansel automatisch erstellte nächtliche Pakete für Linux (.AppImage) und Windows (.exe) an, um echte generalisierte Tests zu ermöglichen, auch durch Menschen, die nicht in der Lage sind, die Software selbst zu kompilieren. Ich habe 2019 danach gefragt , aber offenbar haben Geeks Besseres zu tun, und ich musste selbst 70 Stunden investieren, um das zu ermöglichen. Die Operation ist bereits erfolgreich und hat ermöglicht, in Tagen Windows-Bugs zu beheben, die Wochen gedauert hätten, um in Darktable entdeckt zu werden. (Und Darktable hat 3 Wochen später mein AppImage-Build-Skript ohne angemessene Anerkennung übernommen, aber das ist ein Detail).

Apropos Produktivität, erinnern wir uns daran, dass die Leuchttafel seit 2018 fast vollständig zweimal neu geschrieben wurde (und die letzte Version nicht besser oder schneller ist), und die große Änderung der Sammlungsfilter im April 2022  eine andere ähnliche Änderung (aber nur mit 600 Zeilen statt 6000) überschrieben hat, die im Februar 2022  eingeführt wurde (die Februar-Version ist die, die in Ansel verwendet wird). Wir können das Wort „Produktivität“ nicht ernsthaft verwenden, wenn die Arbeit eines Beitragsgebers die Arbeit eines anderen in einem Monat buchstäblich löscht, nur aus Mangel an Projektmanagement. Es wird als gegenseitiges Treten auf die Füße bezeichnet.

Also, was tun wir, um das Problem zu lösen? In Stille leiden? In Verleugnung leben? Weiterhin Sachen reparieren, die jemand anderes im nächsten Jahr kaputt machen wird, wenn wir nicht hinschauen? Die Muggel weiterhin glauben lassen, auf Foto-Forum-Länge, dass Open Source genauso gut wie proprietär ist, während man als Joker die Tatsache behält, dass es kostenlos ist, sodass man nicht das Recht hat, sich zu beschweren? Ist das nicht ein bisschen zu einfach und unehrlich, diese Doppelsprache?

Möchtest du nicht aufhören, Gewohnheiten als Erfahrung durchgehen zu lassen und Fatalismus mit Weisheit zu verwechseln, sondern eher das Problem an der Wurzel angehen? Denkst du nicht, dass du und ich besser als Software verdient haben, die von Amateuren entworfen wurde, deren einziges Talent es ist, Freizeit zu haben und sich leisten können, kostenlos zu arbeiten, seit sie ins Management gewechselt haben und die Kinder zur Universität gegangen sind?

Oder ich habe mich von Anfang an geirrt, und Open Source geht darum, überkomplexe Werkzeuge an Geeks zu geben, die sie nicht wirklich brauchen, während wir versuchen, den Rest der Welt davon zu überzeugen, dass Open Source nicht ein Hyper-Nische für Entwickler ist?

Vier Jahre Arbeit, um hierher zu kommen

Nach 4 Jahren, in denen ich Vollzeit an Darktable gearbeitet habe für 70% des Mindestlohns, und 2 Jahren, in denen ich die chronische Unzufriedenheit ertrage, meinen Namen zu beschmutzen, indem ich zu Mist beitrage, habe ich Ansel geforkt und werde nicht zurückkehren.

In 4 Jahren habe ich dieser Software etwas gebracht, das ihr schmerzlich fehlte: einen einheitlichen Workflow, basierend auf einem Satz von Modulen, die entworfen wurden, um zusammenzuarbeiten, aber jeweils auf einen bestimmten Aspekt einwirken, wo Darktable-Module eher eine Sammlung von unterschiedlichen Plugins waren. Wir sprechen über:

  • Filmic,
  • Ton-Equalizer,
  • das physikalisch genaue Weichzeichnungsmodul,
  • beide Versionen des Farbgleichgewichts,
  • Farbabstimmung, einschließlich der GUI, um mit Farbcheckern direkt im Dunkelraum zu profilieren und die Weißabgleichung nach CIE-Standards,
  • das Negadoctor-Modul, um Filmnegative basierend auf Kodak Cineon umzuwandeln,
  • das Diffuse- und Schärfemodul für die Hinzufügung und Entfernung von Unschärfe, basierend auf thermischer Diffusion,
  • die gerichtete laplacianische Rekonstruktion von Highlights.

Ich habe auch grundlegendere Werkzeuge entwickelt, die Grundlagen für die vorhergehenden Module liefern:

  • ein Anisotropa4.order Differentialgleichungslöser in Wellenheitsraum für Diffusion und Schärfung,
  • eine Anpassung der vorherigen als die geführte Laplace für RGB-Signalrekonstruktion durch Gradientenweiterleitung,
  • ein Wahrnehmungsmodell für Farbempfindlichkeit, das den Helmholtz-Kohlrausch-Effekt in der Sättigungsberechnung berücksichtigt, um den „Fluo“-Effekt zu begrenzen, der typischerweise mit intensiven Sättigungseinstellungen kommt, im Farbgleichgewicht,
  • eine theoretische Hilfe bei der Entwicklung des belichtungsinvarianten geführten Filters (EIGF), im Tone Equalizer,
  • ein linearer Vektorgleichungslöser durch Cholesky-Methode,
  • verschiedene Interpolationsmethoden der Ordnung 2, 3 und radial-basiert.

Im GUI habe ich insbesondere getan:

  • Stilerklärung refaktoriert , indem ich das Styling aus dem C-Code entfernte, um es in das CSS-Stilblatt zuzuordnen, was ermöglicht, mehrere UI-Themen zu haben, einschließlich benutzerdefinierter,
  • den Vorschau-Modus Hinweis-Peaking  und ISO 12 646 Farbmodul  eingeführt,
  • das Farb-Vokabular im globalen Farbwähler eingeführt , das es ermöglicht, die ausgewählte Farbe von ihren chromatischen Koordinaten aus zu benennen und sich an farbenblinde Fotografen richtet.

Nach diesem schrieb ich Dutzende von Dokumentationsseiten in 2 Sprachen, veröffentlichte Artikel und Dutzende von Stunden Video auf YouTube, um zu demonstrieren, wie man Module verwendet, in welchem Kontext und zu welchem Vorteil, einschließlich schneller Bearbeitungen mit nur 3 bis 5 Modulen, um 75 bis 80 % der Bilder zu verarbeiten, egal welches Dynamikbereich. In der Open-Source-Welt, außer vielleicht für Projekte, die durch Stiftungen unterstützt werden (wie Krita und Blender), existiert dieses Niveau an Unterstützung und Dokumentation einfach nicht, und es sind nicht die Entwickler selbst, die sich um diese Arbeit kümmern.

Trotz all dem hatte ich nie mehr als 240 Spender, im Vergleich zu ungefähr 1800 eindeutigen Befragten, die an den Umfragen 2020 und 2022 von Darktable teilgenommen haben, und die angaben, zwischen 500 und 1000 €/an  für Fotografie auszugeben.

Ich werde nicht zuschauen, wie sie die Benutzbarkeit dieser Software zerstören, während ich versuche, mich davon zu überzeugen, dass es Fortschritt ist und wir nichts dagegen tun können. Anstatt des Fortschritts ist es die wahnhafte Vision des Fortschritts von einem Haufen von Fünfzigjährigen Dilettanten. Seit 2 Jahren halte ich geduldig den Mund und versuche nett zu sein, aber angesichts der Verschlechterung der Basisfunktionen, die zur Einhaltung der Launen verrückter Programmierer komplexer geworden sind, hätte ich mich früher verabscheuungswürdig verhalten sollen. Nettsein hat nichts gelöst, weil der Trend nicht nur anhielt, sondern sich beschleunigte, und es wird keine Einsicht geben, bevor der Punkt ohne Wiederkehr erreicht ist. Wir können nicht erwarten, dass diejenigen, die die Probleme geschaffen haben, diejenigen sind, die sie lösen.

Also, wenn ich für eine “Gemeinschaft” arbeiten muss, die hauptsächlich wegen des abofreien Aspekts der Software beteiligt ist und entschieden hat, dass meine Arbeit den Mindestlohn nicht wert ist, werde ich es nach meinen Bedingungen und mit meinen Standards tun.

In Bezug auf Funktionen hat Darktable bereits zu viel und wir müssen reduzieren. Ich benutze es seit 10 Jahren und es war bereits mit schlecht gestalteten Dingen gepackt. Die Herausforderung besteht jetzt darin, die Funktionen clever zu präsentieren und nervige Bugs zu beheben, bevor diese Idioten neue einführen oder sie auf ihre spezielle Weise „reparieren“: indem sie den Staub unter den Teppich kehren. Denken Sie daran, dass die Darktable-Pipeline 15 Jahre alt ist und wir sie nicht mehr optimieren können, da sie schon viel gefoltert wurde, um ein vollständiges Umschreiben zu vermeiden (ein vollständiges Umschreiben bietet jedoch keinen Vorteil, wenn wir Gtk als grafischen Backend behalten müssen, da dies der Haupthindernis für die Leistung ist).

Die von Darktable benötigten Lösungen erfordern, Code und Optionen zu entfernen, nicht immer mehr hinzuzufügen. Robustheit hat seinen Preis. Das Darktable-Team tut genau das Gegenteil, ohne aus seinen Fehlern zu lernen.

Mit Ansel möchte ich eine Möglichkeit, diese Arbeit friedlich abzuschließen, damit Linux-Benutzer ein zuverlässiges, konsistentes und leistungsfähiges Werkzeug für ihre künstlerische Fotografie haben. Bevor ich zu Vkdt  wechsle, weil das aktuelle Design seine Grenzen zeigt.


Translated from English by : ChatGPT. In case of conflict, inconsistency or error, the English version shall prevail.

  1. The fact that bugfixes systematically add more lines of code instead of modifying existing lines is a a concerning smell that the programming logic is bad and induces too many particular cases. Rigorous programmers always try to keep their code as generic as possible to avoid spaghetti code ↩︎

  2.  You don’t need to trust me, the command to reproduce the stats is git diff release-3.4.0..release-3.6.0 --shortstat -w -G'(^[^\*# /])|(^#\w)|(^\s+[^\*#/])' -- '*.c' '*.h' '*.cpp' '*.xml.in' '*.xsl' '*CMakeLists.txt' '*.cl' ↩︎

  3. git checkout release-3.0.0 & cloc $(git ls-files -- 'src/views' 'src/gui' 'src/bauhaus' 'src/dtgtk' 'src/libs') ↩︎