Beta-Tester für C++11 UML State Machine Framework yasmine gesucht



  • Artchi schrieb:

    Mir ist nur schleierhaft, wie du gerade auf die MIT-Lizenz gekommen bist?

    Weil sie unrestriktiv ist und ich genau die eine Einschränkung haben wollte. Und sie ist nicht "copyrighted", also darf man sie modifizieren. Mehr steckt da nicht dahinter.

    Artchi schrieb:

    Egal was du uns hier noch erzählst, hinter dem Opensource-Gedanken stehst du jedenfalls nicht.

    Das ist natürlich eine scharfe Abgrenzung. Aber nein, in der 100%-Hardliner-Ecke stehe ich nicht (so wie ich selten etwas schwarz oder weiß sehe). Habe ich aber auch nie behauptet. Aber in die fiese Ausbeuter-böse Menschen-Ecke musst Du mich auch nicht stellen.



  • Wenn jemand mit Begriffen wie OpenSource und sogar MIT-Lizenz ankommt, dann muss er das auch liefern. Oder?

    Und nein, ich verlange kein OpenSource von jemandem um ihn als "gut" anzusehen. Kann jeder SharedSource oder Closed Source machen wie er will! Das ist völlig legitim! Ich bin auch kein OSS/FSF-Jünger, ich benutze MS-Windows und VisualStudio. Aber MS verkauft mir das nicht als OpenSource sondern ganz klar als ClosedSource. Jeder potenzielle Interessen weiß woran er ist. 👍

    Und wir sind auf Seite 5 deines Threads, in dem du uns immer noch dein Yasmine felsenfest als OpenSource "verkaufen" willst... geht gar nicht.



  • Artchi schrieb:

    Und wir sind auf Seite 5 deines Threads, in dem du uns immer noch dein Yasmine felsenfest als OpenSource "verkaufen" willst... geht gar nicht.

    Womit mache ich das denn? Wann habe ich das dann gesagt?
    Wenn Du den ersten Teil der Diskussion mitverfolgt hättest, wäre Dir vielleicht aufgefallen, dass ich auf die dort geäußerte Kritik IMHO sehr offen eingegangen bin (obwohl die Kritik teilweise hart an der Grenzen der Sachlichkeit war) und schon Diverses angepasst habe. Dass Du jetzt so tust als würde ich seit 5 Seiten auf meinem Standpunkt beharren, finde ich nicht in Ordnung.

    Auch dass Du das Ganze jetzt so kategorisiert, als wäre es mehr "closed" als "open" finde ich auch nicht in Ordnung.

    Umsonst und offen ist nicht umsonst und offen genug.
    Um die Analogie von vorhin aufzugreifen:
    Auf mein Klo gehen reicht nicht, auch noch das Wunschklopapier muss es sein.



  • @void*
    Nenn die Lizenz einfach anders. z.b. SOS - kurz für "Seadex Open Source".
    Und "bewirb" die Lizenz nicht damit sie als MIT Lizenz anzupreisen. Eher mit sowas wie "relativ liberale Lizenz die auf der MIT Lizenz basiert".

    @Artchi
    Deine enge Auslegung des Begriffs Open Source ist mMn. total unangebracht. Es gibt schliesslich nicht umsonst Begriffe/Kürzel wie FOSS.



  • hustbaer schrieb:

    @void*
    Nenn die Lizenz einfach anders. z.b. SOS - kurz für "Seadex Open Source".
    Und "bewirb" die Lizenz nicht damit sie als MIT Lizenz anzupreisen. Eher mit sowas wie "relativ liberale Lizenz die auf der MIT Lizenz basiert".

    Es war nie mein Ziel damit zu "werben". Mir ging es nur darum zu zeigen, dass man damit fast alles machen darf und dass die proprietäre Lizenz (das habe ich offen gesagt, dass sie das ist) eine wichtige Einschränkung enthält (und auch welche). Das Ganze war ein Satz im Eröffnungspost. Danach bin ich nie - wie unterstellt - darauf rumgeritten, sondern habe mich zu den Kritikpunkten aus meiner Position geäußert. Auch habe ich nie etwas zu verschönigen versucht oder gesagt "doch, doch, dass ist OpenSource". Ich habe nur die Position vertreten, dass die Lizenz sehr liberal ist. Und das ist sie IMHO auch.
    Mir kam in der Diskussion jetzt auch schon die Idee die MIT einfach zu übersetzen, als extra Paragraph einzubetten und den Verweis auf die MIT-Lizenz ganz zu entfernen.



  • void* schrieb:

    Jegliches Feedback über API, Bugs und auch Feature-Requests sind willkommen.

    Ich habe nur mal ein kurzen Blick in das Beispiel geworfen:

    - Seit Ihr euch sicher, dass ihr jedem Benutzer eurer Bibliothek die Nutzung eures Loggings aufzwingen wollt? Das erschwert die Integration.
    - Ungarische Notation ist so etwas von out! Das erschwert das Lesen von Code ungemein.
    - Brauche ich wirklich 10 header um ein Minimal-Beispiel zu schreiben?
    - Sehr rigoroser Gebrauch von Pointern. Ist das wirklich nötig? Warum kann ich einen state machine nicht einfach als value verwenden?
    - Idealerweise würde ich überhaupt keinen dynamischen Speicher brauchen.
    - Y_UNUSED_PARAMETER: warum gebt Ihr Parametern erst Namen um die Nicht-Verwendung dann mit einem Makro zu dokumentieren?
    - Was sollen regions sein und warum funktioniert ein einfaches Beispiel nicht ohne?
    - return ist KEINE FUNKTION! 😉
    - usw.

    also wenn ich mir schon die Mühe machen würde, für Zustandsautomaten eine Library zu schreiben, dann:
    - Muss sie das Erstellen eines Automatens auch _deutlich_ vereinfachen.
    - Muss der Automat also solches sehr gut lesbar sein, da meiner Meinung nach, genau dass das Problem von Automaten ist: Sie werden schnell unübersichtlich.

    Beispiel:

    #include <state_foo>
    #include <iostream>
    
    enum state_codes {
        waiting,
        reply
    };
    
    enum event_codes {
        hello
    };
    
    state_machine< state_codes, event_codes >(
        state( waiting,
            transition< hello, reply >(),
            on_enter(
                [](){ std::cout << "waiting..." << std::endl; }
            )
        ),
        state( reply,
            auto_transiton< waiting >(),
            on_enter(
                [](){ std::cout << "Hello, foo!" << std::endl; }
            )
        )
    ) pointless_example_machine;
    
    int main()
    {
        pointless_example_machine.fire_event( hello );  
        pointless_example_machine.fire_event( hello );  
        pointless_example_machine.fire_event( hello, std::clog ); // hier mal mit logging
    }
    

    mfg Torsten



  • Hallo Torsten,

    Torsten Robitzki schrieb:

    void* schrieb:

    Jegliches Feedback über API, Bugs und auch Feature-Requests sind willkommen.

    vielen Dank schon mal für Dein Feedback!

    Torsten Robitzki schrieb:

    - Seit Ihr euch sicher, dass ihr jedem Benutzer eurer Bibliothek die Nutzung eures Loggings aufzwingen wollt? Das erschwert die Integration.

    Das ist nicht erzwungen, sondern optional. Das muss man nicht nutzen. Wenn Du nichts initialisierst, wird auch nichts geloggt.
    Eine Idee habe ich aber noch zusätzlich:
    Wir werden noch ein Macro/Define einführen, mit dem man erreichen kann, dass die Log-Macros gar keinen Code erzeugen.

    Torsten Robitzki schrieb:

    - Ungarische Notation ist so etwas von out! Das erschwert das Lesen von Code ungemein.

    Also ungarische Notation kann man das nun wirklich nicht nennen. Hier wird ja keine Typinformation in Variablennamen codiert. Sonst benutzt auch Qt wegen dem Q vor den Klassennamen ungarische Notation.
    Und ich selber sehe gern den Scope einer Variablen am Namen (Klassen-Member, Funktionspararmeter, global, lokal, ...).
    Bei Typen finde ich es u.a. hilfreich
    - wegen Interfaces: i_printer und t_printer oder printer_interface und printer?
    - weil öfters Variablennamen dem Typ "entsprechen". Dann muss man sich für den Variablennamen nicht künstlich irgendwelche Prosa ausdenken.

    void check_consumable_levels(const t_printer& p_printer) {
    	// ...
    }
    
    void check_consumable_levels(const printer& printer_to_check) {
    	// ...
    }
    

    Im Code selber kommt noch zu oft l_ vor. Das sollte eigentlich nur in Sonderfällen zur Auflösung von Mehrdeutigkeiten dienen. Das werden wir noch ausmisten.

    Torsten Robitzki schrieb:

    - Brauche ich wirklich 10 header um ein Minimal-Beispiel zu schreiben?

    Ja und nein. Technisch gesehen ja, weil man halt diverse verschiedene Klassen verwendet. Aus der Usability-/Convenience-Sicht nein, denn es könnte natürlich für die Bibliothek einen Sammel-Header à la windows.h geben. Ggf. auch mit einem "lean and mean"-Macro, das dazu führt, dass nur die wichtigsten Features mitliefert werden.
    Ich nehme das auf.

    Torsten Robitzki schrieb:

    - Sehr rigoroser Gebrauch von Pointern. Ist das wirklich nötig? Warum kann ich einen state machine nicht einfach als value verwenden?
    - Idealerweise würde ich überhaupt keinen dynamischen Speicher brauchen.

    Bzgl. der State Machine:
    Natürlich steht Dir frei die State Machine auf dem Stack anstatt auf dem Heap anzulegen. In dem Beispiel ist es so gelöst, da die State Machine in einer Factory-Funktion erzeug wird und die State Machine ohne kopieren durch reines moven des unique_ptr herausgegeben werden kann.
    Du könntest die State Machine aber auch als Klassenmember haben oder in eine Factory-Funktion per Referenz rein reichen und befüllen lassen. Eine State Machine (rekursiv) zu kopieren halte ich (als default-Verhalten) für keine gute Idee.
    Bzgl. der internen Verwendung:
    Das ist zum Teil so, weil intern polymorphe Container verwendet werden und zum Teil weil im großen und ganzen gegen Interfaces anstatt gegen Implementierungen gearbeitet wird.

    Torsten Robitzki schrieb:

    - Y_UNUSED_PARAMETER: warum gebt Ihr Parametern erst Namen um die Nicht-Verwendung dann mit einem Makro zu dokumentieren?

    Bei der Lambda beim Erstellen der State Machine ist das vielleicht ein etwas schweres Geschütz. Aber das Stichwort "dokumentieren" ist genau das richtige.
    Während das einfache Weglassen des Parameters es implizit macht, passiert es durch das Macro explizit. Außerdem läßt sich nach dem Macro gut suchen, nach einem weggelassenen Parameter nicht. Dies ist ja auch _ein_ Vorteil von C++-Casts gegenüber C-Style-Casts.

    Torsten Robitzki schrieb:

    - Was sollen regions sein und warum funktioniert ein einfaches Beispiel nicht ohne?

    Durch orthogonale Regionen können in einem Zustand mehrere Unterzustände gleichzeitig (parallel) aktiv sein. Normalerweise hast Du in einer State Machine eine "entweder oder"-Beziehung zwischen Zuständen. Durch Regionen kann man eine "und"-Beziehung modellieren.
    Ein einfaches Beispiel funktioniert natürlich auch ohne. Hier ist die API noch sehr geradlinig und man muss hier die Regionen immer manuell anlegen. Priorität hatte hier erst einmal vollständige Funktionalität.
    Der Komfort soll aber auch nicht leiden:
    Es lässt sich natürlich erreichen, dass in einem Composite State automatisch immer eine "default"-Region vorhanden ist und dass sich ein Einfügen direkt in einen Composite State erstmal direkt auf die "default"-Region bezieht. Ich nehme das auf.

    Torsten Robitzki schrieb:

    - return ist KEINE FUNKTION! 😉

    Das mit dem Klammern ist eine alte Angewohnheit, die ich mir aus meinem ersten C-Buch abgeschaut hatte (von Andre Willms, glaube ich) und das ist dann über die Jahre so geblieben.
    Und die C++-Casts sind auch keine Funktionen, sondern Operatoren und da braucht man auch Klammern. 🤡

    Torsten Robitzki schrieb:

    also wenn ich mir schon die Mühe machen würde, für Zustandsautomaten eine Library zu schreiben, dann:
    - Muss sie das Erstellen eines Automatens auch _deutlich_ vereinfachen.
    - Muss der Automat also solches sehr gut lesbar sein, da meiner Meinung nach, genau dass das Problem von Automaten ist: Sie werden schnell unübersichtlich.

    Ich stimme Dir zu, dass das Definieren des Automaten möglichst elegant und kompakt sein sollte. Da können wir bestimmt auch noch Einiges an "Convenience-Schnittstellen" anbieten. Allerdings war das erste Hauptziel, die vollen Fähigkeiten einer UML State Machine abbilden zu können. Wenn das technisch alles funktioniert, können wir in diesem Bereich an der API noch viel machen.
    Das Definieren des State Machine im Code soll in Zukunft auch noch in den Hintergrund rücken, wenn wir den Rumpf-Code aus einem Modell generieren. Aber das will natürlich nicht jeder so machen und dann sollte eine elegante manuelle Definition möglich sein.
    Aber es kann auch nicht das Ziel sein, dass triviale Beispiele trivial zu implementieren sind und komplexere State Machines dann dramatisch schwieriger in der Umsetzung werden.
    Ich habe lieber ein wenig mehr Aufwand mit einfacheren Konstrukten, wenn ich dafür mit komplexen Konstrukten immer noch sicher umgehen kann.
    Dein Beispiel Pseudo-Code ist natürlich schön kompakt. Aber er deckt jetzt nur einen Corner-Case ab, der nur ein Bruchteil der Features einer UML State Machine nutzt.
    Und das yasmine-Beispiel könnte man auch noch deutlich eindampfen. Das finde ich aber aus didaktischer Sicht ungünstig. Das Beispiel soll zeigen, wie die Konzepte funktionieren und nicht wie man den Code auf möglichst wenige Zeilen presst.



  • Die Namenskonflikte zwischen Klassen, Interfaces und Variablen kann man ganz einfach lösen.

    class Printer;
    class IPrinter; // Interface
    Printer printer;
    

    Das ist praktisch und zumindest in der Windows Welt sehr üblich (COM, .NET Framework, Quasi-Standard bei C#, generell viel Code von MS).
    😉



  • hustbaer schrieb:

    Die Namenskonflikte zwischen Klassen, Interfaces und Variablen kann man ganz einfach lösen.

    class Printer;
    class IPrinter; // Interface
    Printer printer;
    

    Naja, die "übliche" Lösung dafür ist, das Objekt nach seiner Rolle, nicht nach seinem Typen zu benennen. Du nennst ja einen int auch nicht Int, oder?

    im Beispiel oben wäre dass:

    void check_consumable_levels(const printer& to_be_checked);
    

    Wenn die Rolle bereits so stark über den Typen definiert ist, dann spricht doch auch überhaupt nix dagegen das Objekt einfach p zu nennen. Oder was würde p_printer in der Situation an zusätzlichen Informationen liefern. Was gibt mir t_ und p_ an zusätzlichen Informationen, die es Wert sind, meinen Lesefluss zu unterbrechen. t_ ist ein Type! Echt? Wow! 😉 Was sollte printer den anderes sein, als ein Typ?

    Am besten noch so etwas: 😉

    /**
     * @param the_printer the printer
     */
    void check_consumable_levels(const printer& the_printer);
    


  • Torsten Robitzki schrieb:

    hustbaer schrieb:

    Die Namenskonflikte zwischen Klassen, Interfaces und Variablen kann man ganz einfach lösen.

    class Printer;
    class IPrinter; // Interface
    Printer printer;
    

    Naja, die "übliche" Lösung dafür ist, das Objekt nach seiner Rolle, nicht nach seinem Typen zu benennen. Du nennst ja einen int auch nicht Int, oder?

    im Beispiel oben wäre dass:

    void check_consumable_levels(const printer& to_be_checked);
    

    Bilderbuchbeispiel => mMn. uninteressant.
    Ja, man sollte Variablen sinnvoll benennen, und sinnvoll ist nicht immer der Typname.
    Allerdings oft halt ... doch. Und dann kollidiert es. Und dann ist unterschiedliche Benamsung praktisch.
    Ist jetzt eigentlich keine Rocket-Science.

    Beispiel:

    void PrintDocument(Document const& document, Rasterizer const& rasterizer, Printer const& printer);
    

    Was soll man hier umbenennen?
    Meinst du dass "toPrint" statt "document" besser wäre? Bei einer Funktion die ... naja, "print document" heisst? Und was mit den anderen beiden Parametern?

    Torsten Robitzki schrieb:

    Wenn die Rolle bereits so stark über den Typen definiert ist, dann spricht doch auch überhaupt nix dagegen das Objekt einfach p zu nennen.

    Doch. Nämlich dass man, wenn es sich nicht gerade um Parameter handelt, sondern z.B. um lokale Variablen, auto statt des Typs schreibt.
    Dann hast du nur noch "p". Nicht so toll.
    Und ... selbst wenn da wirklich Printer p; steht... und nur 2-3 Zeilen bis zur letzten Verwendung von "p" dazwischen sind... ist es vollkommen unnötige Gehirnakrobatik die Zeile suchen zu müssen wo dann der Typ zu finden ist. Und selbst wenn es nur 1/2 Gehirnzelle beschäftigt, ist das 1/2 Gehirnzelle die mir weniger zur Verfügung steht sinnvolle Dinge abzuchecken bzw. im Gedächtnis zu behalten.



  • Torsten Robitzki schrieb:

    Was gibt mir t_ und p_ an zusätzlichen Informationen, die es Wert sind, meinen Lesefluss zu unterbrechen. t_ ist ein Type! Echt? Wow! 😉 Was sollte printer den anderes sein, als ein Typ?

    OK.

    ... printer() ...
    

    Typ? Funktion? Variable (Funktor)?
    Doof, nen?



  • Diese Snake-Notation macht die Sache leider nicht leichter. CamelCase ist da schon flexibler, und dann kann der Parameter halt schon print(Printer printer) heißen.

    Bei Snake muss man sich dagegen "Sonderzeichen" bedienen: print(printer printer_)
    Sieht für den Implementierer nicht so toll aus, aber es gibt keinen Konflikt und der User der Funktion muss sich nicht mit unsinnigen Namen anfreunden.

    class Printer;
    class IPrinter; // Interface
    Printer printer;
    

    Obiges kenne ich auch so von Java bzw. OSGI-/Eclipse-RPC-Notation. Ist natürlich schön.

    Das würde ich bei Snake anders lösen:

    // Das Interface, der Interface-Name sollte "schön" sein!
    class printer;
    
    // Spezielle Implementierung:
    class matrix_printer : public printer;
    // wenn einem nichts besseres einfällt:
    class printer_impl : public printer;
    

    Da man bei gegen-Interfaces-Programmierung immer und überall auf den Interface-Name trifft, sollte dieser einen schöneren und kürzeren Namen als die implementierende Klasse haben. Denn letztere kommt ja nur beim Instanzieren und somit seltener im Quelltext vor.



  • hustbaer schrieb:

    Beispiel:

    void PrintDocument(Document const& document, Rasterizer const& rasterizer, Printer const& printer);
    

    Was soll man hier umbenennen?

    Vorschlag:

    void print(Document const& input, Rasterizer const& rules /* or raster */, Printer const& output);
    

    Wenn ich viel mit Libraries arbeite, die CamelCase verwenden, dann würde ich auch CamelCase verwenden. Wenn ich aber, wie der OP, eine kleine Support-Library schreibe, dann würde ich darauf achten, dass bei gemeinsamer Nutzung mit Elementen aus der Standard-Library, ein ruhiges Gesamtbild entsteht.

    mfg Torsten



  • Es ist aber glaube ich Konsens das die Notation von yasmine mehr als unglücklich und exotisch ist? Wenn man die Community für sein Toolkit gewinnen will, sollte man sich einigermaßen an die allgemeinen Gepflogenheiten halten.



  • Torsten Robitzki schrieb:

    hustbaer schrieb:

    Beispiel:

    void PrintDocument(Document const& document, Rasterizer const& rasterizer, Printer const& printer);
    

    Was soll man hier umbenennen?

    Vorschlag:

    void print(Document const& input, Rasterizer const& rules /* or raster */, Printer const& output);
    

    Der Vorschlag ist nicht dein Ernst, oder?

    Torsten Robitzki schrieb:

    Wenn ich viel mit Libraries arbeite, die CamelCase verwenden, dann würde ich auch CamelCase verwenden. Wenn ich aber, wie der OP, eine kleine Support-Library schreibe, dann würde ich darauf achten, dass bei gemeinsamer Nutzung mit Elementen aus der Standard-Library, ein ruhiges Gesamtbild entsteht.

    Was wäre der Vorteil des "ruhigen Gesamtbilds"?



  • @Artchi
    Ja, dem würde ich mich anschliessen.



  • Torsten Robitzki schrieb:

    Vorschlag:

    void print(Document const& input, Rasterizer const& rules /* or raster */, Printer const& output);
    

    Das ist eine vernünftige Benennung. Parameter oder Variablen nur nach ihrem Typ zu benennen ist eine Unsitte, die man zugunsten der Dokumentation vermeiden sollte.

    Wer meint, dass Document const& document die bestmögliche Benennung ist, schreibt wohl auch solche Kommentare:

    /** \brief Prints the document.
     \argument document the document
     \argument rasterizer the rasterizer
     \argument printer the printer
     \returns void
    */
    void PrintDocument(Document const& document, Rasterizer const& rasterizer, Printer const& printer);
    

    Wenn ein Interface den gleichen Namen wie eine Implementierung bekommen soll, ist zu 99% etwas schief im Gedankenmodell. Man muss sich schon entscheiden, ob ein "printer" abstrakt oder konkret ist.



  • Der Knackpunkt ist dass eine Funktion mit dieser Signatur überhaupt keine Doku braucht. Wozu sollte man dann eine schreiben?

    Und was genau soll an "source" besser sein als an "document"? Wenn schon dann "sourceDocument". Nur bei einer Funktion die nur ein Document nimmt, und dieses ganz offensichtlich ausgedruckt wird, und daher ganz offensichtlich das "source" Dokument ist... also man kanns auch übertreiben.

    Einen Rasterizer als "rules" oder "raster" zu bezeichnen ist 1A Blödsinn.
    Genau so wie den Printer als "output" zu bezeichnen. Wahrscheinlich war hier "sink" (=etwas wo man Dinge hinein tun kann) und nicht "output" (etwas was von einem Prozess generiert wird) gemeint. Oder "outputDevice".

    Ist aber genau so Quatsch. Wieso vorgaukeln dass etwas irgendwie besonders generisch wäre (source, rules, outputDevice), wenn es in Wirklichkeit sehr konkret ist (document, rasterizer, printer)?

    Das ist doch bloss der krampfhafte Versuch etwas zu vermeiden was man irgendwann mal (fälschlicherweise) als "pfui" kategorisiert hat. Nämlich Objekte gleich zu nennen wie ihren Typ. Mein Erfahrung diesbezüglich ist: Je mehr man seine Programme sinnvoll factored, und je besser man seine Klassen benennt, desto häufiger macht es Sinn seine Objekte genau so zu nennen wie ihr Typ.
    Dass das als generelle Regel völlig schwachsinnig wäre ist auch klar. Ich sagen nur: es kommt nicht so selten vor dass es Sinn macht.



  • In diesem Fall kann man aus dem Funktionsnamen und Allgemeinwissen leicht herleiten, wofür die Parameter wohl gut sind. Das System bricht aber sofort zusammen, wenn es um Typen wie Integer, Zeiger, Strings geht oder mehrere Parameter denselben Typ haben.

    Beispiel:

    void Copy(Document document1, Document document2, bool boolean);
    

    Ich will nicht sagen, dass bool ein sinnvoller Parametertyp ist, aber Leute machen so etwas und dann sollte der Parameter wenigstens einen sinnvollen Namen haben. Wenn man anfängt die Parameterbenennung zur Ermessenssache zu machen, produzieren die faulen Entwickler Müllnamen und alle müssen darunter leiden. Deswegen bin ich dafür pauschal sprechende Namen zu verwenden.



  • TyRoXx schrieb:

    In diesem Fall kann man aus dem Funktionsnamen und Allgemeinwissen leicht herleiten, wofür die Parameter wohl gut sind. Das System bricht aber sofort zusammen, wenn es um Typen wie Integer, Zeiger, Strings geht

    Bei manchen Funktionen, ja. Bei anderen nicht.

    string ToString(int integer); // Weil "int int" halt nicht geht
    string ToLower(string str);
    ...
    

    Andere Namen machen hier keinen Sinn. (Nicht dass automatisch alle anderen Namen schlechter wären, "value" oder "number" wären natürlich auch OK - gleichwertig. Aber nicht wirklich besser.)

    TyRoXx schrieb:

    oder mehrere Parameter denselben Typ haben.

    Beispiel:

    void Copy(Document document1, Document document2, bool boolean);
    

    Ja, irgendwie logisch.
    Und?
    Mein Argument war:

    hustbaer schrieb:

    Ja, man sollte Variablen sinnvoll benennen, und sinnvoll ist nicht immer der Typname.
    Allerdings oft halt ... doch.

    Dem hast du widersprochen und mir unterstellt dass in meinem Gedankenmodell etwas schief sei. Und jetzt kommt der Strohmann dass ich behauptet hätte dass es immer Sinn macht? Oft = immer? Wo ich 1 Satz vorher explizit schreibe dass es NICHT immer Sinn macht? Wirklich?


Anmelden zum Antworten