Eine zentrale Eigenschaft der Objektorientierung ist die Unterscheidung zwischen public und private, öffentlich und privat. Diese Eigenschaften beschreiben die Sichtbarkeit von Attributen und Methoden einer Klasse. Insbesondere im Java-Umfeld wird diese Möglichkeit jedoch recht konsequent ignoriert: Öffentliche Attribute sind hier in aller Regel trotzdem privat. Dafür kann man mit einer Methode getAttribut auf ein Attribut namens Attribut zugreifen und mit setAttribut(Attribut) einen neuen Wert setzen. Grund genug sich einmal anzusehen, warum das so ist.
Die Probleme mit Gettern und Settern
Übersicht und Aufwand
In vielen Fällen ist der Einsatz von Gettern und Settern, wie die entsprechenden Methoden genannt werden, nichts weiter als eine aufwändige und unübersichtlichere Schreibweise für ein öffentliches Attribut. Statt 10 Attribute einfach public zu definieren, kommen (3*10=) 30 Zeilen Code für Methoden hinzu, Leerzeilen und Kommentare nicht mitgerechnet. Sie versperren oft den Blick auf die relevanten Methoden der Klasse. Zudem erfordern sie zusätzliche Schreib- oder Klickarbeit. Zwar übernehmen moderne IDEs wie Eclipse die Erzeugung der Methoden, wenn man einen Attributnamen aber noch mal ändern will werden die Getter und Setter gern vergessen.
Bruch mit dem Konzept der Wertzuweisung
Auch die Anwendung von Gettern und Settern erscheint unlogisch, bricht sie doch mit dem ohnehin bekannten Konzept der Variablenzuweisung:
int count = 3;
Es erscheint nur konsequent, so auch mit Attributen zu verfahren:
object.count = 3;
Stattdessen werden Methoden verwendet, welche ja eigentlich ein ganz anderes Konzept verfolgen als einfache Wertzuweisung.
Performance
Wenn auch heute nicht mehr wirklich relevant, so sind Getter und Setter auch aus Performance-Sicht unsinnig. Bei beiden Varianten wird der Wert eines Attributs gelesen oder gesetzt. Die Methodenvariante benötigt aber zusätzlich einen Methodenaufruf, für den zusätzlich Speicher und Taktzyklen bereitgestellt werden müssen.
Zwischenfazit: Contra Getter und Setter
Zusammengefasst spricht so einiges gegen Getter und Setter:
- sie erfordern Arbeit für die Erstellung
- sie blähen den Code der entsprechenden Klasse auf
- sie brechen mit dem Konzept der Wertzuweisung
- sie benötigen zusätzliche Ressourcen
Die Vorteile von Gettern und Settern
Da wir ja nun nicht davon ausgehen können, dass alle Getter- und Setter-Nutzer nicht wissen, dass es öffentliche Attribute gibt, muss ja doch der ein oder andere Vorteil zu finden sein.
Datenkapselung
Ein zentrales Argument in der objektorientierten Softwareentwicklung ist die Datenkapselung. Nach außen soll nicht sichtbar sein, wie ein Objekt funktioniert. Mittels Methoden kann man es zwar beeinflussen, wie genau das Objekt etwas umsetzt, soll ihm aber überlassen sein. Vergleichen wir also:
InetSocketAddress addr = InetSocketAddress(InetAddr.getLocalHost(), 8080); obj1.address = addr; obj2.setAddress(addr);
In vielen Fällen wird auch obj2 lediglich das Addr-Objekt in einem Attribut speichern. Der Unterschied ist aber, dass es genau dies nicht tun muss: Wenn es nur den Port benötigt, kann es auch nur diesen in einem Int-Attribut speichern. Obj1 hat diese Möglichkeit nicht: Auch wenn später erkannt wird, dass man gar nicht das gesamte Addr-Objekt benötigt, muss man es dennoch komplett sichern, da es als öffentliches Attribut ein Teil der Signatur der Klasse ist.
Validierung und Vorbereitung
Ein anderer interessanter Punkt ist die Möglichkeit, einen Wert, der mittels Setter gesetzt wird, direkt zu validieren. Entspricht der Wert etwa nicht irgendwelchen Bedingungen, kann man ihn korrigieren oder das Setzen etwa durch Werfen einer Exception gar verhindern. Ein weiterer Vorteil hierbei ist, dass die Rückmeldung über das fehlerhafte Setzen an der Stelle bemängelt wird, an der es geschieht. Wird das Attribut direkt gesetzt, fallen dessen eventuelle Unzulänglichkeiten erst auf, wenn es irgendwann verwendet wird.
Genauso verhält es sich mit Gettern: Die Rückgabe kann bei einer Methode noch vorbereitet werden, bevor der Fragende sie erhält.
Nur Get/nur Set
Ein weiterer Punkt ist, dass die Eigenschaft Public beides erlaubt: Lesen und Schreiben. Manchmal ist es aber wünschenswert, nur eine dieser Operationen zuzulassen. Nutzen wir Methoden für den Zugriff, können die ungewünschten einfach weggelassen werden.
Konsistenz
Ein häufiges Argument gegen die konsequente Nutzung von Gettern und Settern ist, dass man diese ja verwenden kann, wenn die vorher angesprochenen Funktionen wie etwa Validierung auch wirklich benötigt werden. Dies hätte aber einen unschönen Effekt: Weiß ich, welchen Wert ich bei einem Objekt setzen möchte, muss ich zudem noch herausfinden, ob es sich um ein öffentliches Attribut oder eine Setter-Methode handelt.
obj.localAddress = addr1; obj.setRemoteAddress(addr2);
Dies wäre sehr ärgerlich und sollte unbedingt vermieden werden. Somit empfiehlt sich die konsequente Nutzung von Gettern und Settern.
Zwischenfazit: Pro Getter und Setter
Getter und Setter erlauben dem Softwareentwickler
- Daten zu kapseln und abstrakte Signaturen bereitzustellen
- Werte zu validieren oder vor der Rückgabe zu bearbeiten
- Attribute nur zu lesen oder nur zu setzen
- ein konsistentes Bild zu hinterlassen
Mein Fazit
Zwar konnten mich viele Artikel wie etwa Properties vs. Public Variables, die sich für öffentliche Attribute aussprechen, zunächst durchaus mitreißen, einer genauen Betrachtung halten sie meiner Meinung nach aber kaum stand. Es ist richtig, dass Getter und Setter eigentlich nur konzeptionelle und oft nur theoretische Vorteile haben, die bei einem kleinen Programm vielleicht auch gar nicht ins Gewicht fallen. Dennoch weiß man vorher nie, wohin sich die Software mal entwickeln wird und welche Relevanz ein gepflegter Code haben kann. Wenn der Code zudem offen ist, kann ein nachhaltiges Konzept dahinter auch positive Werbung sein.
Auch die Kritikpunkte an Gettern und Settern sind durchaus richtig, aber nicht sonderlich relevant. Moderne Editoren erzeugen die nötigen Methoden fast automatisch und unwichtige Code-Teile können einfach ausgeblendet werden. Auch der Performance-Nachteil ist heute in keinem Umfeld mehr messbar.
Es gibt aber Ausnahmen. In Eclipses „Standard Widget Toolkit“ (SWT) werden reine Datencontainer für Layouts verwendet, zum Beispiel GridData (Java-Doc). Diese enthalten keinerlei Logik und dienen nur dazu, mehrere Einzelwerte in einem Objekt zusammenzufassen. An dieser Stelle nutzt Eclipse öffentliche Attribute. Eine interessante und auch verständliche Entscheidung.
Aufrufen, die üblichen Guidelines kritisch zu hinterfragen finde ich richtig und wichtig. An dieser Stelle ist der Status quo aber vollkommen berechtigt.