Was ist für euch guter Programmcode?
-
M.1946 schrieb:
Exceptions?
Alles kostet Zeit, so auch die Fehlerprüfung.Nur schade, dass Exception weniger runtime overhead haben als die ganzen ifs zur fehlerabfrage.
Fast überall muss Zeit gespart und optimiert werden.
Kennst du die 90-10 Regel?
(Und das Tolle an diesem Statement ist, dass ich es aus einem der Bücher zitiere, die ihr mir aufgeschwatzt habt, das ist also keine Besserwisserei meinerseits)
Oh, welches denn?
<vector> ohne Exceptions ist kein <vector>, sondern ein genau so schlecht implementierter Container, wie er jedem einfallen kann.
Begründung?
Welche Exception soll vector denn werfen? Es _kann_ ja nicht fehlschlagen.Meine Meinung - keine Belehrung.
Deine Meinung - keine Tatsachen.
-
Deine Schlussfolgerungen bzgl. Exceptions und anderer Dinge sind allesamt grundlegend falsch, weil sie sich auf diese Aussage stützen:
Fast überall muss Zeit gespart und optimiert werden.
Und die ist nicht korrekt. Tatsache ist: Nur an wenigen Stellen im Programm muss Zeit gespart und optimiert werden. Und überall woanders kann nahezu ohne Auswirkungen ohne schlechtes Gewissen tolle Features nutzen.
Und man rät auch nicht wild drauf los und benutzt deshalb keine Exceptions oder sonstwas, sondern man tut vielleicht mal eine Exception raus, wenn sich herausstellt, dass sie dort doch nicht so gut aufgehoben ist.
-
JBeni schrieb:
Ich hab mich mit Annotations noch nicht beschäftigt (ich hab nur von anderen gehört, dass das nichts weltbewegendes sei), aber das kommt in die ToDo-Liste
Die Auswirkungen von Annotations sind noch nicht wirklich abzusehen. Für kleine Projekte sind sie sicherlich relativ uninteressant, da wird man nicht viel mehr als ein @Override nutzen. Für große Projekte könnten sie einem aber vollkommen neue Möglichkeiten beim Programmieren eröffnen. Sie könnten zu einem deutlich deklarativeren Programmierstil führen und das ist in der Java-Welt äußerst weltbewegend. Von den neuen Sprachfeatures aus Java 1.5 könnten die Annotations für größere Projekte also das absolut relevanteste Sprachfeature sein: Viel wichtiger als Generics. Annotations wirken sich nicht als syntaktischer Zucker aus, indem sie etwas Code reduzieren können (wozu sie allerdings auf Dauer sicherlich auch genutzt werden) oder ein paar Casts eliminieren oder so. Stattdessen wirken sie sich auf das Design im Großen aus. ...wobei ich hier nicht @Override oder @Deprecated oder so meine: Mach dich bezüglich Annotations mal schlau und überleg dir dann mal, wofür man die gerade in Verbindung mit Reflection nutzen könnte. Vielleicht kommst du ja da drauf, was ich meine.
http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html
-
JBeni schrieb:
Hm, ich bin schon viele Stunden vor dem Debugger gesessen, aber an ein Fehler der durch das Überschreiben einer Variable/etc entstanden ist mag ich mich wirklich nicht erinnern (weder bei meinem Code, noch bei dem von anderen Leuten).
Das betrifft nicht nur das Überschreiben von Variablen. Es gibt auch andere Fehler, die dadurch frühzeitig erkannt werden. Zum Beispiel fällt es auf, wenn man vergißt, einer solchen Variablen/Konstanten in einem Konstruktor einen Wert zuzuweisen.
-
DrGreenthumb schrieb:
äh, wie war das... wenn man keine Ahung hat, ...
Begründung?
M.1946 schrieb:
Exceptions?
Alles kostet Zeit, so auch die Fehlerprüfung. Um die zusätzliche Sicherheit gewährleisten zu könnten, sind natürlich intern gewisse Abfragen nötig, die eben Zeit kosten. Und Zeit ist genau das, was man bei sehr vielen Anwendungen NICHT hat (bei Spielen schon gar nicht).Seltsam, ich hab schon einige Spiele gesehen, die mit Exceptions arbeiten. Dann machen die das ja alle falsch.
Natürlich kosten Exceptions Zeit, das tut die Abfrage von Rückgabewerten aber auch. Der theoretische Unterschied ist jedenfalls nicht vorhanden. Im Gegenteil, Exceptions tendieren zu einem besseren Laufzeitverhalten, weil der Compiler nunmal besser optimieren kann als du. Leider setzen das Compiler noch nicht wirklich gut um(ich kenn zumindest keinen).
Und niemand sagt, dass du Exceptions in zeitkritischen Situationen einsetzen musst. Aber gerade in Initialisierungsphasen sind sie sinnvoll, und dort ist Performance nur sekundär.
-
Mecnels schrieb:
Ist Euch eigentlich schon einmal aufgefallen, dass nicht ich die ganze Zeit Euch einreden will, was IHR in Euren Codes besser machen solltet, sondern genau umgekehrt
nuja, da gehen schonmal die Gemüter hoch, wenn man sich öfter mit solchen "int i,j,k,l,m;"-Quelltexten rumschlagen muss und dann ist da auf einmal jemand, der das auch nocht vehement verteidigt, worüber man sich selbst so oft ärgert.
Wir versuchen ja nur die Welt zu verbesserngroovemaster schrieb:
DrGreenthumb schrieb:
äh, wie war das... wenn man keine Ahung hat, ...
Begründung?
/usr/src/linux/Documentation
Aber dazu sag ich nichts mehr, ein Flame pro Thread reicht
-
bevor hier niemand mehr reinschaut möcht ich auch noch einen beitrag leisten.
hab vor ewigkeiten mal eine simulation zu ... hmm weiß nicht mehr genau, was das war.
hab in einem artikel etwas über diese simulation gelesen und wollte das nachprogrammieren. kommen hübsche bilder dabei raus.
naja, damit die löwen wieder was zu fressen haben#include <iostream> #include <cstdlib> #include <vector> #include "../sdlwrapper.h" //wen es interessiert, das ist noch was viel älteres und grässlicheres using namespace std; class ColorMapper { public: void add_color (unsigned i) { colors_.push_back(i); } void set_color (unsigned index, unsigned color) { colors_[index] = color; } unsigned colors () const { return colors_.size(); } unsigned operator [] (unsigned color) const { return colors_[color]; } private: std::vector<unsigned> colors_; }; class Field { public: explicit Field (unsigned color = 0) : color_(color) {} void change_color () { ++color_; } void reset_color () { color_ = 0; } unsigned color () const { return color_; } private: unsigned color_; }; class World; class WorldView { public: WorldView (World &world); virtual void draw () = 0; virtual void update (int x, int y) = 0; World &world () const { return world_; } private: World &world_; }; class World { public: enum { X = 800, Y = 800 }; int length () const { return World::X; } int height () const { return World::Y; } World (WorldView *view = 0) : view_(view) {} WorldView *view () const { return view_; } void view (WorldView *view) { view_ = view; } void change_color (int x, int y) { fields[x][y].change_color(); assert(view_); view_->update(x,y); } unsigned color (int x, int y) const { return fields[x][y].color(); } private: WorldView *view_; Field fields[X][Y]; }; WorldView::WorldView (World &world) : world_(world) { world.view(this); } enum Directions { Up=0, Right=1, Down=2, Left=3 }; class Ant { Directions direction; World &w_; int x_, y_; public: Ant (World &w, int x, int y) : w_(w), x_(x), y_(y) {} virtual void step () = 0; virtual ~Ant () {} public: void move_left () { rotate_counterclockwise(); move(); } void move_right () { rotate_clockwise(); move(); } protected: int get_x () const { return x_; } int get_y () const { return y_; } int color () const { return w_.color(x_,y_); } void change_color () const { w_.change_color(x_,y_); } void rotate_clockwise () { direction = Directions((direction+1)%4); } void rotate_counterclockwise () { direction = Directions(direction-1<0 ? 3 : direction-1); } void move (int i = -1) { //wow, was hab ich hier gemacht? Directions direction = this->direction; if (i != -1) { direction = Directions(i); } switch (direction) { case Up: y_ = y_==0 ? World::Y-1 : y_-1; break; case Down: y_ = y_+1==World::Y ? 0 : y_+1; break; case Left: x_ = x_==0 ? World::X-1 : x_-1; break; case Right: x_ = x_+1==World::X ? 0 : x_+1; } } }; class SDLView : public WorldView { public: SDLView (const ColorMapper &color_map, World &world) : WorldView (world), color_map_(color_map) {} void draw (); void update (int,int); private: ColorMapper color_map_; }; void SDLView::draw () { for (int x = 0; x < world().length(); ++x) { for (int y = 0; y < world().height(); ++y) { sdl::Screen::get_screen().put_pixel(x, y, color_map_[world().color(x,y)%color_map_.colors()]); } } sdl::Screen::get_screen().sync(); } void SDLView::update (int x, int y) { sdl::Screen::get_screen().put_pixel(x, y, color_map_[world().color(x,y)%color_map_.colors()]); } #ifdef R Syntax Error #endif #ifdef L Syntax Error #endif #define R &Ant::move_right #define L &Ant::move_left void (Ant::*functions[]) () = { R,L }; //damit mütter den code leichter handhaben können ;) #undef R #undef L class RLAnt : public Ant { public: RLAnt (World &w, int x, int y) : Ant(w,x,y) {} void step () { int c = color(); change_color(); (this->*functions[c%(sizeof(functions)/sizeof(*functions))])(); } }; int main () { srand(time(0)); sdl::SDL::initialize (sdl::Video); sdl::Screen &screen = sdl::Screen::get_screen (World::X, World::Y, 16); ColorMapper color_map; color_map.add_color (screen.mapRGB(255,255,255)); color_map.add_color (screen.mapRGB(0,0,0)); color_map.add_color (screen.mapRGB(255, 0,0)); color_map.add_color (screen.mapRGB(0, 255,0)); World world; SDLView view(color_map, world); RLAnt ant(world, World::X/2, World::Y/2); view.draw(); SDL_Event event; int count = 0; for (bool loop = true; loop; ++count) { while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_QUIT: loop = false; break; case SDL_KEYDOWN: loop = false; break; } } ant.step(); if (count % 200 == 0) { screen.sync(); } } SDL_SaveBMP (screen.handle(), "out.bmp"); }
ist aber schon um einiges älter, aber soviel code hab ich im moment leider nicht (jaja, backups...)
wenn jemand wissen will, wie die bilder aussehen, schau ich mal, ob ich den code für den sdl_wrapper noch irgendwo finde...
ach und bitte vergesst main, darum hab ich mich nicht mehr gekümmert.
-
DrGreenthumb schrieb:
/usr/src/linux/Documentation
Aber dazu sag ich nichts mehr, ein Flame pro Thread reichtHast du dir die Beiträge überhaupt durchgelesen? Es ging um Windows, nicht um Linux. Zudem hab ich kein Linux, kann also im angegebenen Verzeichnis auch nicht nachschaun. Da musst du schon konkret werden, wenn du sinnvolle Argumente bringen willst.
-
void set_color (unsigned index, unsigned color) { colors_[index] = color; }
da mach ich gerne ein assert()
unsigned colors () const { return colors_.size(); }
uU zweideutig? colors() könnte ja auch das array returnen...
World &world () const { return world_; }
Das mag ich nicht: World &world
ein World *p;
ist OK, weil man sagen kann, dass * zur variablen gehört
aber bei einer funktion kann ich mir das nur schwer vorstellenWorld (WorldView *view = 0) : view_(view) {} WorldView *view () const { return view_; } void view (WorldView *view) { view_ = view; }
Soll man wirklich das view beliebig setzen können?
das ist doch nur wegen dem WorldView da, oder?
Directions direction; World &w_; int x_, y_;
unterstricht bei direction vergessen
void move (int i = -1) { //wow, was hab ich hier gemacht? Directions direction = this->direction; if (i != -1) { direction = Directions(i); } switch (direction) { case Up: y_ = y_==0 ? World::Y-1 : y_-1; break; case Down: y_ = y_+1==World::Y ? 0 : y_+1; break; case Left: x_ = x_==0 ? World::X-1 : x_-1; break; case Right: x_ = x_+1==World::X ? 0 : x_+1; } }
Das frage ich mich auch
und deshalb sag ich nix dazu
SDLView::draw () { for (int x = 0; x < world().length(); ++x) { for (int y = 0; y < world().height(); ++y) { sdl::Screen::get_screen().put_pixel(x, y, color_map_[world().color(x,y)%color_map_.colors()]); } } sdl::Screen::get_screen().sync(); }
Oh, fäält mir erst jetzt auf: world.length und world.height? warum nicht width statt length?
#ifdef R Syntax Error #endif #ifdef L Syntax Error #endif
??
wenn schon error, dann geht doch #error
aber warum nicht einfach "umdefinen" und nachher zurück definen?#define R &Ant::move_right #define L &Ant::move_left void (Ant::*functions[]) () = { R,L }; //damit mütter den code leichter handhaben können ;) #undef R #undef L
uU könnte man bei World X und Y doch etwas dynamischer gestalten, sonst bringt sich das ableiten davon ja nicht so viel,
wenn ich immer 800x600 machen mussbis auf move() und dem R und L Ding ists aber nice
-
@Gregor
Werde mir die Annotations mal vornehmen, wenn du davon so schwärmst.Zu "final"
Gregor schrieb:
Das betrifft nicht nur das Überschreiben von Variablen. Es gibt auch andere Fehler, die dadurch frühzeitig erkannt werden. Zum Beispiel fällt es auf, wenn man vergißt, einer solchen Variablen/Konstanten in einem Konstruktor einen Wert zuzuweisen.
Ich hab keine Argumente die gegen final sprechen, allerdings finde ich deine Argumentation auch nicht überzeugender.
Ich hab noch nie jemanden gesehen, der so oft von ihnen Gebrauch macht wie Du. Hast Du damit wirklich schonmal einen Fehler entdeckt, oder ist das eher eine Tradition (von einem Prof oder so...)?
Bisher konnte ich ohne final ganz gut überleben.
-
Ich verwende final auch sehr oft. Bei Datenelementen sowieso, damit kann man auch durchaus ganz gut Fehler früher feststellen.
Bei lokalen Variablen mache ich es je nach Übersichtlichkeit. Wenn eine Methode etwas länger ist und ich einer Variable je nach Bedingung einen anderen Wert gebe, kann ich damit gut sicherstellen, dass sie nur genau einmal einen Wert kriegt.
-
groovemaster schrieb:
Hast du dir die Beiträge überhaupt durchgelesen? Es ging um Windows, nicht um Linux.
Naja, Du hast da irgendwas geredet von wegen "Nicht jedes Betriebssystem bringt Schnittstellen für Treiber mit", das hat er damit für Linux eigentlich recht wirkungsvoll entkräftet.
Zudem hab ich kein Linux, kann also im angegebenen Verzeichnis auch nicht nachschaun. Da musst du schon konkret werden, wenn du sinnvolle Argumente bringen willst.
In diesem Verzeichnis befindet sich die Dokumentation von Linux, auch zu massig Treiber-spezifischen Themen, die allesamt Deine Aussage widerlegen.
Aber ich möchte das hier ebenfalls nicht zu einem WindowsVsLinux-Thread machen; wenn Du weitere Fragen hast, dann stell sie am besten einfach in einem neuen Thread.
-
JBeni schrieb:
Ich hab noch nie jemanden gesehen, der so oft von ihnen Gebrauch macht wie Du. Hast Du damit wirklich schonmal einen Fehler entdeckt, oder ist das eher eine Tradition (von einem Prof oder so...)?
Bisher konnte ich ohne final ganz gut überleben.Das ist eine prinzipielle Sache, die in erster Linie von mir selbst ausgeht. Es ist ziemlich irrelevant, wieviele Fehler ich damit schon gefunden habe. Ich nutze jetzt auch Generics, obwohl ich früher nie Casting-Probleme ohne die Generics hatte. Früher oder später gibt es immer einen Fehler, der mit solchen Dingen rechtzeitig gefunden wird, warum sollte man also darauf verzichten? Es bietet einfach keine Nachteile (wenn man mal von 5 mehr Zeichen in der Zeile absieht) und man kann damit eine Fehlerklasse von vornherein ausschließen.
-
In welchem Kontext und nach welchen zuvor stattgefundenen Initialisierungen Du die Funktion überhaupt aufrufen darfst, wenn Du schwere Systemfehler verhindern willst? Nein.
(Wir sehen davon ab, dass das irgendwie nicht nach einem normalen deutschen Satz klingt.)
Solche Probleme hatte ich auch gelegentlich. Sowas ist hart. Da stizt man echt Ewigkeiten, bis man endlich eine Lösung gefunden hat, damit es solche Funktionen, die nur unter bestimmten Vorraussetungen aufrufen kann, nicht mehr gibt.
Aber Funktionen, bei denen dann als Kommentar steht: "mach erst dann, dann dies, dann jendes und dann einen Kopfstand und wenn dann auch nocht Dienstang und Vollmond ist, darfste sie vielleicht auch mal aufrufen", sind nicht akzeptable.
-
Du hast den Sack Reis vergessen, der noch umfallen muss.
-
Optimizer schrieb:
Du hast den Sack Reis vergessen, der noch umfallen muss.
Da habt ihr völlig recht, so eine Funktion denk ich mir als nächstes aus, die nur dann aufgerufen werden darf, wenn erst ein Sack Reis umgefallen ist.
Aber der Sack Reis wird natürlich in Direct3D animiert
ob ihr es glaubt oder nicht sogar solche Funktionen kann man sich ausdenken
-
nman schrieb:
Naja, Du hast da irgendwas geredet von wegen "Nicht jedes Betriebssystem bringt Schnittstellen für Treiber mit"
Bitte?
Wo soll ich denn sowas gesagt haben? Obwohl das für bstimmte BS teilweise zutrifft (zB DOS), das ist aber ein anderes Thema.
Ich hab lediglich gesagt, dass in der Treiberschnittstelle auch Arbeit steckt. Das ist nicht in ein paar Stunden gemacht. Und das bezog sich auf folgende AussageROFL schrieb:
Glaubst DU bei Windows war das schon immer so? Soundkarte rein, Plug'n Play und alles klappt? Das ist kein Verdienst der MS Programmierer, sondern der Hardware Industrie!
Sowas ist ein geben und nehmen. Da kann imo keiner die Lorbeeren für sich selbst beanspruchen. Soviel zum Thema... aber es ging ja eigentlich um was anderes, also offtopic.close().
-
groovemaster schrieb:
Bitte?
Wo soll ich denn sowas gesagt haben?
Keine Ahnung, aber bei einem 27-Seiten-Thread mag ich jetzt nicht suchen müssen.
-
Pfff, Weichei. Ich hab schon längere Flame-Threads verursacht.
-
nman schrieb:
Keine Ahnung, aber bei einem 27-Seiten-Thread mag ich jetzt nicht suchen müssen.
Musst du auch nicht, denn du wirst diesbezüglich nix finden.