Klassen ohne getter/setter?



  • Also mich würde mal ein Artikel freuen, wie man denn Klassen-Designs ohne Getter und Setter hinbekommen soll. Lese hier immer wieder im Forum, das manche Leute es ein schlechtes Design finden. Aber mich würde mal interessieren, wie das ganze denn real umgesetzt werden sollte?

    Wie würde man z.B. sowas "besser" lösen können:

    class Widget
    {
        public:
           void setModel(Model);
           Model getModel();
    };
    


  • Ich würde den Artikel schreiben.



  • Anmerkung: Das ist nicht meine Meinung, sondern eine Argumentation, mit der ich tatsächlich konfrontiert wurde.

    class Widget
    {
        public:
            Model model;
    };
    

    Begründung:

    Der Setter kann nur wie folgt implementiert sein...

    Widget::setModel(Model m)
    {
        model = m;
    }
    

    ... weil das "die Definition" eines Setters ist. Der darf nicht anders aussehen. Also kann man den Member gleich public machen (siehe oben).



  • Wie wäre es mit einem

    class Widget
    {
    public:
        void model(const Model&);
        const Model& model() const;
    
    private:
        Model model_;
    };
    

    Dann kann man bei Bedarf z.B. die beiden Funktionen duch einen public Funktor ersetzen, sodass keine änderungen im Clientcode mehr erfolgen müssen:

    class Widget
    {
    public:
        ModelImpl model;
    
    private:
        class ModelImpl
        {
        public:
            void operator(const Model&);
            const Model& operator() const;
    
        private:
            Model model_;
        };
    };
    


  • Ich fände so einen Artikel auch interessant! Wie sollte er denn aufgemacht sein? Generelles Klassen-Design vor dem eigentlich Programmieren (also Planung) mit Fallbeispielen oder wie?
    Und komplett ohne Getter? Weil einige Daten muss man ja rausholen?



  • Badestrand schrieb:

    Und komplett ohne Getter? Weil einige Daten muss man ja rausholen?

    Warum muss man das? Warum nicht einfach das Objekt, das die noetigen Daten bereithaelt, uebergeben?



  • Weil es Inkonsistenz zur Folge haben könnte.



  • Apollon schrieb:

    Badestrand schrieb:

    Und komplett ohne Getter? Weil einige Daten muss man ja rausholen?

    Warum muss man das? Warum nicht einfach das Objekt, das die noetigen Daten bereithaelt, uebergeben?

    Ach stimmt, irgendwie meinte ich das auch gar nicht so 😕 Meine Gedanken waren eben wie folgt: Die Methode "size()" in std::string sei ja auch ein Getter, weil es die Länge zurückgibt.



  • und wie kommt man an die nötigen Daten rann ?



  • Knuddlbaer schrieb:

    und wie kommt man an die nötigen Daten rann ?

    Jedenfalls nicht, indem man eine Referenz auf ein Klassenobjekt zurückgibt. Eher halt die nur wirklich nötigen Daten als Datensatz rausgeben. Mit Referenz ist die Klasse z.B. gezwungen, selbst ein Objekt dieser Art zu halten. Bei der Methode "size" von std::string können die Daten ja auch berechnet werden, es ist halt entkoppelter. So sehe ich das jedenfalls.



  • Knuddlbaer schrieb:

    und wie kommt man an die nötigen Daten rann ?

    Hoe? Man hat doch freien Zugriff drauf... Ach! Du meinst von aussen?! Nochmal: man reicht nicht Daten rum, sondern Objekte.



  • Natürlich kann man einen Öltanker auch selbst mit dem Zollstock abmessen. Aber wäre es nicht wesentlich einfacher, der Konstrukteur sagt mir einfach, wie lang das Schiff ist?



  • Apollon schrieb:

    Knuddlbaer schrieb:

    und wie kommt man an die nötigen Daten rann ?

    Hoe? Man hat doch freien Zugriff drauf... Ach! Du meinst von aussen?! Nochmal: man reicht nicht Daten rum, sondern Objekte.

    Davon das Du Deine Aussage wiederholst, wird sie nicht besser. Was fange ich mit einem Objekt an, das ich übergeben bekommen habe ? Was bringt mir ein Objekt, das Berechnungen vornimmt wenn man die Daten nicht verwenden kann ?



  • Badestrand schrieb:

    Ich fände so einen Artikel auch interessant! Wie sollte er denn aufgemacht sein? Generelles Klassen-Design vor dem eigentlich Programmieren (also Planung) mit Fallbeispielen oder wie?
    Und komplett ohne Getter? Weil einige Daten muss man ja rausholen?

    Mir geht es nicht um allgemeines OOD. Mir geht es wirklich um diese Getter/Setter-Sache. Ich pers. kann es mir halt nicht vorstellen. Es gibt natürlich hier und da Situationen, wo man ohne diese auskommt. Aber das klassische Beispiel ist z.B. das mit dem Modell. Oder ein anderes Beispiel:

    class Widget
    {
       public:
          void setPosition(Point);
          Point getPosition();
    };
    

    Sorry, aber wenn etwas eine Eigenschaft hat (z.B. eine 2D-Koordinate), wie soll ich das anders machen?
    Und size() von vector ist auch nur ein getter. Genauso wie resize() auch ein setter ist. Fehlt nur das Prefix set oder get bzw. sie heißen anders. Aber der Effekt ist der gleiche.

    Oberes Beispiel würde wohl so werden:

    class Widget
    {
       public:
          void move(Point);   // das gleiche wie setPosition
          Point position();   // das gleiche wie getPosition
    };
    

    Ist aber am Ende auch nur getter/setter.

    Also, mich würden solche realen Szenarios interessieren, wenn ich eine Entität habe (wie das Model im MVC-Pattern!). Weil normalerweise bekommt man nur zurecht geschnittene Szenarios präsentiert. Aber es gibt soviele GUI-Libs die alle mit getter/setter arbeiten... ich wills jetzt endlich mal konkret wissen, wie man das anders lösen könnte.



  • Du machst den Koordinatenpunkt public. Da die Semantik von set es sowieso nicht zuläßt, Konsistenzprüfungen vorzunehmen, brauchst Du natürlich auch keinen Setter mehr. Und für eine public Koordinate brauchst Du natürlich auch keinen Getter mehr.



  • scrub schrieb:

    Du machst den Koordinatenpunkt public. Da die Semantik von set es sowieso nicht zuläßt, Konsistenzprüfungen vorzunehmen, brauchst Du natürlich auch keinen Setter mehr. Und für eine public Koordinate brauchst Du natürlich auch keinen Getter mehr.

    In dem GUI-Fall musst du aber auf die Positions-Veränderung reagieren, indem du dein Widget verschiebst. So einfach ist es dann doch nicht.



  • Naja, ich vertrete die Meinung auch nicht selbst, sondern das ist das, was ich davon verstehe. Ich finde es auch nicht sinnvoll. Insofern habe ich keine Ahnung, wie das Problem in einer "in dem GUI-Fall" damit anzugehen wäre.



  • Knuddlbaer schrieb:

    Apollon schrieb:

    Knuddlbaer schrieb:

    und wie kommt man an die nötigen Daten rann ?

    Hoe? Man hat doch freien Zugriff drauf... Ach! Du meinst von aussen?! Nochmal: man reicht nicht Daten rum, sondern Objekte.

    Davon das Du Deine Aussage wiederholst, wird sie nicht besser. Was fange ich mit einem Objekt an, das ich übergeben bekommen habe ? Was bringt mir ein Objekt, das Berechnungen vornimmt wenn man die Daten nicht verwenden kann ?

    Beispiel MVC-Pattern: ich muß doch wissen, woher ich die Daten des Models bekomme, wenn ich das View bin.

    Eine andere Möglichkeit wäre, das ich beim Update gleich die Daten bekomme.

    class Widget
    {
         public:
              void update(Model);
    };
    

    Wäre eine Möglichkeit. Aber wie soll sich die View (Widget) beim Model abmelden, wenn es das Model nicht kennt? Man könnte es extern lösen, aber wäre es nicht einfacher, wenn sich das Widget selber im Dtor vom Model abmeldet? Dazu muß ich aber ein Widget::setModel(Model) haben...

    class Widget
    {
         Model *model;
         public:
              void setModel(Model *m)
              {
                   model = m;
              }
              ~Widget()
              {
                   model->remove(this); // beim Model abmelden
              }
    };
    

    Ihr merkt, hier ist einfach Praxismangel vorhanden, wenn man ohne Getter/Setter auskommen soll.



  • scrub schrieb:

    Du machst den Koordinatenpunkt public. Da die Semantik von set es sowieso nicht zuläßt, Konsistenzprüfungen vorzunehmen, brauchst Du natürlich auch keinen Setter mehr. Und für eine public Koordinate brauchst Du natürlich auch keinen Getter mehr.

    Public-Variablen widerspricht aber der OO-Philosophie! Und außerdem will ich sehr wohl eine Prüfung beim setPosition (oder move) durchführen, z.B. keine negativen Koordinaten erlauben.



  • Mir wurde und wird aber entgegnet, dies sei durch "die Semantik" von Set verboten. Setter dürfen nicht auf Konsistenz prüfen, heißt es.
    Das ist wirklich kein Witz und keine Erfindung von mir... das ist die Argumentation. Der Setter darf nur setzen, sonst nichts. Also kann man, wenn man einen Setter anbietet, die Variable auch gleich public machen.


Anmelden zum Antworten