Was ist für euch guter Programmcode?
-
simon.phoenix schrieb:
edit: Lohnt es sich in Client-Code (wo man eh kaum ne umfangreiche externe Doku braucht) für doxygen optimiert zu kommentieren?
Eigentlich nicht wirklich. Weil das Dokumentieren ein großer Aufwand ist und hier kaum nutzen bringt.
Hier denke ich, ist es wesentlicher diverse Designentscheidungen zu dokumentieren und warum etwas wie gelöst wurde, sowie natürlich alle hacks/tricks und sonstigen schmutzigen sache (zB weil es performancemäßig nötig war)
-
Mecnels schrieb:
Findest Du nicht auch, dass sich TicTacToe nicht so ohne weiteres mit einer Umsetzung des Brettspieles Stratego vergleichen laesst?
Warum nicht? Beides Umsetzungen eines Brettspiels. Egal wie komplex Stratego ist, das Prinzip ist immer gleich. Teile ein großes Problem in viele kleine auf und die Welt sieht schon ganz anders aus.
Mecnels schrieb:
[...]Eine KI, die sich unter solchen Voraussetzungen auch in möglichst jeder Spielsituation zurecht finden soll, lässt sich eben nicht mit Tricks oder in 10 Zeilen codieren.
Du hast es nicht verstanden. Es geht nicht darum möglichst kurzen Code zu schreiben, sondern sinnvolle Abschnitte zu finden. Damit reduzierst du (falls es keine Redundanzen gibt) nicht die Länge des eigentlichen Codes, aber erhöhst die Übersichtlichkeit um ein Vielfaches. Was du machst ist alles in eine Funktion zu packen. Dadurch riskierst du, dass der Code zu einem Monster wird, das keiner mehr lesen will und übersiehst u.U. redundate Codeabschnitte.
-
Mecnels schrieb:
Eine KI, die sich unter solchen Voraussetzungen auch in möglichst jeder Spielsituation zurecht finden soll, lässt sich eben nicht mit Tricks oder in 10 Zeilen codieren.
Die KI ansich hat natürlich mehr als 10 Zeilen, vielleicht sogar millionen.
Aber eben in einzelnen Funktionen.
Es gibt keine monster funktion die alles macht, sondern eine million kleine funktionen die alle nur ganz wenig machen.Mir fällt auf, dass viele von Euch 'schleifenscheu' sind, das heisst: in den geposteten Beispielcodes ist zwar alles ganz nett in kleine Teilfunktionen zergliedert, aber kaum einmal entdecke ich (z.B. beim Programm mit den gerichteten Graphen) geschachtelte Schleifen.
Ist das nicht schön? So schön klar, keine tiefen verschachtelungen und nur wenig code pro funktion.
Ein heisser Tip: Schleifenvariablen werden üblicherweise in einem Prozessorregister untergebracht und inkrementiert, die Adressen irgendwelcher Funktionen hingegen müssen immer erst aus dem Speicher abgefragt werden.
Nö, ist nicht so. Stichwort inlining.
Ausserdem sind Funktionscalls mittlerweile so billig, dass inlining schon fast nutzlos ist.Ausserdem muss für jede lokale Variable in diesen Funktionen sowie für die übergebenen Parameter (welchen Typs auch immer) jedes Mal aufs Neue Speicher allokiert werden, die Adresse dieses Speichers in ein Register geholt werden und so fort.
Ne.
Was ich sagen will: Schleifenreicher Code, egal ob in C++ oder Java, ist immer um mindestens das Doppelte schneller als Code, der mit hunderten Minifunktionen vollgestopft ist (vielleicht ist das für viele Programmierer angenehmer zu lesen und zu verstehen, aber man sollte sich schon im Klaren darüber sein, dass zuviele Funktionen die Performance des gesamten Programmes negativ beeinflussen).
*lol*
ne, ist sicher nicht so.Unverständlich ist mir deshalb die Meinung, schleifenreicher Code sei schlecht, denn in jedem Fall ist er locker um das Doppelte leistungsstärker als Code, der mit Funktionsbezeichnern (Adressen) nur so überhäuft ist.
Woher hast du das?
Erstens ist vorzeigige optimierung mal sowieso ganz schlecht, auch wenn man performance beim design im auge behalten muss.
aber du scheinst nur halbwissen diesbezüglich zu haben.
ein compiler kann inlinen, teilweise inlinen die schleife unrollen, die funktion verdammt effektiv aufrufen, etc.ein funktionsaufruf kostet heutztutage nichts mehr und da es inlining gibt kostet es sogar oft garnix.
-
Shade Of Mine schrieb:
Woher hast du das?
Nun ja, ich war mal in der Compilerentwicklung tätig. Du auch?
-
Mecnels schrieb:
Unverständlich ist mir deshalb die Meinung, schleifenreicher Code sei schlecht, denn in jedem Fall ist er locker um das Doppelte leistungsstärker als Code, der mit Funktionsbezeichnern (Adressen) nur so überhäuft ist.
Ich kann mir nicht vorstellen, dass das die allgemeine Meinung ist. Code der weniger Schleifen hat und damit leichter zu lesen ist ist halt besser, da man heutzutage eigentlich die performace etwas weiter hintn anstellen kann als früher. Wenns ans optimieren geht, sieht das ganze dann schon wieder anders aus. Aber ich denke es heißt nicht ohne Grund, eine verfrühte optimierung ist der Ursprung allesn Übels...
Und dann gibt es ja noch inline...
-
Mecnels schrieb:
Shade Of Mine schrieb:
Woher hast du das?
Nun ja, ich war mal in der Compilerentwicklung tätig. Du auch?
Man muss kein Compilerentwickler sein um zu wissen das du Dünnsinn erzählst. Werd konkret... an welchem Compiler hast du mitentwickelt? Oder versuchst du am Ende nur zu bluffen?
-
Mecnels schrieb:
Shade Of Mine schrieb:
Woher hast du das?
Nun ja, ich war mal in der Compilerentwicklung tätig. Du auch?
ROFL
-
Shade Of Mine schrieb:
Optimizer schrieb:
* @param file Der ursprüngliche Dateiname. [...] protected static File findValidFileName(File file)
Wirklich der _Dateiname_?
ok...
/** * Schließt ein Socket und fängt jede IOException, die dabei auftritt.<br> * Leider implementiert <code>ServerSocket</code> nicht das * <code>Closeable</code>-Interface, sonst wäre diese Methode überflüssig. * @param socket Ein Socket, das geschlossen werden soll. Ist dieser * Parameter <code>null</code>, so macht die Methode gar nichts. */
Manchmal rulen templates schon, gell?
Damit hast du nicht wirklich nen Vorteil. Du würdest dir hier 2 Methoden sparen. Aber du kannst den Namen genauso wenig ändern und wenn du es tust und vielleicht was anderes so nennst, oder etwas an der Funktion erweiterst, hast du Verhalten, was du vielleicht nicht wolltest, aber lassen wir das... wir hatten das ja schon mal vor kurzem. IMHO ist es einfach ein Designfehler, dass die Sockets das Interface nicht implementieren.
Warum ist das eine Ausnahme?
validate*
klingt für mich nach: prüfe ob es passt und sags mir dann
hier wäre der name
ensureValidProtocol()
wohl besser, denn ein validate* klingt für mich nicht als ob
es eine Ausnahme wäre, wenn die Protokolle nicht passen...Da hast vielleicht Recht.
- kleiner seitenhieb auf checked exceptions.
dein Kommentar
// (Andere Exception werfen)
ist nicht durchführbar, weil du bereits IsNotAFolderException als einzig
mögliche Exception definiert hast. Eine Änderung hier, würde client code brechen.
Das ist genau das Misverständniss, was mich so ärgert.
Angenommen, die Exceptions wären nicht checked. Cool, dann kann ich jetzt ja einfach noch nen anderen Ausnahmetypen werfen!!
Aber wer fängt sie? Hast du darüber schon mal nachgedacht? Hast du dann nicht mit Client Code gebrochen, wenn der plötzlich abstirbt, weil du einfach mal schnell noch ne neue Exception werfen musstest? Ein sehr ungelungener Seitenhieb, wie ich finde.
Denn mit Client Code brichst du bei sowas immer. Es ist nur ne Frage, ob es bemerkt wird, oder nicht.
btw. ist es hier natürlich völlig egal, weil die Methode eh private ist und ich das selber schon auf die Reihe krieg. Außerdem ist die Methode schlicht noch nicht fertig. Aber ich weiß schon, was du sagen wolltest, nur leuchten mir deine Argumente gegen checked Exceptions nie ein.Mir persönlich gefallen diese Optional Komponenten Progressbar & Co nicht.
Du bindest dich damit an Swing - dh, eine Terminalausgabe erschwerst du damit
ungeheuerlich.Ja, da hab ich auch länger rumüberlegt. Ich wollte erst ein Interface für solche Status-Komponenten machen, was die Aktionen dann fressen.
Dann hätte ich noch Klassen geschrieben, die das implementieren und die Swing-Komponenten entsprechend dann ändern. Ich habe zu Gunsten der Einfachheit davon abgesehen, aber ich stimme dir zu.Danke, Code Review rult.
- kleiner seitenhieb auf checked exceptions.
-
ness schrieb:
Und dann gibt es ja noch inline...
inline ist ausserdem nur eine Empfehlung und in den meisten Fällen unnötig, da der Compiler meist ganz gut erkennt was er expandieren soll und was nicht.
-
Mecnels schrieb:
Shade Of Mine schrieb:
Woher hast du das?
Nun ja, ich war mal in der Compilerentwicklung tätig. Du auch?
lölölölölölöl
Welcome back, Sgt. Nukem.
-
Mecnels schrieb:
Wenns ans optimieren geht, sieht das ganze dann schon wieder anders aus. Aber ich denke es heißt nicht ohne Grund, eine verfrühte optimierung ist der Ursprung allesn Übels...
Und dann gibt es ja noch inline...Du wirst es nicht glauben, es gibt Problemstellungen, in denen kommt perfekte Speicher- und Zeiteinteilung an erster Stelle (verfrühte Optimierung). Auch wenn Dir der zur Verfügung stehende Hauptspeicher grenzenlos erscheinen mag, einige Berechnungen überfordern nach wie vor binnen weniger Millisekunden 2048 MB grosse RAMs (versuche ein Schachprogramm zu schreiben, das in eine feste Zugtiefe von 15 Halbzügen vordringt, und Du weisst, worauf ich hinaus will).
-
Und du wirst nicht glauben, dass findige Leute nur da optimieren wo es Sinn macht und dass man misst bevor man optimiert. Meist macht der Compiler schöne Optimierungen schon von selber; nett von ihm, oder? Dir als Compilerentwickler sage ich da aber sicher nichts neues. Ausserdem kann ein guter Algorithmus meist viel mehr zur Optimierung beitragen als ein Codeklumpen den kein Schwein mehr lesen kann.
-
Jetzt hast du schon zweimal korrigiert und es fehlt immer noch mindestens ein Komma.
-
Optimizer schrieb:
Jetzt hast du schon zweimal korrigiert und es fehlt immer noch mindestens ein Komma.
Neue Rechtschreibung *bluff*
-
Deine Signatur ist etwas großkotzig, sorry...
-
Es gibt keinen guten oder schlechten Code.
Es gibt nur Code, der eine Problemstellung zufriedenstellend löst,
oder eben nicht zufriedenstellend löst. Ob da jetzt viele Schleifen oder
viele Funktionen oder viel Flammerei mit im Spiel ist, ist dann eigentlich
belanglos!!!Schluss jetzt!!!
-
simon.phoenix schrieb:
Deine Signatur ist etwas großkotzig, sorry...
~vorsicht ironie~
Wieso? Ich hätte gerne ein top-optimiertes Stratego von dessen Source ich noch was in puncto Optimierung lernen kann.
-
simon.phoenix schrieb:
Deine Signatur ist etwas großkotzig, sorry...
Dass mittlerweile Aufrichtigkeit mit Grosskotzigkeit gleichgesetzt wird, ist sogar mir neu, und ich versuche doch immer einigermaßen auf dem Laufenden zu bleiben.
Jedenfalls ist es nicht irgendeine Phantasie meinerseits, dass Speicherzugriffe auf ein Prozessorregister beinahe mit der einem arglosen Kunden verkauften Taktfrequenz (sagen wir 2.5 Ghz) passieren (im Unterschied zu Zugriffen auf den Haupt- oder Grafikkartenspeicher - na, was glaubt ihr: wieviele 16-Bit-Werte kann ein Prozessor, auf dem 2.5 Ghz draufstehen, pro Sekunde aus dem Hauptspeicher in ein ein Prozessorregister holen?)
Preisfrage 1: Was ist eine Game Loop?
Preisfrage 2: Was macht die Funktion QueryPerformanceCounter? (ein sperriger
Bezeichner, aber sehr aussagekräftig, wie ich meine)
Das beste zum Schluss:
Preisfrage 3: Was glaubt ihr, wieviele Codezeilen in C stecken in der wohl-
bekannten und vielgenutzten CreateWindowEx- Funktion?
(Etwa auch nur 10? Weil ja alles das selbe ist? Oder nicht
doch eher 2741 Codezeilen_wenn ich mich nicht verzählt hab?
Tja - wer weiß? Nicht mitgerechnet
sind alle Funktionen, die CreateWindowEx selber aufruft!!!)Seltsam: Wenn sich wirklich jedes Problem in 10 Zeilen C++ Code lösen lassen könnte (weil ja TicTacToe, Stratego und womöglich sogar Schach ein und dasselbe sind), wäre wohl nie jemals ein Window auf einem Screen aufgetaucht, weil es keine Funktion gegeben hätte, die es erzeugt!
Flammen bringt aber wirklich niemanden hier weiter, also lass ich Euch den Spass und ihr dürft Euch ohne meine weitere Einwirkung weiter gegenseitig die Flöhe in die Ohren setzen.
Trotzdem einen schönen Abend.
-
Seltsam: Wenn sich wirklich jedes Problem in 10 Zeilen C++ Code lösen lassen könnte (weil ja TicTacToe, Stratego und womöglich sogar Schach ein und dasselbe sind), wäre wohl nie jemals ein Window auf einem Screen aufgetaucht, weil es keine Funktion gegeben hätte, die es erzeugt!
Musst du denn alles wörtlich nehmen? Es ist ja nicht so, dass eine Funktion nicht länger als 10 Zeilen sein darf. Natürlich ist es möglich, jede Funktion unter 10 Zeilen zu haalten aber wohl in dem Maße nicht sinnvoll. Aber wenn sie über 100 ist, dann läuft einfach was falsch, dann sollte man Teile in andere Funktionen auslagern, um
- mehr Übersichtlichkeit zu haben
- solche gelösten Teilaufgaben woanders wiederverwenden kann
- nicht komplett verrückt wirdDas ein Programm dadurch langsamer wird, ist natürlich völliger Blödsinn. Compilerbauer bist du mit Sicherheit nicht, denn fast jeder weiß es besser als du.
Preisfrage 1: Was ist eine Game Loop?
Willst du mich vergeigen?
Preisfrage 2: Was macht die Funktion QueryPerformanceCounter? (ein sperriger
Bezeichner, aber sehr aussagekräftig, wie ich meine)Ich weiß es. Ist das jetzt irgendwie toll?
Preisfrage 3: Was glaubt ihr, wieviele Codezeilen in C stecken in der wohl-
bekannten und vielgenutzten CreateWindowEx- Funktion?Wenn du Microsoft-Code als Vorbild nimmst, bist du verloren.
P.S. Nicht persönlich gemeint, aber du bist wirklich irgendwie seltsam. Du "lässt uns unseren Spaß" und merkst gar nicht, dass das hier fast alles gegen dich gerichtet ist - weil du Stuss erzählst.
Dass mittlerweile Aufrichtigkeit mit Grosskotzigkeit gleichgesetzt wird, ist sogar mir neu
Was hat deine Signatur mit aufrichtig zu tun? Gut, man muss es ja nicht gleich als großkotzig beschreiben, meine Reaktion war eher sowas wie "na und?", also nicht dramatisch.
Naja, ebenfalls nen schönen Abend.
@Mods: Bitte den Thread teilen! Ich möchte noch über code-style diskutieren.
-
imo geht ihr da alle zu ideologisch ran.
und Mecnels:
es sprechen alle von birnen und du stellst auf einmal fragen zu pflaumen. da soll einer schlau draus werden.