mach ich zu viele Kommentare?
-
Eure Funktionen sind viel zu lang.
-
SirLant schrieb:
// Erzeuge ein Objekt das die Farbe im richtigen Format für setColor enthält Color color = Color.decode ( "#" + scolor );
Man kann aber voraussetzen, dass der Leser zumindest die Programmiersprache kann.
Ansonsten muss ich 'grob' zustimmen, Funktionen kommentieren den Code besser.
-
DrGreenthumb schrieb:
Man kann aber voraussetzen, dass der Leser zumindest die Programmiersprache kann.
Das hab ich mir auch gedacht. Aber manche Lehrer sind wirklich so dermaßen dumm, dass zB. die Zeile int "iPos;" mit "// Variablendefinition für Position" kommentiert werden muss.
Dann wirds sinnlos, meiner Meinung nach, aber leider muss ich mich daran halten.
Ansonsten seh ich das auch in etwa so. An komplexen Stellen lieber mal etwas mehr kommentieren und was ich gerne mache ist über die einzelnen Funktionen in 2-3 Zeilen erklären was in der Funktion geschieht.
-
CrazyOwl schrieb:
DrGreenthumb schrieb:
Man kann aber voraussetzen, dass der Leser zumindest die Programmiersprache kann.
Das hab ich mir auch gedacht. Aber manche Lehrer sind wirklich so dermaßen dumm, dass zB. die Zeile int "iPos;" mit "// Variablendefinition für Position" kommentiert werden muss.
damit wollen die lehrer prüfen ob du auch drüber reden kannst was du macht, der erfolg ist aber nur mässig weil die leute trozdem copy&past'en oder sich auch den kommentar vom nachbar hollen
-
Findet ihr das zuviel?
nö.Wie kommentiert ihr eigentlich immer?
Reichlich, insbesondere den Vertrag. Im Quelltext meistens nur die "trickreichen" Sachen.Und: in welcher Sprache (Deutsch, Englisch, Mischmasch?)???
Englisch, weil ich da flüssiger binTipp: es gibt tools wie Doxygen (http://www.doxygen.org), die deine Kommentarwut in eine brauchbare Software-Dokumentation verwandeln können
-
Eindeutig zuviel. Wenn du im Team arbeitest können die Leute die Sprache ja sowieso.. Der Code sollte selbsterklärend sein!
Es gibt ein paar nützliche Grundregeln, die dir da helfen könnten:- 1 Kommentar am Anfang der Funktion der die Frage "Was macht dies Funktion" knapp und klar beantwortet. Parameter sollten selbstsprechend sein!
- Versuche NIEMALS zu erklären WIE dein Code etwas macht. erkläre knapp WAS er macht. Versuche deinen Code so zu schreiben dass er selbsterklärend ist. Und es ist reinste zeitverschwendung schlechten Code zu erklären
- Die Funktion sollte nicht länger als eine Bildschirmseite sein (ANSI SCREEN 24x80!)
- sollte die Funktion länger werden -> Aufteilen -> Funktionsnamen selbstsprechend
- KEINE Kommentare in einer Funktion. Wenn dein Code so komplex ist dass er Kommentare braucht dann unterteile ihn in Funktionen mit einleuchtenden Funktionsnamen. Die können dann einen Kommentar abbekommen in dem steht WAS gemacht wird und NOTFALLS WARUM es gemacht wird.. NOCHMAL: NIEMALS WIE es gemacht wird!
-
Chickenman schrieb:
- Versuche NIEMALS zu erklären WIE dein Code etwas macht. erkläre knapp WAS er macht. Versuche deinen Code so zu schreiben dass er selbsterklärend ist. Und es ist reinste zeitverschwendung schlechten Code zu erklären
ich find deinen ersten Vorschlag merkwuerdig. IMO sind Kommentare genau dafuer da, zu erklaeren WIE etwas gemacht wird... Das WAS an sich wird doch eigentlich schon durch die Sprache selbst ausgedrueckt (z. B. durch die Funktionsnamen), und ist mit einem kleinen Ueberfliegen des Codes meistens sowieso mehr oder weniger ersichtlich. Die vielen "im folgenden Block tu ich dieses und jenes" Kommentare, dich ich manchmal machen, kommen mir oft wie die ueberfluessigsten vor...
Das WIE hingegen find ich wichtiger. Natuerlich ist es fuer die "Benutzer" meiner Klassen und Funktionen vor allem wichtig, WAS gemacht wird. Aber die schauen sich sowieso nur die Headerdateien, Funktionsdeklarationionen oder evt. die Dokumentation an...
Die Kommentare in den Funktionsruempfen selbst hingegen liest meist sowieso nur, wer auch was dran aendern will. Und eben fuer die Leute ist es IMO sehr wohl von Bedeutung, WIE etwas gemacht wird (damit sie's veraendern koennen), bzw. WARUM es genau auf diese oder jene Art gemacht wird (damit sie den Code ueberhaupt im Detail verstehen)...Ich hab allerdings schon oefters Funktionen gesehen, die kaum erklaeren, WIE etwas geloest wird, aber ehrlich gesagt, hab ich nie verstanden, warum das so ist... ich bin einfach davon ausgegangen, die Programmierer sind zu faul, es hinzuschreiben. Auf die Idee, das waere Absicht, bin ich nie gekommen. Wenn du mir ein paar einleuchtende Gruende dafuer nennen kannst, lass ich mich gern ueberzeugen
Chickenman schrieb:
- Die Funktion sollte nicht länger als eine Bildschirmseite sein (ANSI SCREEN 24x80!)
Klar, den Vorschlag hab ich auch schon oft genug gehoert, und ich versuch ihm eigentlich auch Folge zu leisten. Aber ich kann mir nicht vorstellen, dass viele Projekte 100%ig diese Konvention befolgen, ohne dabei voellig zerhackten Code zu schreiben. Gute, aussagekraeftige Variablennamen brauchen ebensoviel Platz wie gute, aussagekraeftige Funktionsnamen... und nein, dinge wie ulStdDevP oder strcmp() halt ich nicht fuer gute Namen, bis ich entschluesselt hab wofuer die einzelnen Akronyme eigentlich da sind, hab ich den selben Code mit besseren Variblen- und Funktionsnamen bereits 10x durchgelesen... Abgesehen von brauchbarer Einrueckung, taktischen Kommentaren usw.
Und wenn man deshalb so lange Namen verwendest, aber trotzdem in den 80 Spalten bleiben willst, wie sieht dann ein Funktionsaufruf auf? Auf x Zeilen aufgeteilt? Schoen und gut, aber wie willst du dann in den 24 Zeilen bleiben? Noch dazu, wo doch gut strukturierter Code auch nach Whitelines schreit?Und ausserdem verwenden - von den EMACS-Juengern mal abgesehen - heutzutage doch die meisten Programmierer Entwicklungsumgebungen, wo mehr als 1 Terminalseite auf einmal auf dem Bildschirm platz hat
Was das lange Aufteilen von langen Funktionen in mehrere kurze angeht: Ich hab's mir zwar auch schon ueberlegt, aber... Funktionen stellen fuer mich wiederverwendbare Code-Stuecke dar. Ich unterteile, wenn ich denke "diesen Teil koennt ich irgendwo nochmal brauchen". Aber Funktionen stellen fuer mich eine logische Einheit dar. Ich versuch zwar immer, sie so kurz und aufgeteilt wie moeglich zu machen, aber... manche Teile gehoeren einfach zusammen, die kann man IMO nicht gut aufteilen, ohne das Ganze umstaendlich zu loesen (Unmengen von Parametern/Rueckgabewerten z. B. )....
Zeig doch mal ein bischen Beispielcode von dir
@peterchen:
ich weiss, ich hab mir mal mein eigenes kleines Doxygen geschrieben
-
@Chickenmann: Welche der beispielkommentare bitte soll er denn einsparen?
ich stimme mit dir überein, daß gut geschriebener Code der beste Kommentar ist. Allerdings läßt sich a) nicht alles in Code ausdrücken, was zu kommentieren ist und b) variiert "einleuchtend" von Coder zu Coder.
1 Kommentar am Anfang der Funktion der die Frage "Was macht dies Funktion" knapp und klar beantwortet. Parameter sollten selbstsprechend sein!
Wie ist es mit dem Vertrag? Randbedingungen? Fehlerbehandlung?
Ich halte das Aufschreiben des verwendeten Algorithmus nicht für prägnant genug, aber immerhin besser als ein "gibt autor- und quotes-Array zurück"Versuche NIEMALS zu erklären WIE dein Code etwas macht.
Einspruch gegen das geschriene "niemals". Es gibt sehr wohl Fälle, in denen ein kurzer Kommentar zum "Wie" arge Kopfschmerzen beim späteren Leser wermeiden kann. Nicht jedes "Wie" ist für den besten programmierer immer aus dem Code ersichtlich, und für den durchschnittlichen programmierer schon gar nicht.Die Funktion sollte nicht länger als eine Bildschirmseite sein (ANSI SCREEN 24x80!)
Erstens ist das 24x80 überholt, es gibt wenige Entwicklungsumgebungen, in denen das noch Sinn macht. Kommt natürlich darauf an, für welche Plattformen man entwickelt. Und für die üblichen Editoren in einer DOS-Umgebubg wäre 20x78 angebracht....Problem: wenn eine Funktion viel internen State zu verwalten hat, kann ich das nicht einfach auf mehrere Funktionen aufbrechen, ohne das ich eine Klasse draus mache. Schwuppse handle ich mir doppelt soviel Code ein. Das macht nicht immer Sinn! Da hab ich lieber 100x100 Zeichen Code mit eindeutigen Variablenmnamen und vielen Kommentaren.
"iPos;" mit "// Variablendefinition für Position" kommentiert werden muss.
Dann wirds sinnlos, meiner Meinung nach, aber leider muss ich mich daran halten."Wenn man eine Variablendeklaraiton kommentieren muß, ist der Variablenname schlecht gewählt."
Ist aber auch nur eine Faustregel.
-
Blue-Tiger schrieb:
Und ausserdem verwenden - von den EMACS-Juengern mal abgesehen - heutzutage doch die meisten Programmierer Entwicklungsumgebungen, wo mehr als 1 Terminalseite auf einmal auf dem Bildschirm platz hat
Es ist wesentlich übersichtlicher wenn die Funktionen kurz sind. Und wenn die Zeilen nicht breiter als 80 Zeichen sind. Ich zB. hab auch gerne mal 2 Dateien gleichzeitig nebeneinander geöffnet, und seitwärts scrollen müssen ist das schlimmste überhaupt.
SirLant schrieb:
// Tasse zeichnen if (tasse_oder_smilie.equals ("tasse") || tasse_oder_smilie.equals("Tasse") || tasse_oder_smilie.equals ("t") || tasse_oder_smilie.equals ("T")) java_tasse (g, color, x, y, breite, hoehe); else if (tasse_oder_smilie.equals ("smilie") || tasse_oder_smilie.equals ("Smilie") || tasse_oder_smilie.equals ("s") || tasse_oder_smilie.equals ("S")) smilie (g, color, x, y, breite, hoehe);
Sowas zB. muss doch echt nicht sein.
tasse_zeichnen();
wär viel schöner und braucht kein Kommentar.
Für mich sind diese beiden Beispiele die totale Katastrophe (mal abgesehen davon, dass hier blödsinnige Kommentare drin sind weil's ein Lehrer so will).
-
Das ist lächerlich:
// leave function if file does not exist // test if the file exists in a separate if-statement, because // opening a non-existing file would result in a PHP-Error // (displayed on the created website too)
-
peterchen schrieb:
"Wenn man eine Variablendeklaraiton kommentieren muß, ist der Variablenname schlecht gewählt."
Ist aber auch nur eine Faustregel.So war's eigentlich nicht gemeint, war nur ein Beispiel. Anderes Beispiel: UpdateData(FALSE); muss auch kommentiert werde.
Also ich find das leicht übertrieben, aber was solls.
-
Wollte eigentlich auch nur sagen, daß Variablendeklarationen normalerweise keines Kommentars bedürfen (sollten)
bei UpdateData(true/false) freu ich mich immer, wenn#s kommentiert ist, weil ich mir nie die Richtung merken kann...
-
Na gut, von mir aus, ich geb auf, ihr habt gewonnen.
Nur ich kann immer noch nicht zustimmen, dass es sinnvoll ist jede Zeile zu kommentieren.
-
peterchen schrieb:
bei UpdateData(true/false) freu ich mich immer, wenn#s kommentiert ist, weil ich mir nie die Richtung merken kann...
das darf aber kein Grund sein, dass unnötige Kommentare den Code befüllen. Sowas kann man immer in der Doku nachsehen.
-
@Doc: falsch, die Dinger sollten "UpdateControls()" und "SaveControlData()" heißen. .rolleyes:
(i.e. klare Namen sind wichtiger als Doku - inline oder extern)Ich würd# von niemandem verlangen, seine UpdateData's zu kommentieren, aber auch niemanden zurückhalten. Es gibt viel sinnlosere Kommentare als z.B. "// saveAndValidate" oder "// update controls"
Wenn man komplexen Code bearbeitet, der evtl. von jmd anders geschrieben wurde, ist jeder (richtige) Hinweis wertvoll, weil selbst ein Blick in die Doku einen mentalen Kontextswitch darstellt, der evtl. wichtigere Informationen rauswirft. Ist alles eine Frage der Kompexität. Als ich noch "Kleinkram" programmiert hab, ging mit der ganze Krempel auch A. vorbei. Aber wenn man 500.000 Zeilen Quelltext zusammenhalten muß, an denen 5 verschiedene Leute gearbeitet haben, sieht man die Dinge halt ein bißchen anders.
Du kannst dir ja einen Editor (oder Plugin) schreiben, der alle Kommentare ausblendet
-
Versuche NIEMALS zu erklären WIE dein Code etwas macht. erkläre knapp WAS er macht. Versuche deinen Code so zu schreiben dass er selbsterklärend ist. Und es ist reinste zeitverschwendung schlechten Code zu erklären
Was soll das denn? Wie er es macht ist offensichtlich, nur was er macht nicht.
if (x > 1) x = 2-1/x;
Wie erledigt der Code seine Aufgabe? Er prüft, ob x größer als eins ist. Wenn ja weist er x den Wert 2-1/x zu.
Das ist ja hochinteressant und hätte ich da ich überhaupt nicht programmieren kann selbst nie rausgefunden. Schwachsinn!
Was macht er das ist viel interessanter. Gut der Code ist jetzt aus dem Kontext gerissen, aber ich garantiere dir, selbst wenn ich dir den Kontext zeige wirst du nicht erschließen können, was der Code macht.Und hier ist eine Stelle, an der ich persönlich momentan keine eigene Funktion aus dem Code machen, sondern ein kleines Komentar dran pappe.
Nebenbei: Ich hab mal ein paar meiner Projekte analysieren lassen. Bei den meisten kam raus, das 3% des Projekts aus Komentar besteht. Der höchste Anteil war 15%.
-
Blue-Tiger schrieb:
ich find deinen ersten Vorschlag merkwuerdig. IMO sind Kommentare genau dafuer da, zu erklaeren WIE etwas gemacht wird... Das WAS an sich wird doch eigentlich schon durch die Sprache selbst ausgedrueckt (z. B. durch die Funktionsnamen), und ist mit einem kleinen Ueberfliegen des Codes meistens sowieso mehr oder weniger ersichtlich.
Merkwürdig sind dann aber auch alle die am Linux-kernel coden, und das sind viele die den Code von vielen verstehen müssen. Ich finde dass Wie-Erklärungen entwender total überflüssig sind da entweder der Code selbsterklärend ist oder der Code so schlecht geschrieben ist dass man sowieso neuschreiben sollte. Also nur noch was.
Blue-Tiger schrieb:
Die vielen "im folgenden Block tu ich dieses und jenes" Kommentare, dich ich manchmal machen, kommen mir oft wie die ueberfluessigsten vor...
Deswegen sollte am Anfang der Funktion einmal Erklärt sein was gemacht wird und fertig.
Blue-Tiger schrieb:
Und wenn man deshalb so lange Namen verwendest, aber trotzdem in den 80 Spalten bleiben willst, wie sieht dann ein Funktionsaufruf auf? Auf x Zeilen aufgeteilt? Schoen und gut, aber wie willst du dann in den 24 Zeilen bleiben? Noch dazu, wo doch gut strukturierter Code auch nach Whitelines schreit?
Und ausserdem verwenden - von den EMACS-Juengern mal abgesehen - heutzutage doch die meisten Programmierer Entwicklungsumgebungen, wo mehr als 1 Terminalseite auf einmal auf dem Bildschirm platz hat
Was hast du denn für Funktions/Variablennamen
Wenn du 80 Zeichen damit voll bekommst...const void * inter_module_get_request(const char *im_name, const char * mod_name)
Das sind 79... Du Programmierst ja nicht Paskal wo man noch "ThisVariableIsATemporaryCounter" anstatt "i" geschrieben hat... Vor allem C/C++ sind spartanische Sprachen!
Und EMACS nutzen noch viele
Das mit der Terminalseite hat jedoch nicht nur Platz-Gründe sondern soll vor allem auch eine Richtlinie zur Selbstkontrolle sein. Superfunktionen in Megabreite verleiten nunmal zu Fehlern und sind unübersichtlich!peterchen schrieb:
Versuche NIEMALS zu erklären WIE dein Code etwas macht.
Einspruch gegen das geschriene "niemals". Es gibt sehr wohl Fälle, in denen ein kurzer Kommentar zum "Wie" arge Kopfschmerzen beim späteren Leser wermeiden kann. Nicht jedes "Wie" ist für den besten programmierer immer aus dem Code ersichtlich, und für den durchschnittlichen programmierer schon gar nicht.Die Ausnahme bestätigt die Regel. Aber es sollte auf jeden Fall eine Ausnahme bleiben! Und der Kommentar solte so kurz wie nur möglich schreiben. Und am besten sollte man eine Woche später nochmal nachgucken und nochmal überlegen obs nicht nen besseren Weg gäbe.
peterchen schrieb:
Problem: wenn eine Funktion viel internen State zu verwalten hat, kann ich das nicht einfach auf mehrere Funktionen aufbrechen
Stimmt. Ausnahme. Lange Case oder if-Szenarios können nicht aufteilt werden, das würde es unübersichtlich machen.
Blue-Tiger schrieb:
Zeig doch mal ein bischen Beispielcode von dir
Nö
aber ausm Linuxkernel gibts zum Beispiel module.c (hab ich halt grad offen)
/** * inter_module_register - register a new set of inter module data. * @im_name: an arbitrary string to identify the data, must be unique * @owner: module that is registering the data, always use THIS_MODULE * @userdata: pointer to arbitrary userdata to be registered * * Description: Check that the im_name has not already been registered, * complain if it has. For new data, add it to the inter_module_entry * list. */ void inter_module_register(const char *im_name, struct module *owner, const void *userdata) { struct list_head *tmp; struct inter_module_entry *ime, *ime_new; if (!(ime_new = kmalloc(sizeof(*ime), GFP_KERNEL))) { /* Overloaded kernel, not fatal */ printk(KERN_ERR "Aiee, inter_module_register: cannot kmalloc entry for '%s'\n", im_name); kmalloc_failed = 1; return; } memset(ime_new, 0, sizeof(*ime_new)); ime_new->im_name = im_name; ime_new->owner = owner; ime_new->userdata = userdata; spin_lock(&ime_lock); list_for_each(tmp, &ime_list) { ime = list_entry(tmp, struct inter_module_entry, list); if (strcmp(ime->im_name, im_name) == 0) { spin_unlock(&ime_lock); kfree(ime_new); /* Program logic error, fatal */ printk(KERN_ERR "inter_module_register: duplicate im_name '%s'", im_name); BUG(); } } list_add(&(ime_new->list), &ime_list); spin_unlock(&ime_lock); } /** * inter_module_unregister - unregister a set of inter module data. * @im_name: an arbitrary string to identify the data, must be unique * * Description: Check that the im_name has been registered, complain if * it has not. For existing data, remove it from the * inter_module_entry list. */ void inter_module_unregister(const char *im_name) { struct list_head *tmp; struct inter_module_entry *ime; spin_lock(&ime_lock); list_for_each(tmp, &ime_list) { ime = list_entry(tmp, struct inter_module_entry, list); if (strcmp(ime->im_name, im_name) == 0) { list_del(&(ime->list)); spin_unlock(&ime_lock); kfree(ime); return; } } spin_unlock(&ime_lock); if (kmalloc_failed) { printk(KERN_ERR "inter_module_unregister: no entry for '%s', " "probably caused by previous kmalloc failure\n", im_name); return; } else { /* Program logic error, fatal */ printk(KERN_ERR "inter_module_unregister: no entry for '%s'", im_name); BUG(); } } /** * inter_module_get - return arbitrary userdata from another module. * @im_name: an arbitrary string to identify the data, must be unique * * Description: If the im_name has not been registered, return NULL. * Try to increment the use count on the owning module, if that fails * then return NULL. Otherwise return the userdata. */ const void *inter_module_get(const char *im_name) { struct list_head *tmp; struct inter_module_entry *ime; const void *result = NULL; spin_lock(&ime_lock); list_for_each(tmp, &ime_list) { ime = list_entry(tmp, struct inter_module_entry, list); if (strcmp(ime->im_name, im_name) == 0) { if (try_inc_mod_count(ime->owner)) result = ime->userdata; break; } } spin_unlock(&ime_lock); return(result); } /** * inter_module_get_request - im get with automatic request_module. * @im_name: an arbitrary string to identify the data, must be unique * @modname: module that is expected to register im_name * * Description: If inter_module_get fails, do request_module then retry. */ const void *inter_module_get_request(const char *im_name, const char *modname) { const void *result = inter_module_get(im_name); if (!result) { request_module(modname); result = inter_module_get(im_name); } return(result); } /** * inter_module_put - release use of data from another module. * @im_name: an arbitrary string to identify the data, must be unique * * Description: If the im_name has not been registered, complain, * otherwise decrement the use count on the owning module. */ void inter_module_put(const char *im_name) { struct list_head *tmp; struct inter_module_entry *ime; spin_lock(&ime_lock); list_for_each(tmp, &ime_list) { ime = list_entry(tmp, struct inter_module_entry, list); if (strcmp(ime->im_name, im_name) == 0) { if (ime->owner) __MOD_DEC_USE_COUNT(ime->owner); spin_unlock(&ime_lock); return; } } spin_unlock(&ime_lock); printk(KERN_ERR "inter_module_put: no entry for '%s'", im_name); BUG(); }
Die Kommentarregeln sind übrigens von dem für Kernelprogrammierer vorgegebenen CodingStyle. Was ich bei C++-Programmierung sonst noch gut find ist unter http://geosoft.no/style.html
Ausserdem sind das alles nur wohlgemeinte Richtlinien die en-Masse erprobt worden für gut befunden worden sind...
-
peterchen schrieb:
@Doc: falsch, die Dinger sollten "UpdateControls()" und "SaveControlData()" heißen. .rolleyes:
(i.e. klare Namen sind wichtiger als Doku - inline oder extern)Da sind wir uns einig, aber dann lieber gleich richtige Funktionen schreiben als Blöde zu benutzen und jedesmal ein Kommentar hinter zu packen
Es ist ja nicht so, dass mich zu viele Kommentare stören, es ist nur blöd wenn man dort Kommentare setzt, wo man es mit Sprachmitteln besser hätte ausdrücken können.
Und diese beiden Beispiele hier, sind echt das krasse Gegenteil was ich mir von gut-lesbarem Code vorstelle.
Die ganze Ausgangsfrage ist schon ungünstig. Wenn man soviele halbglobale Variablen hat, brauch man natürlich Kommentare, dass man überhaupt weiß worums geht.
-
SirLant schrieb:
// Tasse zeichnen if (tasse_oder_smilie.equals ("tasse") || tasse_oder_smilie.equals("Tasse") || tasse_oder_smilie.equals ("t") || tasse_oder_smilie.equals ("T")) java_tasse (g, color, x, y, breite, hoehe); else if (tasse_oder_smilie.equals ("smilie") || tasse_oder_smilie.equals ("Smilie") || tasse_oder_smilie.equals ("s") || tasse_oder_smilie.equals ("S")) smilie (g, color, x, y, breite, hoehe);
Sowas zB. muss doch echt nicht sein.
tasse_zeichnen();
wär viel schöner und braucht kein Kommentar.
Für mich sind diese beiden Beispiele die totale Katastrophe (mal abgesehen davon, dass hier blödsinnige Kommentare drin sind weil's ein Lehrer so will).[/quote]
Wie sollte ich es denn deiner Meinung nach schreiben? Ich habe 4 mögl. Kombinationen
die der benutzer eingeben kann für den Smilie und 4 für die Tasse,
und für den Fall, dass etwas anderes passiert, ist das else da, das kann
ich doch gar nicht einfach so vereinfachen, oder doch?Zu den Kommentaren, wie gesagt, die meisten in der Klasse würden bei dem Color.decode
bereits verzweifeln trotz dem Kommentar, ohne wäre das für die Undenkbar.
-
*dreifach_post*