Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Klatsch und Tratsch (https://www.delphipraxis.net/34-klatsch-und-tratsch/)
-   -   Die häufigsten Programmierirrtümer (https://www.delphipraxis.net/149587-die-haeufigsten-programmierirrtuemer.html)

Wolfgang Mix 24. Mär 2010 19:18


Die häufigsten Programmierirrtümer
 
Liebe DPler,

ich würde gerne hier einmal die häufigsten Irrtümer sammeln
und ein Tut bauen.

Ich hoffe auf rege Beteiligung.

Mein Brainstorming vorerst:

- IF-Schleife (2260 Hits im Forum)

- if a/b = 0 (Hinweis auf Link zu Luckie)

- if a= 7 or 13

- if ergebnis = true

...

...


Gruß

Wolfgang

Helmi 24. Mär 2010 19:22

Re: Die häüfigsten Programmierirrtümer
 
Hallo,

wie wärs mit so etwas:

If a = b and c <> d then

Also mehrere Vergleiche ohne Klammern

Wolfgang Mix 24. Mär 2010 19:23

Re: Die häüfigsten Programmierirrtümer
 
gut, mehr :)

Namenloser 24. Mär 2010 19:23

Re: Die häüfigsten Programmierirrtümer
 
Das hier hab ich schon öfter bei blutigen Anfängern gesehn:
Delphi-Quellcode:
if Button1.Click then
...

Wolfgang Mix 24. Mär 2010 19:26

Re: Die häüfigsten Programmierirrtümer
 
danke, "alter Hase" :)

Helmi 24. Mär 2010 19:26

Re: Die häüfigsten Programmierirrtümer
 
Ich hätt noch was:
Delphi-Quellcode:
var
  r: Real;

begin
  { ... }

  If r = 0 then //Float-Wert-Abfrage genau auf Null

end;

Wolfgang Mix 24. Mär 2010 19:27

Re: Die häüfigsten Programmierirrtümer
 
Sh. Post #1

Helmi 24. Mär 2010 19:31

Re: Die häüfigsten Programmierirrtümer
 
Auch wenn es kein Programmierfehler ist,

aber ein häufiger Fehler ist auch ein falsch geschriebener Thread-Titel:

Re: Die häüfigsten Programmierirrtümer

:mrgreen:

alzaimar 24. Mär 2010 19:38

Re: Die häüfigsten Programmierirrtümer
 
Schlecht gewählte und nichtssagende Variablenbezeichner.
Schlecht lesbarer Code.

Der größte Programmiererirrtum: Zu meinen,von anderen keine Ratschläge annehmen zu müssen.

Wolfgang Mix 24. Mär 2010 19:39

Re: Die häufigsten Programmierirrtümer
 
@ Helmi :) Mit 60 ohne Brille ist auch schlecht

Helmi 24. Mär 2010 19:42

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Wolfgang Mix
@ Helmi :) Mit 60 ohne Brille ist auch schlecht

*auf die Bildschirmlupe verweis* :mrgreen:

Hier hätt ich noch einen:
Delphi-Quellcode:
for i := 1 to StringList.Count do
  S := StringList.Strings[i];

Wolfgang Mix 24. Mär 2010 19:44

Re: Die häüfigsten Programmierirrtümer
 
Zitat:

Zitat von alzaimar
Schlecht gewählte und nichtssagende Variablenbezeichner.
Schlecht lesbarer Code.

Der größte Programmiererirrtum: Zu meinen,von anderen keine Ratschläge annehmen zu müssen.

Das versuche ich hier gerade, bist du nachtragend?

Noedel 24. Mär 2010 19:44

Re: Die häufigsten Programmierirrtümer
 
naja, kein Programmierfehler, eher ein Fehler im Umgang mit dem BB-Code:

"hab schon das alles geschafft:

[ganz viel Quelltext, nicht in Delphi-Tags eingefasst, nicht eingerückt]

Wer kann mir helfen?"

----------

Auch kein Programmierfehler, aber ein Mangel an Kenntnis im Umgang mit dem Debugger:

"[ganz viel Quelltext, vielleicht in Delphi-Tags eingefasst, eventuell eingerückt]

Da kommt dann ein Fehler. Wieso?"

Matze 24. Mär 2010 19:51

Re: Die häufigsten Programmierirrtümer
 
Das sind keine "Programmierirrtümer", sondern Programmierfehler!
Da es in "Programmieren allgemein" steht, hier noch ein Fehler, der einen richtig frustrieren kann, da man ihn teils nur schwer findet:

Code:
// Der Code ist für C, C++, C#, ... (nicht für Delphi)
if (a = b) {
    // ...
}

Reinhardtinho 24. Mär 2010 19:55

Re: Die häufigsten Programmierirrtümer
 
Etwas, was ich öfters sehe:


Fehler werden nicht gefunden, da Einrückung nicht korrekt ist.
- begin oder end zuviel/zuwenig
- if-Anweisung ohne begin/end und man wundert sich, dass zuviel ausgeführt wird
- ...


Abbruchbedingungen, die niemals zutreffen können.


GOTO (siehe xkcd).


Was ich persönlich einfach nicht leiden kann (ist ansich ja nicht falsch, aber ich finde es einfach unschön):

Delphi-Quellcode:
if cancelled then
  exit
else
begin
  ...
end;
//Ende der Methode
anstatt

Delphi-Quellcode:
if not cancelled then
begin
  ...
end;
//Ende der Methode

Wolfgang Mix 24. Mär 2010 19:55

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Matze
Das sind keine "Programmierirrtümer", sondern Programmierfehler!
Da es in "Programmieren allgemein" steht, hier noch ein Fehler, der einen richtig frustrieren kann, da man ihn teils nur schwer findet:

Code:
// Der Code ist für C, C++, C#, ... (nicht für Delphi)
if (a = b) {
    // ...
}

Meintest du?
if (a == b) {

Darauf bin ich auch schon öfter 'reingefallen :(

Luckie 24. Mär 2010 19:56

Re: Die häufigsten Programmierirrtümer
 
Delphi-Quellcode:
var
  sl: TStringList;
begin
  sl.Create;
  sl....;

scrat1979 24. Mär 2010 20:00

Re: Die häufigsten Programmierirrtümer
 
Hätte auch noch was:

Delphi-Quellcode:
if y = 2010 Then
 xyz := true
else
 xyz := false;
statt

Delphi-Quellcode:
 xyz := (y = 2010);

Reinhardtinho 24. Mär 2010 20:02

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Matze
Code:
// Der Code ist für C, C++, C#, ... (nicht für Delphi)
if (a = b) {
    // ...
}

Diese Schreibweise der Klammernpaare (gilt auch für begin/end) - also nicht untereinander - halte ich auch für eine Quelle für Programmierirrtümer, gerade für Anfänger.

Luckie 24. Mär 2010 20:03

Re: Die häufigsten Programmierirrtümer
 
Das ist weder ein Irrtum noch ein Fehler. Der Programmierer fand eventuell seine Schreibweise lesbarer.

scrat1979 24. Mär 2010 20:03

Re: Die häufigsten Programmierirrtümer
 
... und noch was

Delphi-Quellcode:
 sl : TStringList;
 [...]
begin

 sl := TStringList.Create(nil);
 [...]

 sl.Free; // wird oft vergessen :)
end;
P.S.: Wie zum Teufe rücke ich denn hier in den Tags ein?!? :evil: Im Antwort-Editor ist es eingerückt :(

Wolfgang Mix 24. Mär 2010 20:08

Re: Die häufigsten Programmierirrtümer
 
@ Michael:
Sehe ich auch so

Reinhardtinho 24. Mär 2010 20:13

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Luckie
Das ist weder ein Irrtum noch ein Fehler. Der Programmierer fand eventuell seine Schreibweise lesbarer.

Ich habe weder das eine noch das andere behauptet.
Ich möchte nur darauf hinweisen, das Anfänger in solch formatiertem Code Fehler schlechter finden. Dabei handelt es sich allerdings nicht um eine pauschale Aussage, sondern ein Hinweis rein aus Erfahrung mit Anfängern.

Helmi 24. Mär 2010 20:13

Re: Die häufigsten Programmierirrtümer
 
was auch ein Irrtum sein kann, wäre das hinzufügen eines Eintrages in eine StringList z. B. mittels "Insert" statt "Add"

BUG 24. Mär 2010 20:21

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Reinhardtinho
GOTO (siehe xkcd).

Ist aber eher kein typischer Anfängerfehler, da man dafür ja die passende Syntax (Label vor dem begin deklarieren) kennen muss.
GOTO habe ich in "Anfängercodes" hier in der DP noch nie gesehen.

Wenn man nicht ständig davor warnen würde, würden es die meisten (Anfänger) nicht mal kennen :mrgreen:
(Mein erstes GOTO hab ich in einer Warnung gesehen.)

Die Muhkuh 24. Mär 2010 20:32

Re: Die häufigsten Programmierirrtümer
 
Ich hätte da zu bieten:

Delphi-Quellcode:
// Damit es auf jeden Fall ausgeführt wird!!!
if 1 = 1 then
begin
  // Code
end;
Auch das Gegenteil hab ich schon oft genug gesehen:

Delphi-Quellcode:
// Darf nicht mehr ausgeführt werden!!!
if 1 = 2 then
begin
  // Code
end;
Toll fand ich auch:

Delphi-Quellcode:
if (Bedingung) then
begin
  Var1 := 'bla';
  Var2 := 'bla';
end
else
begin
  Var1 := 'blubb';
  Var2 := 'blubb';
end;

Var1 := 'bla';
Var2 := 'bla';

Mithrandir 24. Mär 2010 21:13

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Matze
Das sind keine "Programmierirrtümer", sondern Programmierfehler!
Da es in "Programmieren allgemein" steht, hier noch ein Fehler, der einen richtig frustrieren kann, da man ihn teils nur schwer findet:

Code:
// Der Code ist für C, C++, C#, ... (nicht für Delphi)
if (a = b) {
    // ...
}

Mit PHP geht das auch seeeeehr gut.... :wall: :wall:

s.h.a.r.k 24. Mär 2010 21:21

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Daniel G
Mit PHP geht das auch seeeeehr gut.... :wall: :wall:

OHHHHH ja... Und da soll man das erst mal finden...

Zitat:

Zitat von Helmi
was auch ein Irrtum sein kann, wäre das hinzufügen eines Eintrages in eine StringList z. B. mittels "Insert" statt "Add"

Warum? :gruebel: Man kann doch via Insert einen Index angeben. Oder meinst du, dass jeder das Insert für das Add hält?

Zitat:

Zitat von scrat1979
... und noch was

Delphi-Quellcode:
 sl : TStringList;
 [...]
begin

 sl := TStringList.Create(nil);
 [...]

 sl.Free; // wird oft vergessen :)
end;
P.S.: Wie zum Teufe rücke ich denn hier in den Tags ein?!? :evil: Im Antwort-Editor ist es eingerückt :(

Das hier mag ich noch dazu berichtigen, dass man da doch gleich das try-finally hinzufügt.


Delphi-Quellcode:
var
  sl : TStringList;
begin
  sl := TStringList.Create(nil);
  try

  finally
    sl.Free; // oder auch FreeAndNil(sl); welches ich all zu gerne nutze
  end;
end;

sx2008 24. Mär 2010 21:26

Re: Die häufigsten Programmierirrtümer
 
Ein Klassiker: Zugriff auf leeres, dynamisches Array (auch Strings sind dynamische Arrays):
Delphi-Quellcode:
var
  s : string;
  i, anz_comment : integer;
begin
  // Sinn & Zweck: Zähle alle Zeilen, die mit * beginnen
  anz_comment : = 0;
  for i:=0 to Memo1.Lines.Count-1 do
  begin
    s := Memo1.Lines[i];

    // sollte die Zeile leer sein, also s ='' dann knallts hier richtig
    // es gibt eine Zugriffsverletzung, denn s zeigt auf nil
    // auch die Bereichsprüfung kann hier keinen Schutz bieten
    if s[1] = '*' then
      Inc(anz_comment);
  end;

Delphi-Laie 24. Mär 2010 21:59

Re: Die häufigsten Programmierirrtümer
 
Oder:

if a=1 or 2 (anstatt: if (a=1) or (a=2)),

also so vereinfacht bzw. verkürzt, wie man in unserer natürlichen Sprache abgekürzt, aber dennoch verständlich sich auszudrücken pflegt.

s.h.a.r.k 24. Mär 2010 22:12

Re: Die häufigsten Programmierirrtümer
 
@sx2008: Ist ein s := '' gleichzusetzen, wie s := nil? :gruebel: Wäre mir definitiv neu, wobei ich nicht weiß, wie das intern gehandelt wird.

Zitat:

Zitat von sx2008
Delphi-Quellcode:
var
  s : string;
  i, anz_comment : integer;
begin
  // Sinn & Zweck: Zähle alle Zeilen, die mit * beginnen
  anz_comment : = 0;
  for i:=0 to Memo1.Lines.Count-1 do
  begin
    s := Memo1.Lines[i];

    // sollte die Zeile leer sein, also s ='' dann knallts hier richtig
    // es gibt eine Zugriffsverletzung, denn s zeigt auf nil
    // auch die Bereichsprüfung kann hier keinen Schutz bieten
    if s[1] = '*' then
      Inc(anz_comment);
  end;

Hier will ich noch anbringen, dass ich es schon mehrfach gesehen habe, dass bei Schleifen entweder bei 1 angefangen wird und der Zähler dann als Index verwendet wird, wobei dieser dann nicht so verwendet wird Zähler - 1. Beim letzten Element schlägt dies dann folglich fehl. Oder dass zwar bei 0 begonnen wird zu zählen, aber bis (in diesem Fall) Memo1.Lines.Count läuft und nicht Memo1.Lines.Count - 1.

R2009 25. Mär 2010 06:10

Re: Die häufigsten Programmierirrtümer
 
Hi,

aus meinen C Erfahrungen:

if (a = 0)

ist nicht das gleiche wie

if (a == 0)

Das ist ein Fehler der im nachhinein kaum noch zu finden ist.
Compiler meckert nicht. Im ersten Fall wird kein Vergleich durchgeführt sondern a die Null zugewiesen.

Ist zwar kein Fehler aber was ich überhaupt nicht leiden kann ist die C Schreibweise in Pascal:

Delphi-Quellcode:
extrem unschön:
If blabla then begin
...
end
sehr viel übersichtlicher:
If blabla then
   begin
     ...
   end
Was mich auch nervt ist mein eigener unkommentierter Kode,
den ich dann nach 4 Wochen selbst nicht mehr versteh!

Grüsse
Rainer

alzaimar 25. Mär 2010 06:37

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von R2009
extrem unschön:
...
sehr viel übersichtlicher:

der 'extrem unschöne' Code wird von Programmierern, die viel Code lesen, bevorzugt. Das "Begin" auf einer separaten Zeile hat keine eigene Aussage: Das hier bedingter Code folgt, ist durch die Einrückung (horizontale Formatierung) schon hinreichend dokumentiert. Letztendlich ist es jedoch Geschmackssache und muss jeweils Teamweit festgelegt werden. Diskussionen > 5 min sind hier überflüssig. Wir haben das z.B. durch Abstimmung geregelt.
Zitat:

Was mich auch nervt ist mein eigener unkommentierter Kode, den ich dann nach 4 Wochen selbst nicht mehr versteh!
Dann schreib ihn so, das Du (man) ihn versteht. :zwinker: Das geht auch ohne Kommentare. Kommentare sind eh böse. :mrgreen:

Was Du aber vielleicht eigentlich meinst, ist:
Ein großer Programmiererirrtum ist es, zu meinen, das Maß aller Dinge sei funktionierender Code.
Das Maß aller Dinge muss lesbarer Code sein (der kann im Nachhinein viel einfacher entwanzt werden).

Das schließt deine oben zitierte Meinung mit ein, hoffe ich.

R2009 25. Mär 2010 06:53

Re: Die häufigsten Programmierirrtümer
 
Hi alzaimar,

Zitat:

der 'extrem unschöne' Code wird von Programmierern, die viel Code lesen, bevorzugt. Das "Begin" auf einer separaten Zeile hat keine eigene Aussage: Das hier bedingter Code folgt, ist durch die Einrückung (horizontale Formatierung) schon hinreichend dokumentiert. Letztendlich ist es jedoch Geschmackssache und muss jeweils Teamweit festgelegt werden. Diskussionen > 5 min sind hier überflüssig. Wir haben das z.B. durch Abstimmung geregelt.
Dies ist ganz einfach meine persönliche Meinung.
Ich will niemand davon überzeugen und ich will auch keine Diskussion darüber anfangen.

Zitat:

der 'extrem unschöne' Code wird von Programmierern, die viel Code lesen, bevorzugt.
das ist eine subjektive Aussage die für unser Umfeld hier nicht stimmt.

Grüsse
Rainer
Ps: konnte das einfach so nicht stehen lassen. Bitte keine Diskussion darüber anfangen!

Luckie 25. Mär 2010 06:59

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von alzaimar
Zitat:

Zitat von R2009
extrem unschön:
...
sehr viel übersichtlicher:

der 'extrem unschöne' Code wird von Programmierern, die viel Code lesen, bevorzugt. Das "Begin" auf einer separaten Zeile hat keine eigene Aussage: Das hier bedingter Code folgt, ist durch die Einrückung (horizontale Formatierung) schon hinreichend dokumentiert.

Was ich mir aber abgewöhnt habe ist folgendes:
Delphi-Quellcode:
if ... then
   ...; // eine Zeile
stattdessen:
Delphi-Quellcode:
if ... then
begin
  ...; // eine Zeile
end;
Ich fasse auch Rümpfe in begin und end ein, auch wenn sie nur eine Zeile umfassen. Einfach aus dem Grund, weil der Rumpf eventuell später erweitert wird und man dann vergisst das begin und end zu ergänzen. Bei dem daraus resultierenden Fehlverhalten kann man sich manchmal dumm und dämlich suchen. So was vermeide ich somit von vorne herein.

Das mache ich übrigens in allen Programmiersprachen so, sei es in Delphi oder PHP. Ich habe sogar schon Code vom Kollegen dahingehend angepasst.

Was Kommentare angeht: Sie generell als böse zu bezeichnen ist auch nicht ganz richtig, wie eigentlich fast jede Pauschlisierung. Aber wenn man etwas kommentiert, dann höchstens das Warum. Das Wie sehe ich am Code. Denn jemand der den Code liest wird sich meist fragen: Warum macht der das? Wenn dann da steht "Workaround wegen Bug XYZ", dann weiß derjenige Bescheid und ändert die Stelle nicht, weil er denkt es wäre überflüssig oder so und baut somit wieder einen schon beseitigten Fehler ein.
Auch habe ich mir angewöhnt, wenn ich fremden Code ändere meine Änderungen zu markieren mit:
Delphi-Quellcode:
// [mp:start]
...;
...;
...;
// [mp:end]
(mp ist mein Kürzel in der Firma.) Dann sehe ich sofort welcher Code von mir ist und ich kann ihn im Fall der Fälle über die Such-Funktion auch schneller wiederfinden. Leider habe ich meinen Kollegen noch nicht dazu bringen können dies auch zu tun. Wenn ich jetzt einen Fehler beheben muss, weiß ich teilweise nicht, ob der Fehler vom Framework stammt oder in vom Kollegen nachträglich hinzugefügten Code. Ich habe schon Stunden mit der Fehlersuche verbracht, wo es dann nachher hieß: "Äh, Moment, der Code ist von mir. Ich weiß, was da nicht stimmt." :wall:

Cylence 25. Mär 2010 07:35

Re: Die häufigsten Programmierirrtümer
 
hmm

ich glaub ich hab auch noch was, ein bekannter von mir macht ständig sachen

onFormActivate

besser wär aber onFormshow, weil activate wird aufgerufen wenn man mal auf den desktop klickt und dann wieder auf das fenster....hat schon einige probleme gegeben hier...


Gruß

tom

Luckie 25. Mär 2010 07:53

Re: Die häufigsten Programmierirrtümer
 
Nun ja, das ist aber weniger ein Irrtum, als ein Fehler würde ich sagen.

Hansa 25. Mär 2010 08:26

Re: Die häufigsten Programmierirrtümer
 
Ein häufiger Irrtum ist :
Delphi-Quellcode:
for i := 1 to StringList.Count ...
Das ist eben das Versehen, zu vergessen, dass das bei 0 anfängt und dementsprechend bei count-1 Schluss ist. "Listenindex überschreitet das Maximum XY". :shock:

Aber was ist hieran auszusetzen, bzw. unschön, mal davon abgesehen, dass es sich keineswegs um einen Irrtum handelt :

Zitat:

Zitat von R2009
Ist zwar kein Fehler aber was ich überhaupt nicht leiden kann ist die C Schreibweise in Pascal:

Delphi-Quellcode:
extrem unschön:
If blabla then begin
...
end

sehr viel übersichtlicher:
If blabla then
   begin
     ...
   end

Ich bevorzuge die erste Variante. Bei mir einzige Abweichung vom ansonsten IMHO guten Styleguide. Auch die zweite entspricht übrigens nicht dem offiziellen Styleguide. Grund für 1. Variante : wenn sich was verirrt, dann ein END; Oder ein begin wird vergessen. Ist so etwas passiert, dann will ich auch direkt sehen, ob das zu if, while oder sonstwas gehört. Das vom Styleguide, also das BEGIN bündig unter das zugehörige IF etc. zu schreiben läuft zwar ungefähr auf dasselbe hinaus. Notfalls geht man vom END; aus einfach nach oben, hat das entsprechende IF und sieht, ob das BEGIN am Ende der Zeile steht. Oder eben eine Zeile darunter. Aaaaber : es dürfte keine Seltenheit sein, dass eine Prozedur mit 10 IF...BEGIN usw. sagen wir mal 70 Zeilen hat. Die geht dann auf eine DIN A 4 Seite. Werden 10 BEGIN in extra Zeilen geschrieben, dann sinds schon 80 und die Seite reicht knapp eben nicht. Verschachtelungstiefe ist dann auch nicht sofort erkennbar. Für Bildschirm gilt ähnliches. Es muss unnötigerweise mehr gescrollt werden etc. Bei neueren Delphi-Versionen ist dieses Problem aber auch durch Ein/Ausklappen etwas entschärft. Betonung liegt dabei auf "etwas".

Wer nur nach Zeilen bezahlt wird, der richte sich allerdings wirklich besser 100% nach dem Styleguide. :mrgreen:

joachimd 25. Mär 2010 10:32

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von Hansa
Ein häufiger Irrtum ist :
Delphi-Quellcode:
for i := 1 to StringList.Count ...
Das ist eben das Versehen, zu vergessen, dass das bei 0 anfängt und dementsprechend bei count-1 Schluss ist. "Listenindex überschreitet das Maximum XY". :shock:

Dazu die Worte meines (alten) Informatik-Professors, der inzwischen schon sicherlich nicht mehr auf dieser Erde weilt:
Zitat:

Es ist immer eins mehr oder weniger als man denkt

BUG 25. Mär 2010 10:43

Re: Die häufigsten Programmierirrtümer
 
Zitat:

Zitat von R2009
aus meinen C Erfahrungen:

if (a = 0)

ist nicht das gleiche wie

if (a == 0)

Das ist mir auch mehrfach passiert, besonders wenn man von Pascal = als Vergleichsoperator gewöhnt ist :evil:

Zitat:

Zitat von joachimd
Dazu die Worte meines (alten) Informatik-Professors, der inzwischen schon sicherlich nicht mehr auf dieser Erde weilt:
Zitat:

Es ist immer eins mehr oder weniger als man denkt

Der Fehlertyp hat sogar seinen eigenen Namen: Off-by-One-Error


Alle Zeitangaben in WEZ +1. Es ist jetzt 07:49 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz