Was ist für euch guter Programmcode?
-
Optimizer schrieb:
Warum benutzt du eigentlich nicht containsKey(Object key)?
Da ist was dran.
Hab es gleich mal geändert.
Bezüglich der set-Geschichte dachte ich zwischendurch, dass du vielleicht den Rückgabetyp einiger Methoden in meiner Klasse meinst, die momentan eine List zurückliefern. Das wäre nicht so eine einfache Änderung, aber vielleicht sinnvoll. Was hälst du davon? Als Nachteil sehe ich eigentlich nur, dass Sets möglicherweise etwas rechenaufwändiger als Listen sind.
-
Ich halte mich nicht an die 80Zeichen ich nehme 90-95, das ist mit den meisten Auflösungen ohne Probleme anzuschauen und wenn wirklich jemand ne kleinere hat (wobei ich das bei nem Programmierer mal einfach bezweifel :p), dann muss er halt gelegentlich etwas scrollen
Wenn man natürlich in Umgebungen arbeitet wo der Code hauptsächlich über terminals bearbeitet wird sollte man es natürlich einhalten, aber warum sollte ich bei nem Programm mit GUI mich so auf diese 80Zeichen beschränken?
@Mecnel (hoffe ich hab den Namen richtig geschrieben):
Es gibt sicher auch mal größere Funktionen, z.B. ein switch-Statement wächst doch ziemlich schnell über die 10Zeilen hinaus und aus dem Grund macht es Sinn das switch-Statement in eine eigene Funktion auszulagern um den eigentlichen Code übersichtlich zu haltenKlassen sollen für gewöhlich auch eher in die breite und nicht in die Länge wachsen, aber dennoch gibt es einfach Klassen die einfach groß sind ohne, dass es sich ändern lässt. Zum Beispiel die BigInteger aus der Java API (~1000Zeilen groß).
Ich weiß ja jetzt nicht wie die Funktion CreateWindowEx intern aussieht aber ich kann mir vorstellen, dass die wirklich so groß sein muss, was aber eher am allgemeinen Design der Winapi liegt *g*
-
SirLant schrieb:
Klassen sollen für gewöhlich auch eher in die breite und nicht in die Länge wachsen[...]
Meinst du in Form von langen Parameterlisten? Halte ich für noch hässlicher als Klassen mit vielen Methoden.
-
MaSTaH schrieb:
SirLant schrieb:
Klassen sollen für gewöhlich auch eher in die breite und nicht in die Länge wachsen[...]
Meinst du in Form von langen Parameterlisten? Halte ich für noch hässlicher als Klassen mit vielen Methoden.
Neee... er meint bestimmt Zeilen, die 500 Zeichen lang sind.
-
simon.phoenix schrieb:
haltet ihr euch an die "78-zeichen pro zeile"?
Nope, natürlich wachsen meine Zeilen nicht bis ins Unendliche, aber ich mache den Umbruch mehr nach Gefühl. 78 Zeichen halte ich für übertrieben kurz.
-
MaSTaH schrieb:
SirLant schrieb:
Klassen sollen für gewöhlich auch eher in die breite und nicht in die Länge wachsen[...]
Meinst du in Form von langen Parameterlisten? Halte ich für noch hässlicher als Klassen mit vielen Methoden.
Längere Parameterlisten lassen sich aber manchmal nicht vermeiden.
z.b. Logon(server, user, pw, method)
dann noch hübsche "const std::string& bla" und schon muss man in die nächste Zeile um die 80 zeichen einzuhalten
-
simon.phoenix schrieb:
Längere Parameterlisten lassen sich aber manchmal nicht vermeiden.
z.b. Logon(server, user, pw, method)
dann noch hübsche "const std::string& bla" und schon muss man in die nächste Zeile um die 80 zeichen einzuhalten
Kannst ja irgendwelche Wrapper oder structs oder so nutzen.
-
simon.phoenix schrieb:
dann noch hübsche "const std::string& bla" und schon muss man in die nächste Zeile um die 80 zeichen einzuhalten
Ich meinte das eher auf die Anzahl der Parameter als auf die tatsächliche Länge (in Zeichen) bezogen.
Wenn man Parameterlisten à la WinAPI hat, dann sollte man sich IMHO Gedanken ums Design machen.
Ich habe für mich als grobe Faustregel gesetzt jede Funktion mit mehr als 4 Parametern zu überdenken. Wenn es sich wirklich nicht sinnvoll ändern lässt, dann sind auch mehr Parameter in Ordnung, bei mir aber eher die Ausnahme.
-
@simon
dafür kann man Zeilen umbrechenstruct foo { foo(std::string const &host, std::string const &user, std::string const &pwd, std::string const &method); };
find ich deutlich lesbarer, als eine Endloszeile.
-
kingruedi schrieb:
@simon
dafür kann man Zeilen umbrechenstruct foo { foo(std::string const &host, std::string const &user, std::string const &pwd, std::string const &method); };
find ich deutlich lesbarer, als eine Endloszeile.
Jo klar.
btw: Das nachgestellte const erschwert die Lesbarkeit (Gewöhnungsfaktor, dass man das const vorne an stellt). Finde ich
-
Bei BigInteger könnte man aber teile in nested classes auslagern. Dadurch wird natürlich nicht der Source der Klasse weniger, aber die Klasse selber trotzdem, was ja entscheidend ist -> man muss über weniger den Überblick behalten. Es geht immer was und sehr oft ist es sinnvoll, etwas möglichst klein zu halten.
Bezüglich der set-Geschichte dachte ich zwischendurch, dass du vielleicht den Rückgabetyp einiger Methoden in meiner Klasse meinst
Nein, das war irgendein krasser Gehirnfehler von mir. Vergiss das einfach *mich nicht darüber zu sprechen trau*
Was hälst du davon? Als Nachteil sehe ich eigentlich nur, dass Sets möglicherweise etwas rechenaufwändiger als Listen sind.
private List<ElementType> getValuesFromNodes(final List<Node> nodeList) { assert(nodeList != null); final LinkedList<ElementType> valueList = new LinkedList<ElementType>(); for (final Node node : nodeList) { valueList.add(node.getValue()); } return valueList; }
Hier zum Beispiel? Mit was für einem KeyType würdest du das Set dann austatten? Wenn ich mir die public Methoden von Eclipse anzeigen lassen, wird da immer nur Instanzen des ElementType gearbeitet. Du würdest auf jeden Fall irgendwas neues offenbaren.
Naja rechenaufwändiger als an ne doubly LinkedList 50 Dinger einzeln anzuhängen, ich weiß nicht.
-
simon.phoenix schrieb:
btw: Das nachgestellte const erschwert die Lesbarkeit (Gewöhnungsfaktor, dass man das const vorne an stellt). Finde ich
Nein, ein nachgestelltes const ist eigentlich logischer. Vorallem wenn du dir mal anguckst, wie man Member-Funktionen konstant macht.
-
Ich meinte mit in die breite eher im Sinne von vielen kleinen Klassen anstelle von einer rießigen Mammutklasse.
-
Der es besser weiss schrieb:
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!!!
Ja! Endlich ein Statement das den Nagel auf den Kopf trifft! Auch ein perfekt strukturierter Code ist wertlos, wenn er die Problemstellung nicht löst! Es führen bekanntlich viele Wege nach Rom!
@Shade: Ich hab mir Dein Tic Tac Toe jetzt einmal angeschaut. 20 oder mehr separate Quelldateien für so eine Mini-Aufgabe? Ist das nicht ein bisschen übertrieben? Um Mücken zu jagen, verwendet man doch auch nicht schwere Artillerie.
@Alle:
So, jetzt knall ich Euch einfach mal eine etwas anspruchsvollere Aufgabe auf den Tisch.
Ihr seid eine Firma, habt 2000 Mitarbeiter, auf Eurem Firmengelände gibt es 3000 Türen die sich mit 150 verschiedenen Schlüsseln aufsperren lassen. Ihr könnt es euch leisten und stellt jemanden ein, der die Vergabe der Schlüssel an die Mitarbeiter gegen Kaution sowie die Zurücknahme der Schlüssel von aus der Firma ausscheidenden Mitarbeitern sowie die Wiederauszahlung der Kaution mit Hilfe eines massgeschneiderten Datenbankprogrammes verwalten soll, ausserdem soll immer abfragbar sein, wieviele Exemplare eines der 150 Schlüsseltypen momentan vorrätig sind und wieviele sich momentan im Gewahrsam der Mitarbeiter befinden.
Ungefähr so erzählt ihr es dann einem Softwareentwickler, der ein entsprechendes, massgeschneidertes Datenbankprogramm entwickeln soll. Das Betriebssystem ist Windows2000.
Dann will er noch haben, dass die Daten bereits sortiert in die Datei geschrieben werden (asynchron natürlich, nur um es noch komplizierter zu machen), damit man die Datensätze später im Rekordtempo mit Binary Tee aus der Datei lesen kann.---
So, wo fangt ihr an, wenn zufällig Euch das Schicksal ereilt hätte, und Ihr müsstet jetzt diese Anwendung schreiben?
Denkt daran, dass ihr mit Eurem Konzept auch noch in einigen Tagen zurechtkommen müsst, wenn ihr mit Eurer Arbeit bereits weit fortgeschritten seid.Was das alles mit gutem oder schlechtem Programmcode zu tun hat? Sehr viel, denn wenn ich jetzt anfange, hunderte kleine Minimodule für jede simple kleine Setz- oder Leseoperation zu schreiben, dann verliere ich als Normalsterblicher mit hundertprozentiger Sicherheit innerhalb kürzester Zeit den Überblick über die Bezeichner für seine Funktionen!
Ihr werdet feststellen, dass Ihr Euch bei der Umsetzung von Aufgabenstellungen diesen Typs ziemlich schnell selber dabei ertappen werdet, hundertzeilige und ziemlich komplizierte Funktionen schreiben zu müssen.Es ist nur allzu logisch, dass der Umfang einer Funktion proportional zu der von ihr verlangten Mächtigkeit ist.
(Nur aus Neugierde, hat jemand von Euch schon einmal ein Projekt diesen Typs auf dem Tisch gehabt?)
-
Mecnels schrieb:
Was das alles mit gutem oder schlechtem Programmcode zu tun hat? Sehr viel, denn wenn ich jetzt anfange, hunderte kleine Minimodule für jede simple kleine Setz- oder Leseoperation zu schreiben, dann verliere ich als Normalsterblicher mit hundertprozentiger Sicherheit innerhalb kürzester Zeit den Überblick über die Bezeichner für seine Funktionen!
Du scheinst den Sinn von diesen vielen Aufspaltungen nicht ganz gerafft zu haben. Bessere Wartbarkeit und _Wiederverwendbarkeit_. Teile einer Funktion sind beschissen wiederzuverwenden, ganze Funktionen nicht. Außerdem wird die Übersichtlichkeit stark erhöht.
Und den Überblick über Bezeichner verliert man nur wenn man in einer 500 Zeilen-Funktion 87 lokale Variablen erzeugt hat
-
nichtsdestotrotz besteht der code einer funktion aus funktionsaufrufen oder trivialen handlungen.
du würdest wirklich die ganze problemstellung in, sagen wir mal, ein halbes dutzend funktionen packen? dann kannst du auch gleich alle funktionen sparen und alles ins hauptprogramm klatschen (überspitzt formuliert).
-
Was das alles mit gutem oder schlechtem Programmcode zu tun hat? Sehr viel, denn wenn ich jetzt anfange, hunderte kleine Minimodule für jede simple kleine Setz- oder Leseoperation zu schreiben, dann verliere ich als Normalsterblicher mit hundertprozentiger Sicherheit innerhalb kürzester Zeit den Überblick über die Bezeichner für seine Funktionen!
Ich nicht. Ich kann, wenn ich Code lese, mit einem viel aussagenden Funktionsaufruf wie sortList(list); mehr anfangen, als wenn ich das ausschreibe.
Dadurch behalte ich mehr Überblick, denn wenn ich nur wissen muss "aha, da wird die liste sortiert", dann bin ich froh, wenn ich den Code, der die Liste sortiert, gar nicht sehen muss, wenn mich die Sortierung selber gar nicht interessiert im Moment.
Und wenn man alles schön in Klassen kapselt hat man kein Problem damit, viele kleine Einzelteile zu haben.Ihr werdet feststellen, dass Ihr Euch bei der Umsetzung von Aufgabenstellungen diesen Typs ziemlich schnell selber dabei ertappen werdet, hundertzeilige und ziemlich komplizierte Funktionen schreiben zu müssen.
Natürlich ertappe ich mich dabei, wie meine Funktion immer länger wird. Und was mach ich dann? Ich sehe "aha, mit diesem Code lese ich erstmal die Konfiguration von irgendwas aus. Dann markier ich diesen Code, mache einen Rechtsklick, wähle aus dem Kontextmenü "Extract method" denk mir noch einen Namen wie readConfig() aus und dann steht statt den 50 Zeilen Code nur noch readConfig(); da und die 50 Zeilen stehen woanders. Das interessiert mich dann schon gar nicht mehr und ich kann an der ursprünglichen Funktion weitercoden und habe den Überblick. Denn readConfig(); sagt mir immer wieder recht schnell, was hier passiert.
-
Längere Parameterlisten lassen sich aber manchmal nicht vermeiden.
Doch. Man muss nur kreativ sein.
class CreateFoo { friend class Foo; public: CreateFoo & host (std::string const & newHost) { host_ = newHost; } CreateFoo & user (std::string const & newUser) { user_ = newuser; } CreateFoo & password (std::string const & newPassword) { password_ = newPassword; } CreateFoo & method (std::string const & newMethod) { method_ = newMethod; } private: std::string host_; std::string user_; std::string passwd_; std::string method_; }; class Foo { public: Foo (CreateFoo const &); ... };
Und dann kanste so ein Foo bauen:
Foo foo = CreateFoo() .host ("...") .user ("...") .password ("...") .method ("...");
Du kannst 'CreateFoo' sogar ein default-Konstruktor spendieren, der alles mit vernünftigen Vorlagen belegt. Auf die Weise kann man sogar beliebige Parameter bei der Definition auslassen, statt nur die letzten und man hat freie Wahl über die Reihenfolge. Es ist also nicht schlimm, wenn man sich mal nicht genau erinnert.
-
besserwisser schrieb:
nichtsdestotrotz besteht der code einer funktion aus funktionsaufrufen oder trivialen handlungen.
Simmt, also kann ich ihn zerlegen und übersichtlicher machen.
dann kannst du auch gleich alle funktionen sparen und alles ins hauptprogramm klatschen (überspitzt formuliert).
Nein, da hat das eine mit dem anderen nichts zu tun
-
Mecnels schrieb:
Ihr werdet feststellen, dass Ihr Euch bei der Umsetzung von Aufgabenstellungen diesen Typs ziemlich schnell selber dabei ertappen werdet, hundertzeilige und ziemlich komplizierte Funktionen schreiben zu müssen.
Es ist nur allzu logisch, dass der Umfang einer Funktion proportional zu der von ihr verlangten Mächtigkeit ist.
Andersherum wird ein Schuh draus. Dinge wie Modularisierung nach dem Prinzip "high cohesion, low coupling", Information Hiding, Datenkapselung, Layering, Dependency Inversion usw. werden mit zunehmender Komplexität der Aufgabe wichtiger nicht andersherum. Nicht umsonst sind alle diese Techniken Antwortversuche auf die zunehmende Komplexität von Software. Ein kleines Ein-Tag-Ein-Mann-Projekt kannst du völlig ohne Berücksichtigung solcher Mittel in eine große Funktion mit 60% globalen Variablen klatschen. Das geht, weil du das Programm vollständig und umfassend verstehst. Sobald dies aber nicht mehr gegeben ist, wird die Qualität der Abstraktion und Modularisierung entscheidend.
Nicht nur für die Verständlichkeit und Wartbarkeit des Programms sondern auch für die Möglichkeit arbeitsteilig daran zu entwickeln.(Nur aus Neugierde, hat jemand von Euch schon einmal ein Projekt diesen Typs auf dem Tisch gehabt?)
Nur aus Neugierde, hast du jemals irgendein Buch zum Thema Softwareentwicklung gelesen?