programmierBar

argh...neu statt edit :(
 
Zuletzt bearbeitet:
Nochmal: Mich interessiert der innere Zustand nicht. Deswegen Getter. Damit bekomme ich Informationen aus dem Objekt raus, ohne den internen Zustand kennen zu müssen. Beispiel:

Code:
class Benutzer {
     public string VollständigerName() {
          if(spitzname) return name + " '" + spitzname +  "' " + nachname;
          return name + " "  + nachname;
     }
}
Es wäre nicht Aufgabe der Mailklasse den vollständigen Namen des Benutzers zusammenzustückeln.

War mir klar, dass das Beispiel kommt ;) Natürlich möchtest du der Email-Klasse überlassen, wie sie Email-Adressen formuliert! Dem User ist absolut egal, wie das legitime Format einer vollständigen Emailadresse ist. Das interessiert nur das Objekt, das die Email versendet.


Was ist dein
Code:
void einschreiben(Student student) raises EinschreibenFehlgeschlagenException;
denn anderes als ein Setter?

Das ist irgendwas! Klar füge ich dem Objekt den Nutzer zu. "einschreiben" ist aber eine Methode der Funktion mit einem Parameter und nicht ein Manipulator eines Objektfeldes.

Willst du etwa dass die Vorlesung für sämtliche Aktionen zuständig ist, die mit der Liste der Studenten möglich ist? Also drucken, als HTML ausgeben, als PDF ausgeben, per Mail an den Dozenten verschicken? Dann muss man für jede neue Aktion das Objekt verändern. *DAS* ist schlechtes Design. Da landen wir beim gleichen Problem wie beim Benutzer-Objekt. Willst du jetzt die Vorlesung auch zu einer Entität degradieren und die Logik wieder an eine anderes Klasse delegieren? Da dreht man sich nur wieder aufs neue im Kreis.

Dann gibt es ein Objekt, das HTML erzeugt. Es ist ein "Helper"-Objekt der Klasse Vorlesung. Der Vorlesung sagst du dann "vorlesung.print_students_as_html()" oder "vorlesung.print_students_as_pdf()". Intern wird dann die Helperklasse getriggert, die für den Druckmechanismus verantwortlich ist.

Irgendwo muss ich das ja ändern, wenn ich neue Funktionen hinzufügen möchte. Das Vorlesungs-Objekt bekommt also eine neue Methode und zusätzlich, wenn man die Funktionalität kapseln möchte, eine private Helper-klasse.

Wenn du den Zustand eines Objektes von außen nicht manipulieren willst, dann darf keine einzige Methode deiner Klasse Parameter erwarten, denn jede könnte den Zustand deines Objektes ändern.

Nein, das habe ich nicht gesagt! Setter setzen ein Feld des Objektes! Ich habe nicht gesagt, dass es keinen eingehenden Datenverkehr geben darf! Es darf nur nicht unkontrolliert von außen auf Felder zugegriffen werden. Eine Methode mit Parametern erfüllt eine bestimmte Funktion auf Basis von seinem eigenen State und den Parametern.
 
Zuletzt bearbeitet:
Ich verstehe dich da nicht, es geht fast immer da drum den internen Zustand eines Objektes zu manipulieren. Wie willst du zu einer Liste ein neues Objekt hinzufügen wenn du den Zustand nicht verändern darfst?

Edit: Irgendwie hab ich das Gefühl wir meinen verschiedene Sachen, aber ich habe nicht die geringste Vorstellung was du meinst.

Ja wir reden offensichtlich aneinander vorbei. Mir geht es bei gettern und settern nicht darum, dass man den State eines Objektes garnicht verändern kann. Wenn es im Rahmen einer Funktionalität eines Objektes passiert ist es legitim. Das ist dann aber kein Setter mehr! Mir geht es um ein tumbes

Code:
void setFoo(Foo foo) {

 this.foo = foo;

}

Das ist schlicht unnütz und gefährlich! Getter und Setter reichen den State nach außen damit dort damit gearbeitet werden kann. Ich wiederhole mich gern. Das interessiert dort nicht. Das ist interner State des Objektes!
 
War mir klar, dass das Beispiel kommt ;) Natürlich möchtest du der Email-Klasse überlassen, wie sie Email-Adressen formuliert! Dem User ist absolut egal, wie das legitime Format einer vollständigen Emailadresse ist. Das interessiert nur das Objekt, das die Email versendet.
Ich weiß nicht, was du mir damit jetzt sagen willst. Ich habe nicht behauptet, dass das Benutzer-Objekt dem Email-Objekt die Adresse zusammenbasteln soll.

Das ist irgendwas! Klar füge ich dem Objekt den Nutzer zu. "einschreiben" ist aber eine Methode der Funktion mit einem Parameter und nicht ein Manipulator eines Objektfeldes.
Nichts anders ist ein Setter!

Dann gibt es ein Objekt, das HTML erzeugt. Es ist ein "Helper"-Objekt der Klasse Vorlesung. Dieser sagst du dann "vorlesung.print_students_as_html()" oder "vorlesung.print_students_as_pdf()". Irgendwo muss ich das ja ändern, wenn ich neue Funktionen hinzufügen möchte. Das Vorlesungs-Objekt bekommt also eine neue Methode und zusätzlich, wenn man die Funktionalität kapseln möchte, eine private Helper-klasse.
Und genau das extrem schlechtes Design. Da versteigst du dich in Helfer-Klassen und zusätzlichen Methoden obwohl du eigentlich nur eine Funktion brauchst die dir eine Liste der Studenten zeichnet.

Gutes Design wäre:
Code:
class Vorlesung {
      private List<Student> studenten;

      List<Student> ListeDerStudenten() {
          return studenten.copy();
      }
}

Nein, das habe ich nicht gesagt! Setter setzen ein Feld des Objektes! Ich habe nicht gesagt, dass es keinen eingehenden Datenverkehr geben darf! Es darf nur nicht unkontrolliert von außen auf Felder zugegriffen werden. Eine Methode mit Parametern erfüllt eine bestimmte Funktion auf Basis von seinem eigenen State und den Parametern.
Genau das tun Setter. Setter verändern kontrolliert den Zustand eines Objektes. Unkontrolliert wäre eine öffentliche Eigenschaft.

Um das vielleicht nocheinmal klarzustellen: Getter und Setter sind eben keine direkten Manipulatoren von Objektfeldern. Sie sind eine öffentliche Schnittstelle und es ist Aufgabe des Objektes sicherzustellen, dass durch die Benutzung der Getter und Setter das Objekt in einem konsistenten Zustand verbleibt.
 
Zuletzt bearbeitet:
Ich weiß nicht, was du mir damit jetzt sagen willst. Ich habe nicht behauptet, dass das Benutzer-Objekt dem Email-Objekt die Adresse zusammenbasteln soll.

Nichts anders ist ein Setter!

Dann gibt es ein Objekt, das HTML erzeugt. Es ist ein "Helper"-Objekt der Klasse Vorlesung. Dieser sagst du dann "vorlesung.print_students_as_html()" oder "vorlesung.print_students_as_pdf()". Irgendwo muss ich das ja ändern, wenn ich neue Funktionen hinzufügen möchte. Das Vorlesungs-Objekt bekommt also eine neue Methode und zusätzlich, wenn man die Funktionalität kapseln möchte, eine private Helper-klasse.
Und genau das extrem schlechtes Design. Da versteigst du dich in Helfer-Klassen und zusätzlichen Methoden obwohl du eigentlich nur eine Funktion brauchst die dir eine Vorlesung Zeichnet. Gutes Design wäre:

Code:
class Vorlesung {
      private List<Student> studenten;

      List<Student> GetStudentenListe() {
          return studenten.copy();
      }

}

Genau das tun Setter. Setter verändern kontrolliert den Zustand eines Objektes. Unkontrolliert wäre eine öffentliche Eigenschaft.


Oh Contrair! Was für Kontrolle?

Ein sauberes Design wäre:

Code:
class Vorlesung {
      private List<Student> studenten;

      void printList(IVLPrinter printer) {
          return printer.print(this.studenten);
      }

      boolean is_contender(Student student) {
            return studenten.contains(student);
      }

      ...

}

Auf diese Art und Weise erlaube ich nur dem Printer den Zugriff auf die Liste der Studenten, niemanden sonst. Gebe ich ihm noch eine Immutable List oder eine Deep-Copy der Liste, kann ich auch sicher sein, dass nicht ein IVLPrinter injiziert wird, der doch mal an der Liste herumspielt
 
Zuletzt bearbeitet:
Wir haben ein unterschiedliches Verständnis von Settern.
 
Ein sauberes Design wäre:

Code:
class Vorlesung {
      private List<Student> studenten;

      void printList(IVLPrinter printer) {
          return printer.print(this.studenten);
      }
Ja. Etwas übertrieben vielleicht, aber das ist Ansichtssache und kommt auf den Einzelfall an.
Code:
      boolean is_contender(Student student) {
            return studenten.contains(student);
      }

      ...

}
Da stimme ich ohne Einschränkung zu.
Gebe ich ihm noch eine Immutable List oder eine Deep-Copy der Liste
War immutable nicht vorhin noch schlechtes Design? ;) Wie gesagt, das selbe erreichst du mit einem GetStutendList auch.
Wir haben ein unterschiedliches Verständnis von Settern.
Offensichtlich. :) Das Problem das ich sehe, ist, dass es von außen einfach nicht erkennbar ist, ob ein Setter ein „echter“ Setter ist oder nicht. Das kann mal der Fall gewesen sein. Aber evtl. ist seit Einführung des Setters das Feld für das er mal zuständig war nicht mehr existiert. Ist es deswegen kein Setter mehr? Und woran sollte man das von außen erkennen?
 
Zuletzt bearbeitet:
Ja. Etwas übertrieben vielleicht, aber das ist Ansichtssache und kommt auf den Einzelfall an.
Da stimme ich ohne Einschränkung zu.

Nicht übertrieben, sondern defensiv ;) Ich hab schon Pferde kotzen sehen, direkt vor der Apotheke *grins* Defensive Programmierung ist die halbe Miete, Systeme testbar und sicher zu halten.

Offensichtlich. :) Das Problem das ich sehe, ist, dass es von außen einfach nicht erkennbar ist, ob ein Setter ein „echter“ Setter ist oder nicht. Das kann mal der Fall gewesen sein. Aber evtl. ist seit Einführung des Setters das Feld für das er mal zuständig war nicht mehr existiert. Ist es deswegen kein Setter mehr? Und woran sollte man das von außen erkennen?

Wenn er kein echter Setter mehr ist, verdient er den Namen nicht mehr. Die Implementierung bricht dann den Vertrag, den man mal mit den nutzenden Objekten eingegangen ist. Tut die Methode mehr als nur setFoo, bekommt sie einen anderen, passenden Namen - Refactoring sei dank.

Edit: Hab auf der Vorseite noch was ergänzt.
 
War immutable nicht vorhin noch schlechtes Design? ;) Wie gesagt, das selbe erreichst du mit einem GetStutendList auch.

Ja schlechtes Design bei Gettern *grins*

Erreichst du das wirklich? Mit dem Getter darf jeder, der sich im Namespace befindet, die Liste erhalten. In meinem Design darf das nur der Printer!
 
Ja schlechtes Design bei Gettern *grins*
Da kann man bei Java sowieso nicht von sprechen. ;)

Erreichst du das wirklich? Mit dem Getter darf jeder, der sich im Namespace befindet, die Liste erhalten. In meinem Design darf das nur der Printer!
Ja und? Ist alles nur eine Frage inwieweit man das Design unnötig verkompliziert.
 
Ja und? Ist alles nur eine Frage inwieweit man das Design unnötig verkompliziert.

Was verkompliziert da? Das sorgt nur dafür, dass wirklich nur der mit den Daten operiert, der sich dafür interessieren darf! Ich rede hier nicht von 500 Zeilen Code sondern eher von >10.000.. Da brauchst du sowas!
 
Etwas, das bei meinem Design hinzu kommt, ist dass ich in der Implementierung der Vorlesung sehe, wem ich die Liste der Studenten zukommen lasse. In deinem ist nicht der Fall. Das nenne ich Kontrolle!
 
Was verkompliziert da?
Weil du für jede neue Aktion ein neues Interface brauchst. Wenn du die Studentenliste nach allen Studenten mit Anfangsbuchstabe "A" suchen willst brauchst du entweder ein neues Interface, missbrauchst eine Printer-Klasse oder nimmst einfach die Kopie der Studentenliste die dir schon zur Verfügung steht.

Das sorgt nur dafür, dass wirklich nur der mit den Daten operiert, der sich dafür interessieren darf!
Wayne? Wenn das wirklich so kritisch ist gibt es eben keinen Getter. Aber das jemand das Printer-Interface mißbraucht kann das auch nicht verhindern.
 
Zuletzt bearbeitet:
Weil du für jede neue Aktion ein neues Interface brauchst. Wenn du die Studentenliste nach allen Studenten mit Anfangsbuchstabe "A" suchen willst brauchst du entweder ein neues Interface, missbrauchst eine Printer-Klasse oder nimmst einfach die Kopie der Studentenliste die dir schon zur Verfügung steht.

Warum willst du von außen nach der Liste aller Studenten mit dem Anfangsbuchstaben 'A' suchen? Das ist genauso sinnvoll wie ein Getter.

Du wirst die Printerklasse nicht missbrauchen (das ist übrigens ein Interface, welches von verschiedenen Printern implementiert werden kann). Wenn du dann eine Sucherklasse das Printerinterface implementieren läßt, hast du dort eine Methode print, die nicht druckt, sondern nach was sucht. Was immer du mehr mit den Daten der zur VL gehörigen Studenten anstellen möchtest, musst du die Vorlesungs-Klasse erweitern. Den Code, der das gewünschte tut, musst du dann so oder so schreiben, ob er in der Vorlesungsklasse steht oder auch nicht..
 
Warum willst du von außen nach der Liste aller Studenten mit dem Anfangsbuchstaben 'A' suchen? Das ist genauso sinnvoll wie ein Getter.
Aus dem selben Grund aus dem ich die Liste drucken will. Wenn keine Informationen aus den Klassen nach außen dringen dürfen, kann ich gleich aufhören zu Programmieren.

Du wirst die Printerklasse nicht missbrauchen (das ist übrigens ein Interface, welches von verschiedenen Printern implementiert werden kann).
Weil?
 
Weil du für jede neue Aktion ein neues Interface brauchst. Wenn du die Studentenliste nach allen Studenten mit Anfangsbuchstabe "A" suchen willst brauchst du entweder ein neues Interface, missbrauchst eine Printer-Klasse oder nimmst einfach die Kopie der Studentenliste die dir schon zur Verfügung steht.

Wayne? Wenn das wirklich so kritisch ist gibt es eben keinen Getter. Aber das jemand das Printer-Interface mißbraucht kann das auch nicht verhindern.

Das ist dann offensichtlich, weil bei einem einfachen Code Review zu sehen ist, dass eine Klasse Search das Interface IVLPrinter implementiert und ganz merkwürdige Sachen in der Methode print tut. Das ist nicht zu sehen, wenn man quer durch die Anwendung Zugriff auf ein Objekt erlaubt ist, das zu einer Klasse gehört.

Ja es gibt dann keinen Getter.. Und was, wenn du doch mit den Daten operieren musst? ;) Du misst da mit zweierlei Maß!
 
Aus dem selben Grund aus dem ich die Liste drucken will. Wenn keine Informationen aus den Klassen nach außen dringen dürfen, kann ich gleich aufhören zu Programmieren.

Ich habe nicht gesagt, dass keine Informationen aus den Klassen heraus dürfen. Du übertreibst maßlos oder willst mich mit Absicht nicht verstehen.

> Weil?

Weil es offensichtlich ist, dass er verbotenes tut!

Wenn du auf ein Feld von außen zugreifst, ist das nicht ersichtlich!
 
Der selbe Satz hätte von mir stammen können.

Ich glaube wir können die Diskussion hier abbrechen, das führt zu nichts.

Mal wieder ;)

Für und Wider wurde erörtert.. sollen die Anderen sich durch die letzten zwei Seiten wälzen. Macht bestimmt Spaß *grins*

So, Prost! Schönen Abend!
 
guude,
Ich bin strikter Verfechter des Grundsatzes, dass Getter evil sind und Setter faktisch unnötig, und das in jeder Sprache!. Warum? Wenn ich ein Feld an einem Objekt setzen will, setze ich das Feld. Wenn ich beim Setzen noch mehr mache, als das Feld zu setzen, ist es kein Setter mehr, ergo: unnötig.
was meinste du denn mit noch mehr setzen? wie setzt du denn das feld sonst, mit einer methode vom objekt?

Getter wiederum zeigen, dass ich außerhalb des Objektes ein Implementierungsdetail benötige. Das zeigt mir aber, dass mein Design schlecht ist. Was interessiert mich außerhalb eines Objektes ein bestimmtes Feld, dass dort verwendung findet? Besser ist es doch, den die gewünschte Arbeit machen zu lassen, der davon ahnung hat, in diesem Fall das Objekt mit dem Feld, anstatt es außerhalb zu manipulieren.
du wuerdest also dem objekt eine methode schreiben, um sich selbst anzuzeigen? also anstatt einem getName eine methode print die einfach den namen anzeigt?

Das fällt einem spätestens dann auf die Füße, wenn die Implementierung des Objektes mit dem Feld nicht von einer Manipulation von Außen ausgeht. ("Der Getter sollte ja nur den Status zurückgeben, ein Programmierer verändert aber jetzt das Feld -> call by reference -> das Objekt verändert sich") Und dann knallt es weil es zu Seiteneffekten kommt.

also ich lese diesen kompletten - nicht nur den quote - post nun bestimmt zum 10. mal aber ich verstehe ihn nicht. ich dachte immer bzw. bekam "eingetrichtert" das getter und setter das gegenteil von evil sind, und von guten programmierstil zeugen.

koenntest du das mal etwas genauer und langsamer schreiben :D oder ein codeschnipsel, gib mir irgendwas, ich wills doch nur verstehen ... :)

regards,
buk
 
Zurück
Oben Unten