Was ist für euch guter Programmcode?



  • MecnelsNichtEingeloggt schrieb:

    1.) Verwende keine defines, denn es ist nicht sinnvoll, das gesamte äußere Erscheinungsbild einer Anwendung einfach dadurch verändern zu können, dass man den symbolischen Konstanten andere Werte gibt. Besser ist es, an hundert verschiedenen Positionen irgendwo in hunderten Modulen die tatsächlichen Werte hinzuschreiben

    Verarscht du mich?

    2.) Funktionen sollten ihrem Aufrufer generell keine Auskunft darüber geben, ob während ihrer Ausführung irgend welche Fehler aufgetreten sind, darum sollte man vor allem keine bool Werte zurückgeben,

    Weil es Exception gibt?

    3.) Verwende keine Zeiger auf Zeiger, denn ... warum eigentlich? Ach ja, das spart nämlich sehr viel Speicher und das ist <template Begruendung bitte> auch nicht gut.

    Man würde natürlich nie irgendetwas wrappen, damit es leichter verwendbar ist, oder?

    4.) Als Elementfunktionen überladene arithmetische Operatoren sind nicht gut. Die sind nämlich zu wenig fehleranfällig, besser du überlädst sie global und lässt dich davon überraschen, was unter Mitwirkung Deiner Konvertierungskonstruktoren oft an interessanten Ergebnissen dabei heraus kommt.

    Lies bei zeiten mal ein C++ Buch. Wie etwa Effective C++ oder ähnliches.

    (ach und explicit ist zwar alles andere Plattformunabhängig, aber wer braucht das schon bei Klassen für mathematische Objekte? Sind ja sowieso alle Plattformspezifisch).

    Ok, du verarscht mich.
    Falls du der echte bist (bitte demnächst durch einloggen bestätigen/widerlegen) beende ich die Diskussion mit dir. Denn verarschen lasse ich mich nicht.

    --- Ein Projekt kann man frontal angehen, also einfach drauflosprogrammieren,
    --- wenn einem der Code in einer Funktion zu lang wird, einen Funktionsnamen
    --- dafür erfinden, weiterprogrammieren, wieder einen Funktionsnamen erfinden
    --- und so weiter und so fort. Irgendwann hat man dann hunderte Funktionen,
    --- wahrscheinlich auch eine Lösung für das Problem, und kann sogar von
    --- Modularisierung sprechen.

    --- Oder man kann es aus simplen Bausteinen wie etwa Vektoren, Feldern,
    --- Spielsteinen etc., die alle Elemente des Programmes sind, allmählich zu
    --- einem Ganzen zusammenfügen. Und letzteres heisst dann objektorientiert.

    *lol* muss ich das echt kommentieren?
    Ich kann bei mir in der Arbeit jeden fragen den ich will, die Antwort wird sein: kleine Funktionen, kleine Module mit kleinen öffentlichen Schnittstellen sind wesentlich wartbarer als ein paar monster funktionen.
    Hier in dem Forum sind auch so ziemlich alle meiner Meinung (es gab noch keine Gegenstimme)

    Denk bei zeiten mal darüber nach.

    Natürlich heißt dass es alle so machen nicht, dass es richtig ist. Aber man sollte die Gründe überlegen warum so viele Leute soviel zeit dafür opfern kompakte Funktionen und Module zu entwickeln, wenn es doch einfacher und besser wäre ohne plan alles in eine Funktion zu stecken...



  • MecnelsNichtEingeloggt schrieb:

    1.) Verwende keine defines, denn es ist nicht sinnvoll, das gesamte äußere Erscheinungsbild einer Anwendung einfach dadurch verändern zu können, dass man den symbolischen Konstanten andere Werte gibt. Besser ist es, an hundert verschiedenen Positionen irgendwo in hunderten Modulen die tatsächlichen Werte hinzuschreiben, denn wenn man dann dahinter kommt, dass die Textgroesse doch um 2 logische Einheiten größer sein soll, dann hat man das Vergnügen, dutzende Dateien durchsuchen zu müssen und den Wert eben hundertmal ausbessern zu dürfen, und das gleiche nochmal, wenn doch die kleiner Textgröße gereicht hätte. So schlägst du wenigstens Stunden an Zeit tot, was zwar mit define nicht nötig gewesen wäre (da hätte es gereicht den einen Wert daneben auszubessern), aber

    das hat keiner gesagt, du sollst "const int GROESSE = 100;" schreiben statt "#DEFINE GROESSE 100". den vorteil solltest du als erfahrener hase doch sofort erkennen.

    MecnelsNichtEingeloggt schrieb:

    2.) Funktionen sollten ihrem Aufrufer generell keine Auskunft darüber geben, ob während ihrer Ausführung irgend welche Fehler aufgetreten sind, darum sollte man vor allem keine bool Werte zurückgeben, denn dann könnte man ja womöglich den Fehler bei Probeläufen sofort entdecken. Es macht einfach mehr Spaß, in einem großen Programm unter hunderten schweigenden Minifunktionen einen Fehler finden zu müssen.

    das hat keiner gesagt, du sollst exceptions verwenden. die sind dafür gemacht.

    MecnelsNichtEingeloggt schrieb:

    3.) Verwende keine Zeiger auf Zeiger, denn ... warum eigentlich? Ach ja, das spart nämlich sehr viel Speicher und das ist <template Begruendung bitte> auch nicht gut.

    das hat keiner gesagt, du sollst std::vector o.ä. container verwenden um schwer auffindbare fehler zu vermeiden.

    MecnelsNichtEingeloggt schrieb:

    4.) Als Elementfunktionen überladene arithmetische Operatoren sind nicht gut. Die sind nämlich zu wenig fehleranfällig, besser du überlädst sie global und lässt dich davon überraschen, was unter Mitwirkung Deiner Konvertierungskonstruktoren oft an interessanten Ergebnissen dabei heraus kommt. Ist einfach zu lustig (ach und explicit ist zwar alles andere Plattformunabhängig, aber wer braucht das schon bei Klassen für mathematische Objekte? Sind ja sowieso alle Plattformspezifisch).

    hä? "ich weiß irgendwas nicht genau, evtl. hatte ich unrecht, also behaupte ich einfach irgendwas" oder wie?



  • Shade Of Mine schrieb:

    MecnelsNichtEingeloggt schrieb:

    1.) Verwende keine defines, denn es ist nicht sinnvoll, das gesamte äußere Erscheinungsbild einer Anwendung einfach dadurch verändern zu können, dass man den symbolischen Konstanten andere Werte gibt. Besser ist es, an hundert verschiedenen Positionen irgendwo in hunderten Modulen die tatsächlichen Werte hinzuschreiben

    Verarscht du mich?

    2.) Funktionen sollten ihrem Aufrufer generell keine Auskunft darüber geben, ob während ihrer Ausführung irgend welche Fehler aufgetreten sind, darum sollte man vor allem keine bool Werte zurückgeben,

    Weil es Exception gibt?

    3.) Verwende keine Zeiger auf Zeiger, denn ... warum eigentlich? Ach ja, das spart nämlich sehr viel Speicher und das ist <template Begruendung bitte> auch nicht gut.

    Man würde natürlich nie irgendetwas wrappen, damit es leichter verwendbar ist, oder?

    4.) Als Elementfunktionen überladene arithmetische Operatoren sind nicht gut. Die sind nämlich zu wenig fehleranfällig, besser du überlädst sie global und lässt dich davon überraschen, was unter Mitwirkung Deiner Konvertierungskonstruktoren oft an interessanten Ergebnissen dabei heraus kommt.

    Lies bei zeiten mal ein C++ Buch. Wie etwa Effective C++ oder ähnliches.

    (ach und explicit ist zwar alles andere Plattformunabhängig, aber wer braucht das schon bei Klassen für mathematische Objekte? Sind ja sowieso alle Plattformspezifisch).

    Ok, du verarscht mich.
    Falls du der echte bist (bitte demnächst durch einloggen bestätigen/widerlegen) beende ich die Diskussion mit dir. Denn verarschen lasse ich mich nicht.

    --- Ein Projekt kann man frontal angehen, also einfach drauflosprogrammieren,
    --- wenn einem der Code in einer Funktion zu lang wird, einen Funktionsnamen
    --- dafür erfinden, weiterprogrammieren, wieder einen Funktionsnamen erfinden
    --- und so weiter und so fort. Irgendwann hat man dann hunderte Funktionen,
    --- wahrscheinlich auch eine Lösung für das Problem, und kann sogar von
    --- Modularisierung sprechen.

    --- Oder man kann es aus simplen Bausteinen wie etwa Vektoren, Feldern,
    --- Spielsteinen etc., die alle Elemente des Programmes sind, allmählich zu
    --- einem Ganzen zusammenfügen. Und letzteres heisst dann objektorientiert.

    *lol* muss ich das echt kommentieren?
    Ich kann bei mir in der Arbeit jeden fragen den ich will, die Antwort wird sein: kleine Funktionen, kleine Module mit kleinen öffentlichen Schnittstellen sind wesentlich wartbarer als ein paar monster funktionen.
    Hier in dem Forum sind auch so ziemlich alle meiner Meinung (es gab noch keine Gegenstimme)

    Denk bei zeiten mal darüber nach.

    Natürlich heißt dass es alle so machen nicht, dass es richtig ist. Aber man sollte die Gründe überlegen warum so viele Leute soviel zeit dafür opfern kompakte Funktionen und Module zu entwickeln, wenn es doch einfacher und besser wäre ohne plan alles in eine Funktion zu stecken...

    #defines haben ihre Vorteile und ihre Nachteile.
    Konstanten haben ihre Vorteile und ihre Nachteile.
    Was man nimmt ist Geschmackssache, mir sind #defines lieber,
    Dir vielleicht Konstanten, aber wie gesagt, egal.
    Ich hab den Zynismus vielleicht ein bisschen zu weit getrieben, sorry.

    Wie man Operatoren überlädt ist ebenfalls von der Aufgabe abhängig,
    die man damit lösen soll. Wenn Vektoren im Spiel sind, ist es meiner
    Meinung besser, Elementfunktionen zu nehmen, Du bevorzugst globale
    Operatoren und baust lieber explicit Constructors ein. Schon wieder:
    Nur Geschmackssache. Viele Wege führen nach Rom, nur mein Ansatz ist
    wahrscheinlich bequemer und weniger fehleranfällig. Aber wie gesagt -
    nur meine Meinung.

    bool Rückgabe vs Exceptions: Exceptions sollten in krassen Ausnahmefällen zum Einsatz kommen (Ein Speichermedium existiert nicht und es wird versucht, darauf zu schreiben, um ein Beispiel zu nennen), aber wohl nicht, um Abkürzungen zu anderen Programmteilen zu nehmen. Das erinnert an Basic und Goto. Meine Meinung, darum schweigen meine Funktionen nicht darüber, ob sie eine Operation erfolgreich beenden konnten, sondern lassen es den Aufrufer mit true oder false wissen. Wieder: Geschmackssache. Rückgabewerte für Fehler ist die ältere Methode, aber sicher nicht schlechter (eher bewährter).

    Zeiger auf Zeiger: Nicht jeder kommt mit der Zeigerarithmetik zu recht, dabei ist es doch so simpel. Wenn sie Dir aber zu kompliziert sind, dann kannst Du angesichts der heutzutage zur Verfügung stehenden Hauptspeichergrößen natürlich auch jedes Objekt extra im Speicher anlegen. Dieser Umgang mit dem Hauptspeicher wäre vor 20 Jahren katastrophal gewesen, und auch heute gibt es Anwendungen, in denen das nicht egal ist (aber die haben wahrscheinlich etwas mit der NASA oder ähnlichen abstrusen Vereinen zu tun).

    Sollte ich Dir mit meiner letzten Post zu sehr auf den Schlips getreten sein, so musst Du schon zugeben, dass das angesichts Deiner Kommentare zu meinen Posts nicht von ungefähr gekommen ist. Trotzdem - war nicht böse gemeint.

    Viele kleine Bausteine verknüpft mit Logik ergeben ein geordnetes Ganzes.
    --- ein bekannter Kybernetiker der 60er Jahre_Vordenker der Objektorientierung

    Gute Nacht.



  • Kann es sein das dieser Mecnels ein Troll ist und alle ihn abfüttern?



  • Vielleicht wäre es aber mal an der Zeit sich von seinen "bewährten" Verfahren zu lösen und Neuland zu betreten?

    Kannst Du mal kurz erklären, warum Deine überladenen Operatoren Members sein sollen? Dann hast Du die implizite Konvertierung sofern nicht durch explicit unterdrück ja immer noch, halt auf dem rechten Argument. Das heißt a+b funktioniert dann, aber b+a nicht... das klingt irgendwie nicht so wirklich sinnvoll, oder?
    Und wenn Du das verhinderst indem Du den Konstruktor explicit machst... dann sehe ich nicht was es bringen soll, das als Member zu machen.



  • #defines haben ihre Vorteile und ihre Nachteile.
    Konstanten haben ihre Vorteile und ihre Nachteile.
    Was man nimmt ist Geschmackssache, mir sind #defines lieber,
    Dir vielleicht Konstanten, aber wie gesagt, egal.
    Ich hab den Zynismus vielleicht ein bisschen zu weit getrieben, sorry.

    Du hast wirklich noch kein C++ Buch gelesen. Meyers, Effective C++, Die erste Richtlinie überhaupt.

    Das erinnert an Basic und Goto.

    Das was du tust, erinnert daran 👎

    Rückgabewerte für Fehler ist die ältere Methode, aber sicher nicht schlechter (eher bewährter).

    Starrsinn³

    wäre vor 20 Jahren katastrophal gewesen

    Ich denke dieser Satz ist bezeichnend für deinen ganzen tollen Programmierstil...



  • Mecnels schrieb:

    #defines haben ihre Vorteile und ihre Nachteile.
    Konstanten haben ihre Vorteile und ihre Nachteile.
    Was man nimmt ist Geschmackssache, mir sind #defines lieber,
    Dir vielleicht Konstanten, aber wie gesagt, egal.

    naja, welche vorteile haben denn symbolische konstanten gegenüber echten? daß man die typsicherheit umgeht oder was? sag mal, da bin ich echt gespannt, was ich alles verpaßt habe, seit ich kein #define mehr verwende...

    Mecnels schrieb:

    Viele kleine Bausteine verknüpft mit Logik ergeben ein geordnetes Ganzes.

    ist absolut richtig. dein problem dabei ist, daß du unfähig bist, diese alte erkenntnis auf die programmierung mit c++ anzuwenden. denn jeder der vielen kleinen bausteine ist entweder klasse oder funktion. in dem moment, in dem du eine funktion lauter verschiedene sachen selbst erledigen läßt, hast du aber eben nicht viele kleine bausteine, sondern wenige klobige. siehst du das denn nicht selber?!?



  • Jester schrieb:

    Vielleicht wäre es aber mal an der Zeit sich von seinen "bewährten" Verfahren zu lösen und Neuland zu betreten?

    Kannst Du mal kurz erklären, warum Deine überladenen Operatoren Members sein sollen? Dann hast Du die implizite Konvertierung sofern nicht durch explicit unterdrück ja immer noch, halt auf dem rechten Argument. Das heißt a+b funktioniert dann, aber b+a nicht... das klingt irgendwie nicht so wirklich sinnvoll, oder?
    Und wenn Du das verhinderst indem Du den Konstruktor explicit machst... dann sehe ich nicht was es bringen soll, das als Member zu machen.

    Der eigentliche Punkt ist dass ein Konvertierungskonstruktor Zahl->Vektor für einen Vektor schon unsinnig ist, ob jetzt explicit oder nicht spielt da keine Rolle. In Anbetracht dessen ist es VÖLLIG EGAL ob das + jetzt Elementfunktion oder global ist, und mir deshalb die Kritik an der Implementierung als Elementfunktion sehr suspekt (weil wieder einmal kritisiert wurde ohne zu überlegen). Zahl und Vektor haben soviel gemeinsam wie Auto und Regenwurm, und niemand konvertiert Autos in Regenwürmer.
    😃



  • Mecnels schrieb:

    #defines haben ihre Vorteile und ihre Nachteile.
    Konstanten haben ihre Vorteile und ihre Nachteile.

    Vorteile von #defines wären?
    zB in effective C++ super nachlesbar warum #define hier nur nachteile hat (betonung auf _nur_)

    Wie man Operatoren überlädt ist ebenfalls von der Aufgabe abhängig,
    die man damit lösen soll. Wenn Vektoren im Spiel sind, ist es meiner
    Meinung besser, Elementfunktionen zu nehmen, Du bevorzugst globale
    Operatoren und baust lieber explicit Constructors ein. Schon wieder:
    Nur Geschmackssache. Viele Wege führen nach Rom, nur mein Ansatz ist
    wahrscheinlich bequemer und weniger fehleranfällig. Aber wie gesagt -
    nur meine Meinung.

    Klar, dein Ansatz ist besser 😉
    Dein Problem ist doch: wenn der Ctor nicht explicit ist, hast du nicht nur beim op+ diese Konvertierungsprobleme, sondern bei Funktionsaufrufen auch.

    Natürlich macht es in dieser Situation keinen großen Unterschied, aber es hat keinen Vorteil den op+ als member zu deklarieren, es bricht nur die konsistenz.

    Oder willst du mir nochmal genau erklären warum der op+ member sein muss?

    Wenn wir von

    struct C
    {
      C(int) {}
    };
    

    ausgehen. Dann könnte man bei einem op+ als member
    1+C() nicht schreiben, wohl aber
    C()+1
    was doch etwas komisch ist, oder?
    wäre der Ctor explicit, könnte man keins der beiden schreiben.
    wenn wir nun aber den op+ als non member definieren, kann man
    1+C() und C()+1 schreiben, sofern der Ctor nicht explicit ist und keins von beiden, wenn er es nicht ist.

    dein vektor kann nicht umwandeln, weil er keinen umwandlungskonstruktor hat.

    Und nun ekläre mir den vorteil von einem op+ als member.
    Umwandlung zählt nicht, weil ich das gerade widerlegt habe.

    Mein grund warum man ihn non member machen sollte: konsistenz

    bool Rückgabe vs Exceptions: Exceptions sollten in krassen Ausnahmefällen zum Einsatz kommen

    Nein, bei jeder Art von Ausnahme. Sonst würde sie ja fatalError und nicht Exception heißen.

    darum schweigen meine Funktionen nicht darüber, ob sie eine Operation erfolgreich beenden konnten, sondern lassen es den Aufrufer mit true oder false wissen.

    Exception schweigen auch nicht, und sind einer C mäßigen fehlerbehandlung technisch überlegen.
    Soll ich die technischen Vorteile aufzählen?

    Andererseits hat dein bool ein Problem: der Call hat keine Ahnung was passiert ist. Das ist doch ein gravierendes Problem, oder etwa nicht?

    Wenn wir jetzt davon ausgehen, dass eine Funktion "DisplayScene" welche die ganze Ausgabe auf den Bildschirm rendern sollte einfach false liefert - was macht der caller dann?

    Es kann an soviel liegen, lost surface? kein speicher mehr? illegale parameter beim aufruf? sonst was?
    er weiß es nicht.
    Also wären zumindest integer recht praktisch, damit der caller irgendwie reagieren kann.

    Wie lautet deine Begründung warum der caller nicht auf fehler reagieren darf? Oder speicherst du dann den fehlercode errno mäßig in einer externen variablen?

    Zeiger auf Zeiger: Nicht jeder kommt mit der Zeigerarithmetik zu recht, dabei ist es doch so simpel. Wenn sie Dir aber zu kompliziert sind, dann kannst Du angesichts der heutzutage zur Verfügung stehenden Hauptspeichergrößen natürlich auch jedes Objekt extra im Speicher anlegen.

    Verarsch mich bitte nicht.
    Ich rede nicht von vector<vector<int> > weil das klar arsch lahm ist.
    Ich rede von einem wrappen um diese Zeiger, weil es einfach leichter zu verwenden ist.
    Und komm mir nicht mit "ich versteh zeiger arithmetik nicht". Aber vergleiche mal den Aufwand beim Speichermanagement von einem Type** mit dem von einem Wrapper.
    Man schreibt diesen Wrapper einmal und hat ihn immer - nie mehr speicherprobleme.
    weiters wird der code ausgelagert, es ist doch für deinen Code egal wie du zu dem element [x][y] kommst, also pack es in eine externe Funktion.
    Dann kann man die Repräsentation später noch ändern.

    In C++ gibt es das schöne: zero cost principle
    So ein wrapper ist in C++ gratis. er kostet keine performance.

    Dieser Umgang mit dem Hauptspeicher wäre vor 20 Jahren katastrophal gewesen,

    Ich glaube du willst nicht lesen was ich schreibe, oder es versuchen zu verstehen.

    Niemand sagt, du sollst ineffizient programmieren. Aber Zeiger auf Zeiger kann man auch anders lösen (ohne dauernd neue Objekt zu erstellen) weil es die Erfindung von Wrappern gibt.

    Zeiger sind doch keine Magie. Sie zeigen einfach auf ein Objekt. Diese Objekte brauchen Platz. Logisch. Nur wenn ich die Zeiger schön wrappe, wo sollte da der Speicherverbrauch aufeinmal explodieren?

    Klar, wenn man dann einfach immer kopien macht, statt die Objekte nur zu referenzieren hat man probleme - aber wer wäre so dumm so etwas zu tun?

    Viele kleine Bausteine verknüpft mit Logik ergeben ein geordnetes Ganzes.
    --- ein bekannter Kybernetiker der 60er Jahre_Vordenker der Objektorientierung

    Eben, genau das behaupte ich ja auch.
    Viele kleine Bausteine.
    Nicht ein großer, fetter Baustein.

    Natürlich sind meine Kommentare auch überspitzt, aber ich gehe auf deine Argumente ein. Und drehe dir deine Worte nicht im Mund um (wie du zB bei #define <-> const)



  • besserwisser schrieb:

    naja, welche vorteile haben denn symbolische konstanten gegenüber echten? daß man die typsicherheit umgeht oder was? sag mal, da bin ich echt gespannt, was ich alles verpaßt habe, seit ich kein #define mehr verwende...

    Konstanten dürfen WIRKLICH nur ein einziges Mal definiert werden, und sind deshalb nicht dafür geeignet, in einem Header zu stehen.
    Bei define ist das egal, weil da immer die letzte Definition gilt, die sich natürlich beim selben Header niemals von eventuell vorhergehenden Definitionen unterscheidet.

    Stell Dir vor, du benötigst den selben Header in den unterschiedlichsten Modulen, dann kannst Du Dir mit Konstanten, die im Header stehen, vom Compiler üblicherweise anhören, dass doppelte Definitionen von Konstanten nicht erlaubt sind, was Konstanten völlig ungeeignet macht, mehreren Modulen zur Verfügung zu stehen. Du musst dann anfangen mit extern und static umständlich Gültigkeitsbereiche zu erfinden, damit das trotzdem geht. Dabei geht es viel einfacher mit #define, da sparst Du dir damit eine Menge Ärger.

    Nur ein gut gemeinter Rat. 🙂



  • Mecnels schrieb:

    Nur ein gut gemeinter Rat. 🙂

    Der dummerweise völliger Käse ist.

    Konstanten dürfen WIRKLICH nur ein einziges Mal definiert werden, und sind deshalb nicht dafür geeignet, in einem Header zu stehen.

    Käse. Konstanten können ganz wunderbar in Headern stehen. const heißt in C++ automatisch static, also internal linkage. Desweiteren sind Integerkonstanten in C++ Compile-Zeit-Konstanten, d.h. es wird, sofern du nicht die Adresse der Konstanten bildest, kein Speicher benötigt.

    Stell Dir vor, du benötigst den selben Header in den unterschiedlichsten Modulen, dann kannst Du Dir mit Konstanten, die im Header stehen, vom Compiler üblicherweise anhören, dass doppelte Definitionen von Konstanten nicht erlaubt sind, was Konstanten völlig ungeeignet macht, mehreren Modulen zur Verfügung zu stehen

    Käse. Wahrscheinlich hast du irgendwann mal geschrieben:

    const char* bla = "Fred";
    

    und dann hat sich dein Linker beschwert (zurecht) und du hast die völlig falschen Schlüsse gezogen.



  • HumeSikkins schrieb:

    Mecnels schrieb:

    Nur ein gut gemeinter Rat. 🙂

    Der dummerweise völliger Käse ist.

    was sogar ich als neuling weiß, weil ichs in meinen paar miniprogrammen, die ich bis jetzt nur erstellt hab, verwendet habe. Mecnels, du hast einfach keine praktische erfahrungen mit sowas. nichts gegen das gedankenexperiment an sich, aber ab und an sollte man seine theorien in der praxis erproben.

    ich meine, ich bin durchaus kein anhänger von gruppenzwang, aber wenigstens könntest du doch inzwischen (nachdem sich immer noch niemand FÜR deinen programmierstil ausgesprochen hat) mal auf die idee gekommen sein "hey, ich probier einfach mal aus, was die da die ganze zeit beschreiben". was würdest du schon verlieren? entweder hast du recht, dann kannst du viel aufrichtiger deine meinung weiterhin vertreten, oder wir haben recht, dann kannst du dich verbessern. und ist es nicht dein ziel, dich weiterzuentwickeln, dich und das, was du erschaffst, immer weiter zu verbessern?



  • Mecnels schrieb:

    Zahl und Vektor haben soviel gemeinsam wie Auto und Regenwurm, und niemand konvertiert Autos in Regenwürmer.

    Das will auch niemand machen...
    Aber was stört dich zB an explicit für den Ctor?

    Wenn dein Vektor einen Ctor mit nur einem int als Param nehmen würde, dann würde dein Grund gegen op+ als non member zutreffen.

    Natürlich würde man dann den Ctor explicit deklarieren und eine Konvertierung findet nicht statt.

    Interessanterweise hast du ohne explicit aber enorme Probleme:

    void f(Vektor);
    
    f(1);
    

    würde plötzlich gehen.

    schlimm schlimm

    Deshalb ist explicit keine spielerei die unnötig ist, sondern essentiell.

    Natürlich ist op+ als member kein fehler, solange du nur vektors miteinander addierst.

    aber wenn du einen neuen op+ dazu gibst, dann hast du einen op+ als member und einen als non member. das stört doch die konsistenz, oder?

    ich mag es, wenn sachen die zusammen gehören an einer stelle sind.



  • besserwisser schrieb:

    was sogar ich als neuling weiß, weil ichs in meinen paar miniprogrammen, die ich bis jetzt nur erstellt hab, verwendet habe. Mecnels, du hast einfach keine praktische erfahrungen mit sowas. nichts gegen das gedankenexperiment an sich, aber ab und an sollte man seine theorien in der praxis erproben.

    Du hast ganz recht, von ein paar miniprogrogrammen sollte man wirklich nicht auf die Praxis schließen.

    In der Praxis interessiert es die Verwender Deiner Funktionen überhaupt nicht, wie Du irgend etwas implementiert hast, die erwarten nämlich nur, dass die Schnittstelle eine Schnittstelle ist, sprich, das macht, was draufsteht, wenn sie sie verwenden wollen. (Genau dazu kapselt man nämlich die internen Daten - um den tatsächlichen Umfang der Klasse zu verstecken und dem Anwender zu ersparen, sich Gedanken darüber zu machen, warum die Schnittstelle funktioniert)

    Irgendwie seid ihr komische Käuze, die einen verteufeln es, Microsoft Code als Vorbild zu nehmen, ist ja klar, er wird ja auch nur von den bestbezahlten Spitzenprogrammierern der Welt entwickelt (aber ihr wisst es ja sicher besser).

    Die anderen wie unwissender und Shade schreiben ein paar Miniprogramme wie TicTacToe und wollen einem einreden, dass man seit 20 Jahren und nach einigen hundert Projekten praxisfern arbeitet.

    Bedenklich ist nur, dass Euch Eure eigenen Widersprüche gar nicht auffallen, weil Ihr Euch so auf mich eingeschossen habt.

    Nehm's Euch trotzdem nicht übel, empfehle unwissender einfach einmal, C++ Das Grundlagen Buch (auch wenn's viel Arbeit ist, 1000 Seiten durch zu ackern), das ist nämlich wirklich eines der besseren Bücher, die im Laufe der letzten Jahre erschienen sind. Und wenn dann die Grundlagen einmal sitzen, dann seht Ihr vielleicht einige meiner Diskussionsbeiträge in einem anderen Licht, fürchtet Euch nicht mehr, Zeiger einzusetzen, wo sie nötig sind usw.

    Bis dann.



  • Du Hirn. Wir fürchten uns nicht, Zeiger einzusetzen. Es geht darum, Zeiger zu wrappen, damit man weniger Dinge vergessen kann. Wenn ich nen auto_ptr hab, kann ich das deleten nicht vergessen, auch nicht bei Exceptions. Wenn ich nen vector nehme, kann ich das deleten nicht vergessen und ne Indexprüfung einbauen.
    Du krasser Ober-Hacker vergisst sowas natürlich sowieso nicht. Das passiert nur uns. Die anderen haben wirklich gute Gründe vorgetragen für bestimmte Dinge und nicht nur ich habe dir eine ganz konkrete Buchempfehlung ausgesprochen.
    Dein Alterstarrsin kann einen ganz schön auf den Keks gehen. Seit wann arbeiten bei Microsoft Spitzenprogrammierer? Natürlich wird es dort auch gute geben, genauso wie es dort auch schlechte geben wird und falls du es noch nicht gemerkt hast:
    DAS WINDOWS API IST C OHNE ++ !!

    Und was du codest ist auch C ohne ++ vielleicht noch mit Klassen. Zum letzten mal: Lies Scott Meiers. Und lerne C++ damit. Du bist nicht im Recht, nur weil du dich als alten Hasen siehst. Und wenn du glaubst, das Shade noch nichts anderes als ein TicTAcToe zustande gebracht ha, täuscht du dich. Das war ein Design-Experiment, etwas was dir anscheinend überhaupt nichts sagt.
    </Diskussion>



  • MecnelsAmArbeitsplatz schrieb:

    In der Praxis interessiert es die Verwender Deiner Funktionen überhaupt nicht, wie Du irgend etwas implementiert hast, die erwarten nämlich nur, dass die Schnittstelle eine Schnittstelle ist, sprich, das macht, was draufsteht, wenn sie sie verwenden wollen.

    Ich rede nicht von Client Code. Denn dann dürften wir uns nur die Schnittstelle ansehen, aber nicht die Implementierung. Und um eine Schnittstelle beurteilen zu können, braucht man viel wissen um die Domain.

    Es geht hier um die Implementierung. Und da spielt wartbarer Code eine sehr große Rolle, oder schreibst du nur wegwerfcode? Vermutlich nicht, deshalb ist es wichtig, dass er wartbar bleibt. Und da ist die Implementierung durchaus interessant (schließlich kann man an der Schnittstelle nicht viel warten ;))

    Irgendwie seid ihr komische Käuze, die einen verteufeln es, Microsoft Code als Vorbild zu nehmen, ist ja klar, er wird ja auch nur von den bestbezahlten Spitzenprogrammierern der Welt entwickelt (aber ihr wisst es ja sicher besser).

    WinAPI Code ist nicht schön. Kann dir jeder hier bestätigen.
    Natürlich ist er funktionell und es ist eine wahnsinns Leistung von MS die Winapi so stabil zu halten. Aber sie ist auch eine C API, deshalb sind einige Designentscheidungen in C++ nicht vertretbar. Denn C++ und C sind halt doch 2 verschiedene Sprachen.

    Die anderen wie unwissender und Shade schreiben ein paar Miniprogramme wie TicTacToe und wollen einem einreden, dass man seit 20 Jahren und nach einigen hundert Projekten praxisfern arbeitet.

    Wie kommst du darauf?
    Ich habe sicher nicht mehr Erfahrung als du, aber ich bin auch schon ein paar Jahre "in the real world". Habe als doch ein wenig einblick.

    Bedenklich ist nur, dass Euch Eure eigenen Widersprüche gar nicht auffallen, weil Ihr Euch so auf mich eingeschossen habt.

    Oh, sehr schön. Welche denn? Ich will ja lernen...
    Aber du bringst leider kaum Argumente 😞
    Wie soll ich dann je besser werden? Ich lege meine Argumente offen da, du kannst nachfragen (und wenn es dir gelingt, mich in widersprüche verstricken) usw. aber du zeigst leider kaum argumente 😞 das macht die sache recht schwer darüber zu diskutieren.

    zB welche vorteile haben #defines gegenüber konstanten?
    warum sind wrapper böse?
    was spricht gegen explicit bei einem ctor der nicht zur konvertierungen verwendet werden soll?
    usw.

    Und wenn dann die Grundlagen einmal sitzen, dann seht Ihr vielleicht einige meiner Diskussionsbeiträge in einem anderen Licht, fürchtet Euch nicht mehr, Zeiger einzusetzen, wo sie nötig sind usw.

    Bitte erklär deinen Standpunkt doch.
    Und lies bitte was ich schreibe. Ich habe nicht gesagt: verwende keine Zeiger, sondern ich habe gesagt: wrappe sie lieber.

    Ich würde von mir nie behaupten C++ zu beherrschen (außer einem Personalchef gegenüber ;)) aber die Grundlagen kann ich mittlerweile schon ganz gut. Und Zeiger stellen für mich auch kein Problem da. Aber dennoch finde ich es schöner, mich nicht darum kümmern zu müssen, weil es ein Wrapper macht.

    Das spart mir Zeit und reduziert die Fehlerquellen und das bedeutet weniger Zeit geht für das Debuggen drauf. Und das macht mich glücklich 🙂

    btw: ich habe den heutigen Vormittag damit verbracht den Code für die Anwendung die ich gerade schreibe zu kürzen und ein neues Modul eingeführt 🙂 Das erlaubt leichtere erweiterung des Codes, weil man nun nur ein kleines Modul ändern muss um neue Funktionalität hinzufügen zu können, statt wie vorher direkt im Source code an 2 stellen die änderungen vorzunehmen.



  • MecnelsAmArbeitsplatz schrieb:

    Irgendwie seid ihr komische Käuze, die einen verteufeln es, Microsoft Code als Vorbild zu nehmen, ist ja klar, er wird ja auch nur von den bestbezahlten Spitzenprogrammierern der Welt entwickelt (aber ihr wisst es ja sicher besser).

    Tut mir leid, aber looooooooooooooooooooooool

    Guck Dir den Code an, dann weißt Du wie man NICHT programieren sollte. Wenn die so toll wären, hätten sie dann so übermäßig viele Sicherheitslücken?

    Wenn Du guten Code sehen willst, dann guck Dir z. B. Linux, POSIX, Boost und co. an.

    Jetzt muss ich mich weiter tot lachen 😉



  • Wahrscheinlich ist das Feld der C/C++ Programmierung wirklich so weit gesteckt, dass man so leicht aneinander vorbeireden kann.

    Ganz kurz zu den Schnittstellen, ein sehr gutes Beispiel ist DirectX:
    Als Programmierer habe ich nun mal nicht wirklich Interesse daran, wie genau ein Funktion implementiert ist, die Oberflächen kopiert, Blitts durchführt, Ein CooperativeLevel für ein Device setzt usw. usf. Trotzdem sind das alles Funktionen, und zwar alles durchweg solche, die NICHT in zehn Zeilen codiert sind! Ärgert Dich die beschränkte Mächtigkeit/Einsetzbarkeit Deiner Minifunktionen denn nicht selber? Alles was Du davon hast ist ein Bezeichnerwildwuchs, der ziemlich leichte Aufgaben plötzlich total kompliziert erscheinen lassen. Man kann es so wie Du machen und 20 oder noch mehr Module schreiben. Stattdessen kann man die Aufgabe auch analysieren:
    1.) Abwechselnd setzen zwei Spielteilnehmer Jetons oder dergleichen auf ein 3x3 grosses Spielfeld. (== Problemstellung)

    Aha, also brauchen wir Klassen für Jetons und Felder, die jeweils ein ELEMENT des gesamten Spieles sind.
    Das GESAMTE Spiel OPERIERT mit diesen ELEMENTEN, und dementsprechend stecken wir die Felder und Jetons in eine Klasse TicTacToe, die in ihren Elementfunktionen mit Objekten der Klasse Jetons und solchen der Klasse Feld operiert.

    Das ist meiner Meinung nach jedenfalls der Sinn der Objektorientierung:
    Die Möglichkeit, kompliziertere Datentypen als einfache Zahlen und kompliziertere Operationen als einfache Additionen aus der Sicht des Programmierers mit ihrem Namen anzusprechen, das meinte ich mit Baukastenprinzip: Du baust Dir die Objekte, die Du brauchst, aus den einfachen ganzzahligen Datenobjekten allmählich zu einem sehr großen, die Problemstellung lösendes Objekt, zusammen.

    Aber das ist glaube ich wirklich nur eine Frage der allgemeinen Programmierphilosophie, wie man zu Werke geht, und sicher nicht ein Grund, sich darüber zu streiten, wie es denn nun richtiger gehen müsste:
    Denn jedenfalls lösen wir trotz aller Unterschiede unsere Problemstellungen doch immer zufriedenstellend für unsere Chefs.



  • ROFL schrieb:

    Wenn Du guten Code sehen willst, dann guck Dir z. B. Linux, POSIX, Boost und co. an.

    Jetzt muss ich mich weiter tot lachen 😉

    Genau auf so einen Kommentar habe ich gewartet.
    Erstens: Linux ist Vodoo. Die Anhänger schwärmen, dass man damit alles machen KANN, sagen aber nicht dazu, dass man damit auch alles selber machen MUSS, um dem Rechner Vernünftiges zu entlocken.
    Ich finde es deshalb bei uns hier in Österreich total verkehrt, dass an den Unis Linux-Rechner stehen, an denen die Studenten ausgebildet werden, wenn die armen dann von der Uni abgehen, verlangt plötzlich jeder Arbeitgeber, der gut zahlt, Win2000. Das Gejammer kenn ich nur zu gut von jüngeren Mitarbeitern bei uns. Lustiger Weise hat sich bei uns an den Hochschulen auch die Sitte herausgebildet, Java als Lehrsprache zu verwenden, wieder einmal sind sie auf einen kurzlebigen Trend (Hype heisst das heutzutage, oder?) hereingefallen, der sich mittlerweile offensichtlich tot gelaufen hat, und jetzt können die Jungs zwar Java aber das interessiert niemanden, weil sich C/C++ eben schon seit fast 30 Jahren und mehr bewährt hat. Die Plattformunabhängigkeit ist angesichts der langsamen Interpretation des Objektcodes einfach nicht überzeugend, schon gar nicht, wenn auf 90% aller Rechner sowieso das selbe OS werkelt. Aber ich mach ja die Lehrpläne nicht, denn dann würden die Leutchen viel besser auf das Leben vorbereitet von der Hochschule abgehen - indem man ihnen C/C++ anstatt Java beibringt und indem man sie vor Win2000 und nicht vor Substandard Linux Rechner setzt.
    Nur wieder die Meinung eines alten Sturkopfes, aber ihr könnt ja weiterhin weghören.



  • Darf ich? Darf ich? 😃 ...ne, ich halt mich mal zurück, solange der letzte Beitrag nicht in einen neuen Thread ausgelagert wird. 🙂


Anmelden zum Antworten