programmierBar

wegus

MU Team
Thread Starter
Dabei seit
13.09.2004
Beiträge
18.946
Reaktionspunkte
6.670
Getter/Setter sind ganz bestimmt nicht evil :)

Sie sind in ihrer Standardform redundantes Zeug. Da gefällt mir der Ansatz von z.B. Ruby ganz gut, die Getter/Setter implizit erzeugen können wenn gewünscht. Erst dann wenn ich spezielle Getter ( etwa mit Type-Casting) oder Setter mit Zusatzaktionen (Converter,...) benötige muß man sie wirklich hinschreiben.

Generell sind Getter/Setter die Werkzeuge um den Zugriff auf Attribute kanalisiert laufen zu lassen, die Kontrolle dafür der Instanz zu überlassen ( so kann ein Attribut ja auch temporär gesperrt sein) und Zugriffe zu standartisieren. Dabei ist es durchaus diskutabel ob der immer wiederkehrende Mechanismus eines 1:1 Getter/Setters durch Refactoring automatisiert werden sollte ( also durch IDEs Arbeit abgenommen wird) oder ob man da mal in der Sprachdefinition ansetzt und für Standards eben auch Standard Getter/Setter etabliert wie Ruby es tut.

Ganz ohne zu arbeiten verschlankt zwar Vieles was Routinetipparbeiten angeht, geht aber eben auch wieder Risiken ein, für die man diesen Direktzugriff extra mal abgeschafft hat.
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
guude,

was meinste du denn mit noch mehr setzen? wie setzt du denn das feld sonst, mit einer methode vom objekt?

Garnicht? Darum geht es mir doch! In meiner Auffassung gibt es nur sehr wenig Gründe, ein Feld eines Objektes von außen zu setzen. Die Felder gehören dem Objekt. Nur das Objekt sollte auf den Feldern arbeiten und volle Kontrolle darüber haben, was in die Felder eingetragen wird. Sie sind Bestandteil des States dieses Objektes und nicht das eines anderen.


du wuerdest also dem objekt eine methode schreiben, um sich selbst anzuzeigen? also anstatt einem getName eine methode print die einfach den namen anzeigt?

Genau das würde ich machen :) Schließlich weißt du ja auch selbst, wie du am schönsten aussiehst *grins*

_ebm_ schrieb:
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

Das ist mit einem Codeschnipsel schwer getan, da es eher eine architekturelle Frage ist als eine programmatische.
Stelle dir eine Anwendung mit ca 100.000 Zeilen vor. In ihr existiert eine Klasse, welche eine Menge von Feldern enthält, die ihren State repräsentiert. Sie verläßt sich dabei auf eine bestimmte Menge und Form. Ich versuche ein Beispiel. Eine Instanz dieser Klasse enthält eine Tabelle mit Farben und ihren RGB-Werten. Sie weiß, dass sie dort derzeit 10 Einträge hat und ein Friend stellt diese gerade dar. Das ist aber internes Wissen der Klasse und dieses Friends.
Jetzt wird es etwas verzwickt, weil ich die Sichtweise wechsele. Die Eigenschaft ist unter den Entwicklern bekannt, die das Stück Software geschrieben haben und werden an der Liste nicht herumspielen. Jetzt kommt ein neuer Entwickler ins Team und sieht die Liste der RGB-Werte.. Praktisch? Ja! Na da kann man ja erweitern und ein wenig aufräumen. Er setzt von einer ganz anderen Codestelle, wo er ebenfalls mit Farben hantiert, die Liste um. Er verändert den State des Objektes. Es kommt also zu Seiteneffekten. Das ist aber erlaubt, weil es kein Verbot an einem Setter steht. Die Farb-Klasse hat sozusagen jetzt zwei Friends die sie manipulieren. Man kann sich jetzt gut vorstellen, dass es da heftig knallen kann.
Einige werden sagen, dass man da aufpassen muss. Ich bin der Meinung, dass man soetwas schon im Keim verhindern muss. Das heißt nicht, dass es keine Kommunikation zwischen Klassen geben darf. Allerdings sollten Felder niemals direkt gesetzt werden. Da gehört immer Sicherungsmethodik und eine gewisse Logik dazu. Somit ist diese Funktion kein Setter mehr.

Eine andere Problematik ist, dass Objekte immer per Referenz übergeben werden, man hat also immer ein und das selbe Objekt am Wickel. Da kommt das Problem mit den Gettern ins Spiel. Ein unachtsamer Programmierer läßt sich aus der Farb-Klasse die Liste der Farben geben. Er vergisst sich eine Kopie zu ziehen und manipuliert in seinem Code die Liste direkt. Er verändert also ungewollt den State des Farb-Objektes. Auch hier: währet den Anfängen. Man könnte soetwas sicherlich durch Immutables verhindern. Aber erstens denkt nicht jeder Programmierer daran und zweitens ist das nur eine programmatische Absicherung. Nimmt man die Kapselung in das Immutable nicht vor, geht es wieder. Löst man es durch die Architektur, ist es deutlich aufwändiger, dort ein Problem zu verursachen.

Ich hoffe, das klärt, warum ich es für geschickter halte, etwas von der Klasse machen zu lassen, die über die benötigten Daten am besten bescheid weiß, nämlich der Klasse, die diese Daten als State hat. Verteilt sich dabei das Wissen auf mehrere Klassen, ist das Design missglückt.

Gruß Carsten
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: buk

Darii

Aktives Mitglied
Dabei seit
24.02.2004
Beiträge
2.101
Reaktionspunkte
129
Stelle dir eine Anwendung mit ca 100.000 Zeilen vor. In ihr existiert eine Klasse, welche eine Menge von Feldern enthält, die ihren State repräsentiert. Sie verläßt sich dabei auf eine bestimmte Menge und Form. Ich versuche ein Beispiel. Eine Instanz dieser Klasse enthält eine Tabelle mit Farben und ihren RGB-Werten. Sie weiß, dass sie dort derzeit 10 Einträge hat und ein Friend stellt diese gerade dar. Das ist aber internes Wissen der Klasse und dieses Friends.
Jetzt wird es etwas verzwickt, weil ich die Sichtweise wechsele. Die Eigenschaft ist unter den Entwicklern bekannt, die das Stück Software geschrieben haben und werden an der Liste nicht herumspielen. Jetzt kommt ein neuer Entwickler ins Team und sieht die Liste der RGB-Werte.. Praktisch? Ja! Na da kann man ja erweitern und ein wenig aufräumen. Er setzt von einer ganz anderen Codestelle, wo er ebenfalls mit Farben hantiert, die Liste um. Er verändert den State des Objektes. Es kommt also zu Seiteneffekten. Das ist aber erlaubt, weil es kein Verbot an einem Setter steht. Die Farb-Klasse hat sozusagen jetzt zwei Friends die sie manipulieren. Man kann sich jetzt gut vorstellen, dass es da heftig knallen kann.
Das ist aber ein Entwurfsfehler. Wenn ein Setter unerwünschte Nebenwirkungen haben kann, dann darf man den Setter nicht schreiben.

Eine andere Problematik ist, dass Objekte immer per Referenz übergeben werden, man hat also immer ein und das selbe Objekt am Wickel. Da kommt das Problem mit den Gettern ins Spiel. Ein unachtsamer Programmierer läßt sich aus der Farb-Klasse die Liste der Farben geben. Er vergisst sich eine Kopie zu ziehen und manipuliert in seinem Code die Liste direkt. Er verändert also ungewollt den State des Farb-Objektes. Auch hier: währet den Anfängen.
Das schon wieder ein Designfehler. Den unachtsamen Programmierer trifft hier keine Schuld, wenn er von dem Objekt eine Liste der Farben bekommt, dann soll er sie auch verändern dürfen. Wenn nicht, dann hätte man im Getter die Liste nicht rausgeben dürfen. Oder nur eine Kopie davon. Oder bei C++ schreibt man dann einfach ein const neben den Rückgabetyp.

Du argumentierst die Existenzberechtigung von Gettern und Settern ins Gegenteil um. Das sind aber keine grundsätzlichen Argumente gegen Getter/Setter sondern nur gegen diese speziellen. Das ist so, als würde man while grundsätzlich verdammen, weil man damit Endlosschleifen basteln kann.

Getter und Setter sind ja gerade dazu da, um sicherzustellen, dass beim setzen von Attributen keine Nebeneffekte gibt. Und sei es nur wenn sie es durch ihre Abwesenheit tun. Setter/Getter schreibt man ja nur genau dann wenn man *will*, dass ein Attribut gesetzt werden und man weiß, dass dabei nichts schlimmes passieren kann. Sonst schreibt man sie nicht.

Aber ich gebe dir Recht, der Nutzen und Einsatz von Gettern und Setter ist hauptsächlich auf Daten-Klassen (du nennst sie Entitäten) beschränkt.
 
Zuletzt bearbeitet:

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Das ist aber ein Entwurfsfehler. Wenn ein Setter unerwünschte Nebenwirkungen haben kann, dann darf man den Setter nicht schreiben.

Das ist das Problem. Man sieht das nicht immer und im Laufe der Entwicklung eines Programmes kann sich das auch ändern. Von einer Seite möchte man ja, dass von dort aus Einfluss genommen wird. Mit dem Setter gestattet man aber *jedem*, zukünftig Änderungen vorzunehmen. Programme wachsen, sie verändern sich. Mehrere Entwickler arbeiten im Laufe der Zeit an dem Code. Da besteht die Gefahr, nicht im Entwurf.

Das schon wieder ein Designfehler. Den unachtsamen Programmierer trifft hier keine Schuld, wenn er von dem Objekt eine Liste der Farben bekommt, dann soll er sie auch verändern dürfen. Wenn nicht, dann hätte man im Getter die Liste nicht rausgeben dürfen. Oder nur eine Kopie davon. Oder bei C++ schreibt man dann einfach ein const neben den Rückgabetyp.

Ich hatte schon gesehen, dass ein Merge im VCS ein const oder Immutable hat verschwinden lassen. Und dann?

Du argumentierst die Existenzberechtigung von Gettern und Settern ins Gegenteil um. Getter und Setter sind ja gerade dazu da, um sicherzustellen, dass beim setzen von Attributen keine Nebeneffekte gibt. Und sei es nur wenn sie es durch ihre Abwesenheit tun. Setter/Getter schreibt man ja nur genau dann wenn man *will*, dass ein Attribut gesetzt werden und man weiß, dass dabei nichts schlimmes passieren kann. Sonst schreibt man sie nicht.

Es ist eine technische Möglichkeit, Probleme zu verhindern, keine architekturelle!

Ich wiederhole mich gern ;) Man sollte mit den Feldern den hantieren lassen, der sich damit am besten auskennt. Alle anderen interessiert das eher nicht, was da drin steht.
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Aber ich gebe dir Recht, der Nutzen und Einsatz von Gettern und Setter ist hauptsächlich auf Daten-Klassen (du nennst sie Entitäten) beschränkt.

Ha, Konsens? :) Die Objekte, die du Daten-Klassen nennst und ich Entitäten sind ja genau das was man möchte. Und am schönsten ist es, wenn man die Getter und Setter in Properties verstecken kann :) Für mich sind das im Endeffekt leicht aufgeblasene C-Structs, die zur Kommunikation mit komplexen Datentypen zwischen zwei Klassen dienen. Diese Structs sind für mich keine "echten Klassen", auch wenn sie es technisch sind. Sie tragen nur Daten von A nach B.
 

Darii

Aktives Mitglied
Dabei seit
24.02.2004
Beiträge
2.101
Reaktionspunkte
129
Das ist das Problem. Man sieht das nicht immer und im Laufe der Entwicklung eines Programmes kann sich das auch ändern. Von einer Seite möchte man ja, dass von dort aus Einfluss genommen wird. Mit dem Setter gestattet man aber *jedem*, zukünftig Änderungen vorzunehmen.
Was schlägst du da vor? Also statt Setter? Mehr als „private“ markieren kann ja nicht machen.

Ha, Konsens? :) Die Objekte, die du Daten-Klassen nennst und ich Entitäten sind ja genau das was man möchte. Und am schönsten ist es, wenn man die Getter und Setter in Properties verstecken kann :)
Jein. Eigentlich würde ich da nicht unterscheiden. Hab ich dir zu liebe getan. ;) Objekt ist Objekt. Mir fallen nur keine wirklichen Beispiele ein wo man Setter/Getter braucht wenn ein Objekt nicht hauptsächlich Nutzdaten enthält. Da braucht man sie dafür aber umso mehr.

Die Frage die man sich immer stellen muss: Ist ein Setter sinnvoll? Es ist wenig sinnvoll das File-Objekt eines Streams zwischendurch wechseln zu wollen, also schreibt man da weder einen getter noch einen setter.
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Was schlägst du da vor? Also statt Setter? Mehr als „private“ markieren kann ja nicht machen.

Richtig. Das Feld ist und bleibt private. Wenn man auf die Daten in dem Feld zugreifen möchte, schreibt man eine weitere Methode und zwar in der Klasse, der das Feld gehört. Diese erledigt genau das, was man mit den Daten machen möchte. So verhindert man Seiteneffekte und die Übergabe von internen Daten aus dem Rufenden sind da eindeutig gewünscht. Man hat ja Kontrolle darüber.

Jein. Eigentlich würde ich da nicht unterscheiden. Hab ich dir zu liebe getan. ;) Mir fallen nur keine wirklichen Beispiele ein wo man Setter/Getter braucht wenn ein Objekt nicht hauptsächlich Nutzdaten enthält benötigt. Dafür aber umso mehr.

Genau :) Also wirklich Konsens. Ich sehe es ja genauso. Es gibt sonst keinen Grund Setter und Getter zu verwenden. Dann bin ich ja auch dafür!

Die Frage die man sich immer stellen muss: Ist ein Setter sinnvoll? Es ist wenig sinnvoll das File-Objekt eines Streams zwischendurch wechseln zu wollen, also schreibt man da weder einen getter noch einen setter.

Siehe oben ;) Das Objekt weiß genau, welche Art von Streams es nutzen möchte, um etwas auszugeben. Unsere Ansichten sind doch näher als die letzten Seiten vermuten ließen, findest du nicht auch?
 

bjbo

Aktives Mitglied
Dabei seit
20.11.2003
Beiträge
1.327
Reaktionspunkte
82
Wahnsinn... Einigkeit unter Entwicklern. Das ich das noch erleben darf. :D
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Wahnsinn... Einigkeit unter Entwicklern. Das ich das noch erleben darf. :D

Einig sind wir uns nicht, wir haben nur festgestellt, dass unsere Ansichten recht nahe beieinander liegen ;) (siehe Trennung von Entities und Businesslogik)
 

-Nuke-

Aktives Mitglied
Dabei seit
13.09.2003
Beiträge
2.146
Reaktionspunkte
15
Gutes Design wäre:
Code:
class Vorlesung {
      private List<Student> studenten;

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

*michEinmisch*
Nein ^^ Mit diesem Design gibst du deine interne Struktur des Objektes nach außen hin frei. Das ist nicht unbedingt "gut".

Musst du nun in ein paar Jahren das Programm ändern und die Studenten statt in einer List in einer Map anordnen, musst du JEDEN Code-Teil anpassen, der diese Liste nutzt, oder du musst bei jedem Zugriff deine neue Map in eine List umkonvertieren, sofern das nach den neuen Anforderungen überhaupt möglich ist.

Die Lösung hier -> Zugriff per Iterator.

Aber das ist natürlich alles theoretisch. Will man ein Programm komplett nach allen Regeln der Kunst "gut" designen, plant man 3 Jahre, während ein schlechtes Design schon 10000 mal über die Ladentheke ging ;)
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Aber das ist natürlich alles theoretisch. Will man ein Programm komplett nach allen Regeln der Kunst "gut" designen, plant man 3 Jahre, während ein schlechtes Design schon 10000 mal über die Ladentheke ging ;)

Naja, mit etwas Erfahrung muss man nicht groß "designen". Vieles geht dann intuitiv ;) aber richtig, man kann sich zu Tode spezifizieren. Es kommt auch immer darauf an, was der Entwicklungsleiter oder der Auftraggeber möchte.
 

-Nuke-

Aktives Mitglied
Dabei seit
13.09.2003
Beiträge
2.146
Reaktionspunkte
15
Naja, mit etwas Erfahrung muss man nicht groß "designen". Vieles geht dann intuitiv ;)

Nunja, man kann nicht immer 3 Jahre voraus denken ;) Ist sehr anwendungsspezifisch. Wenn plötzlich ein ein komplett neuer Layer zwischengeschoben werden muss, dann hat man das ggf. damals nicht bedacht ;)

Wenn du deine Anwendung plötzlich im Client/Server teilen sollst und das alles per IPC/RMI machen sollst, dann kann das Ursprungsdesign plötzlich komplett daneben sein ;)
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Nunja, man kann nicht immer 3 Jahre voraus denken ;) Ist sehr anwendungsspezifisch. Wenn plötzlich ein ein komplett neuer Layer zwischengeschoben werden muss, dann hat man das ggf. damals nicht bedacht ;)

Wenn du deine Anwendung plötzlich im Client/Server teilen sollst und das alles per IPC/RMI machen sollst, dann kann das Ursprungsdesign plötzlich komplett daneben sein ;)

Das kannst du aber nur machen, wenn es in der Anwendung schon einen logischen Schnitt gibt, also mehrere Bereiche, die unterschiedliches tun. Die wirst du als versierter Entwickler schon isoliert betrachten und entwickeln. Ein späteres Zerschneiden ist dann nur noch ein Klacks. Sprich, die Layer sollten schon existieren.
 

bjbo

Aktives Mitglied
Dabei seit
20.11.2003
Beiträge
1.327
Reaktionspunkte
82
Einig sind wir uns nicht, wir haben nur festgestellt, dass unsere Ansichten recht nahe beieinander liegen ;) (siehe Trennung von Entities und Businesslogik)

Also für Entwickler ist das schon fast so etwas wie Blutsbrüderschaft ;)
 

-Nuke-

Aktives Mitglied
Dabei seit
13.09.2003
Beiträge
2.146
Reaktionspunkte
15
Das meine ich ja mit "3 Jahre voraus denken" ;)
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Das meine ich ja mit "3 Jahre voraus denken" ;)

*lach* also ich denke da nicht 3 Jahre im Voraus sondern an ein sauberes Design. Alles andere wäre *für mich* sträflich. Es geht ja dabei nicht darum, Eventualitäten wie Verteilung in Betracht zu ziehen, sondern den Code wartbar zu halten. Wenn man die einzelnen Concerns trennt und kapselt, kann man die Wartbarkeit schon fast garantieren ;)
 

Kümmelkorn

Aktives Mitglied
Dabei seit
06.10.2008
Beiträge
1.940
Reaktionspunkte
127
Ich hab gerade mal ein bisschen an der Oberflächen von Datenbanken gekratzt und frage mich, wo da der Unterschied zu der Model-Schicht beim Programmieren liegt!? Nächstes Semester haben wir Datenbanken, laut Modulhandbuch werden in dem Kurs Entity-Relationship-Modelle durchgenommen. Entitys kenne ich aber auch aus der Modelschicht und Beziehungen können die beim Programmieren auch haben. Außerdem sehe ich keinen Plausiblen Grund, warum Datenbanken etwas anderes sein sollten als Serialization (ich erinnere mich da dunkel an NSPropertyListSerialization)? Ob man eine Datenstruktur nun in eine Datenbank oder eine plist-Datei konvertiert, ist doch im Grunde egal!?

Sind Datenbanken also das selbe wie die Model Schicht? Sind Entity-Relationship-Modelle quasi ein Klassendiagram nach MVC, nur dass V und C halt "ausgeblendet" sind? Oder gibt es da einen tragischen Unterschied? Was ist der Unterschied zwischen Datenbanktabellen und Objekten? Welche Rolle spielen dabei Beziehungstabellen (die ich nur vom Namen her kenne) und kennt jemand dazu einfaches, anschauliches und mit Beispielen illustriertes Material (von mir aus gern auch in englisch)?

:eek:
O:)
Danke für eure Hilfe :)
Gruß, Micha
 

_ebm_

Aktives Mitglied
Dabei seit
19.01.2008
Beiträge
2.079
Reaktionspunkte
204
Ich hab gerade mal ein bisschen an der Oberflächen von Datenbanken gekratzt und frage mich, wo da der Unterschied zu der Model-Schicht beim Programmieren liegt!? Nächstes Semester haben wir Datenbanken, laut Modulhandbuch werden in dem Kurs Entity-Relationship-Modelle durchgenommen. Entitys kenne ich aber auch aus der Modelschicht und Beziehungen können die beim Programmieren auch haben. Außerdem sehe ich keinen Plausiblen Grund, warum Datenbanken etwas anderes sein sollten als Serialization (ich erinnere mich da dunkel an NSPropertyListSerialization)? Ob man eine Datenstruktur nun in eine Datenbank oder eine plist-Datei konvertiert, ist doch im Grunde egal!?

Sind Datenbanken also das selbe wie die Model Schicht? Sind Entity-Relationship-Modelle quasi ein Klassendiagram nach MVC, nur dass V und C halt "ausgeblendet" sind? Oder gibt es da einen tragischen Unterschied? Was ist der Unterschied zwischen Datenbanktabellen und Objekten? Welche Rolle spielen dabei Beziehungstabellen (die ich nur vom Namen her kenne) und kennt jemand dazu einfaches, anschauliches und mit Beispielen illustriertes Material (von mir aus gern auch in englisch)?

:eek:
O:)
Danke für eure Hilfe :)
Gruß, Micha


Hallo Micha,

Also Jein, Datenbanken sind in erster Linie strukturierte Speicher von irgendwie gearteten Daten. So gibt es verschiedene Datenbankmodelle. Mit die wichtigsten sind relationale Datenbanken (RDBMS), Key-Value-Stores und Big Tables. Die einfachste ist übrigens das Dateisystem.

Natürlich kann man die Datenbanken auf Objekte abbilden. Dafür gibt es dann Objekt-Relationale Modelle für dir rdbms und in K-V-Stores kann man eh beliebige Daten, also auch serialisierte Objekte ablegen.

Das war jetzt ziemliches Buzzword-Bingo aber so kommst du mit Wikipedia & Co. weiter.
 
Oben