Schlechter Stil wenn man alle public: hat?



  • Ich finde es grundsätzlich merkwürdig, wenn jemand Klassen mit zig get/set schreibt und die wirklich auch nur das tun. Das hat überhaupt nichts mit OOP zu tun und man kann die Member gleich alle public machen. Wenn ein set aber noch eine andere Funktion erfüllt, nämlich z.B. weitere Abhängigkeiten aktualisieren usw. dann ist es natürlich etwas anderes. Am liebsten wäre mir wenn C++ so etwas wie Properties bekäme und man Variablen einfach mit obj.var holen bzw. setzen könnte. Noch schöner ist es allerdings, wenn man vom internen Aufbau des Objektes überhaupt nichts von außen mitbekommt. Aber dass dies nicht immer ganz einfach ist brauche ich wohl nicht erwähnen.



  • Naja, der VC hat als Erweiterung Properties im Angebot. Das endet auch nur daran, das man set und get schreiben muss. Der Aufwand beim Programmieren ist so der gleiche, die Verwendung schaut dann anderst aus.

    Alt:

    class T
    {
      int m_member;
    public:
       int member();
       void member(int i);
    }
    
    T t;
    
    t.member(12);
    int a = t.member();
    

    Im VC mit der neuen Erweiterung:

    class T
    {
      int m_member;
    
    public:
       property member()
       {
          int get();
          void set(int i);
       }
    }
    
    T t;
    
    t.member = 12;
    int a = t.member;
    

    Das Problem ist viel mehr der Aufwand die get und set Methoden zu schreiben.
    Daher neigt man dazu, einfach ein public: davor zu schreiben.

    ABER

    Wenn jetzt eine Änderung im Quellcode notwendig wird und man plötzlich vor Verwendung des Members abfragen machen muss, wird es schwer, da sich das Interface ändert. (Mit dem property im VC geht es noch, da bleibt wenigstens der Clientcode gleich, ggf muß man aber alles neu Übersetzen, muss ich jetzt passen).

    UND

    mittels get und set kann man steuern ob nur geschrieben , nur gelesen oder gelesen und geschrieben werden kann.

    Das was man an Zeit durch ein einfaches "public:" spart, kann einen hinterher mehrfach diese kosten.

    Es macht manchmal sinn einfach public zu nehmen (siehe oben) aber es ist mit entsprechenden Nachteilen behaftet und wird bei bedarf entsprechend bestraft. (Die Strafen fallen mit zunehmender Erfahrung aber geringer aus :D)



  • Why getter and setter methods are evil:
    http://www.javaworld.com/javaworld/jw-09-2003/jw-0905-toolbox.html

    Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.



  • mathik schrieb:

    Don't ask for the information you need to do the work; ask the object that has the information to do the work for you.

    Und wer hat die Getter und Setter? Das Objekt. Also macht doch mit den Gettern und Settern das Objekt die Arbeit.

    Und wenn Faulheit ein Grund ist schlechten Code zu schreiben, dann hat man offnsichtlich seinen Beruf verfehlt.



  • Vielleicht solltest du nicht alles in Klassen packen, sondern manchmal ganz einfach Strukturen verwenden, wenn das ding sowieso keine Funktionen hat.
    Falls es in einer Klasse wirklich so viele attribute gibt, auf die du zugreifen musst, dann könnte das auch an nem schlechten design liergen. Vielleicht in mehrere Klassen aufteilen, oder ganz umstrukturieren. Die Klassen sollen doch was tun (render, move,...) und nicht nur als Datencontainer dienen.



  • Was stört euch jetzt hauptsächlich? Die Schreibarbeit um getter/setter zu schreiben? Dann besorgt euch vernünftige C++ Tools! 😃 Ein Beispiel? Hier:

    Membervariable _mymember angelegt:
    http://www.kharchi.de/files/cpp/getter1.png

    Kontextmenü zu der Memebervariable geöffnet um Getter/Setter autom. generieren zu lassen:
    http://www.kharchi.de/files/cpp/getter2.png

    Fertig 🙂 :
    http://www.kharchi.de/files/cpp/getter3.png

    So, da mache ich mir heute keinen Kopf drüber, ob es mich Schreibarbeit kostet. Weil es nunmal ruckzuck mit zwei Mouseclicks geht. Vernünftige C++ Tools vorausgesetzt. 😉

    Members sollte man immer kapseln. Wobei ich pers. folgender Regel nachgehe:
    1. Alle Memebervariablen private.
    2. Getter und Setter erstelle ich erst nach Bedarf.
    3. Selbst wenn Getter und Setter nichts großartiges machen, machen sie Sinn. Weil was ist, wenn ich später doch mehr machen muß? Z.B. eine Statusänderung vermerken muß? Wenn ich die Members public habe, wird das schwierig. Selbst wenn ich es nachträglich private mache, werden woanders Compile-Errors auftauchen, die man beheben darf. Was auch Arbeitszeit kostet.



  • Igit! Was soll der unterstrich vor dem Variablen namen? Und wieso haben die getter und setter keine Namen mit denen man sie auch als soclhe erkennt? Also getDing und setDing.



  • Ist das dein Problem, ob ich einen Unterstrich davor mache, oder meines? Und ob ich get und set davor haben will, ist ja wohl auch mein Problem. Um dich aber zu beruhigen: man kann es selbst konfigurieren, was generiert werden soll!



  • _beruhigt.



  • Artchi schrieb:

    [...] Weil was ist, wenn ich später doch mehr machen muß? [...]

    Visitor-Pattern.



  • Apollon schrieb:

    Artchi schrieb:

    [...] Weil was ist, wenn ich später doch mehr machen muß? [...]

    Visitor-Pattern.

    Wayne?
    Es geht doch um getter und setter oder public zugriff.

    vorher

    class abc {
      public int i;
    }
    
    //an 1045 stellen
    abc.i = x;
    

    jetzt soll i nie 0 sein können, oder sonst was...

    class abc {
      private int i;
      public setI(int i) {
        if i == 0 throw exception
        this.i = i
      }
    }
    
    //an 1045 stellen ändern
    abc.setI(x);
    

    Was soll ich jetzt da mit dem visitor pattern?

    MFG



  • Setter verletzen das Information-Hiding-Prinzip. Das macht dann natuerlich das Pattern ueberfluessig. Und ganz nebenbei, meine Antwort bezog sich, wie deutlich zu erkennen auf das Zitat und nicht auf Getter/Setter.



  • Apollon schrieb:

    Setter verletzen das Information-Hiding-Prinzip. Das macht dann natuerlich das Pattern ueberfluessig.

    😕 Kannst du mir mal ein vernünftiges Beispiel zeigen, bei dem man das Visitor pattern einsetzt anstelle eines setters?

    Und ganz nebenbei, meine Antwort bezog sich, wie deutlich zu erkennen auf das Zitat und nicht auf Getter/Setter.

    So wie du zitierst macht der (Neben)Satz für mich keinen Sinn. Wenn ich mir den Satz davor anschau, dann schon.

    Selbst wenn Getter und Setter nichts großartiges machen, machen sie Sinn. Weil was ist, wenn ich später doch mehr machen muß?

    Und dann gehts doch um setter und getter.
    Oder was soll

    Weil was ist, wenn ich später doch mehr machen muß?

    bedeuten?



  • Also wie mir ein Visitorpattern anstatt eines Setters helfen soll, frage ich mich ehrlich.

    Ausgangssituation:

    class A
    {
    public:
      int b;
    };
    
    int main()
    {
        A a;
        a.b = 1;
    }
    

    So, irgendwann will ich das Verhalten der Klasse A so ändern:

    class A
    {
      private:
          int b;
          bool changed;
    
      public:
          void serB(int b)
          {
               if(b != this->b)
                   changed = true;
               this->b = b;
          }
          int getB()
          {
               return b;
          }
    };
    
    int main()
    {
        A a;
        a.setB(1);
    }
    

    1. Wenn ich vorher alles public hatte, nur weil bei setten nicht viel passiert, habe ich ein Problem, wenn ich es später doch private setze, weil ich mehr machen will. Z.B. Status ändern. Ich muß im gesamten Projekt die Compile-Errors beheben. Wenn es sich um eine verbreitete Klasse oder Library handelt, habe nicht nur ich ein Problem, sondern auch alle anderen Nutzer. Schlecht wenn sich auf einmal die API stark ändert.

    2. Wie kann mir bei einer Schnittstellenänderung bitte ein Visitorpattern helfen?

    Also, ich mache lieber von Anfang an alles private, selbst wenn ein setter nicht viel macht. Aber ich kann so viel flexibler das Verhalten einer Klasse ändern, ohne das der Klassenbenutzer etwas davon mitbekommen. DAS ist Kapselung. Und nicht wenn der Benutzer nachher bei einem Update der Klasse/Lib vor einem Compile-Error-Wald steht. 👎



  • Eigentlich sollten sich Schnittstellen nicht aendern und Member gegen Zugriffe von aussen geschuetzt werden (private und keine Getter/Setter). Solltest Du dann die Klasse um weitere Funktionalitaet erweitern wollen (spaeter mehr machen), hilft dir da das Visitor-Pattern. Und im gutem Design gehoeren konkrete Klassen sowieso nicht zur Schnittstelle.



  • Und im gutem Design gehoeren konkrete Klassen sowieso nicht zur Schnittstelle.

    Stimmt, also auch keine Public-Attribute. Thema erledigt, nächstes Problem bitte.



  • Apollon schrieb:

    Eigentlich sollten sich Schnittstellen nicht aendern und Member gegen Zugriffe von aussen geschuetzt werden (private und keine Getter/Setter). Solltest Du dann die Klasse um weitere Funktionalitaet erweitern wollen (spaeter mehr machen), hilft dir da das Visitor-Pattern.

    Wenn ich später neue Funktionen brauch, dann kann ich die auch so dazu machen, da brauch ich nicht das Visitor pattern. Es ging aber auch nie darum weitere funktionen einzubauen, sondern beim setzen eines Wertes noch etwas zusätzliches zu machen.

    Und im gutem Design gehoeren konkrete Klassen sowieso nicht zur Schnittstelle.

    Was verstehst du unter Schnittstelle?

    Ist das hier schlechtes Design oder wie würdest du das machen?
    http://java.sun.com/j2se/1.4.2/docs/api/java/sql/Statement.html
    http://java.sun.com/j2se/1.4.2/docs/api/java/sql/PreparedStatement.html
    Wie soll ich den Daten abfragen oder setzen ohne getter und setter?

    PS: Ich mach den Witz gleich, dann braucht ihr ich nicvht mehr machen: Java ist sowieso schlechtes Design. Muhahaha...



  • Worauf willst du hinaus? Diese Methoden setzen doch einen Parameter auf einen gewissen wert, oder holen einen Parameter als einen bestimmten wert. Hiermit will man doch gar keine Attribute der Klasse auslesen oder setzen.



  • Knuddlbaer schrieb:

    Naja, der VC hat als Erweiterung Properties im Angebot. Das endet auch nur daran, das man set und get schreiben muss. Der Aufwand beim Programmieren ist so der gleiche, die Verwendung schaut dann anderst aus.

    Alt:

    class T
    {
      int m_member;
    public:
       int member();
       void member(int i);
    }
    
    T t;
    
    t.member(12);
    int a = t.member();
    

    Im VC mit der neuen Erweiterung:

    class T
    {
      int m_member;
    
    public:
       property member()
       {
          int get();
          void set(int i);
       }
    }
    
    T t;
    
    t.member = 12;
    int a = t.member;
    

    Das Problem ist viel mehr der Aufwand die get und set Methoden zu schreiben.

    Was spräche denn gegen eine Erweiterung die das explizite hinschreiben der getter/setter Methoden unnötig macht wenn sie nicht mehr machen als den Wert rauszugeben bzw. zu setzen? Das wäre dann wieder so was ähnliches wie public, aber soweit ich weiß kann man keine Pointer auf Properties holen. Richtig?



  • Eigentlich nichts, außer vielleicht dass es ein sehr sehr spezielles Problem löst. Dann doch lieber richtige properties so wie in der VC-Erweiterung. Damit kriegste das auch alles. Wenn dann die einfachen getter/setter noch generierbar sind finde ich das recht komfortabel.


Anmelden zum Antworten