(Getter und) Setter [2]

Ich habe folgenden Salat:

In einer klasse gibt es viele verschiedene variablen, darunter x und y.
x und y wird immer um 2 hoch oder runtergezählt. Nun habe ich statt

public void setX(int x){this.x = x}
public void setY(int y){this.y = y}

aber folgendes:

public void addX(int amount){x += amount;}
public void addY(int amount){y += amount;}

ist letztere methode auch so “in ordnung” ? Also eigentlich ist es ja egal, aber mal so reintheoretisch?
Meine begründung dafür ist das ich glaube die erste variante ist langsamer, denn:
sonst müsste ich in setx immer getx aufrufen, also so:

object.setX(object.getX() + amount);
object.setY(object.getY() + amount);

und ausserdem ist das doch unübersichtlicher, oder? Was glaubt ihr?

Ich “glaube” dass es ok ist. Mache es zumindest auch immer so.

Schreib Code niemals, weil du denkst, er wäre schneller.
Performance optimiert man bei Bedarf und nur an ausgewählten Stellen (Durch Profiling/Benchmark zu ermitteln).
In Punkto lesbarkeit hast du recht, solche “shortcut”-Methoden lesen sich wesentlich schöner.

Getter und Setter kann man ja trotzdem anbieten, falls doch mal ein Benutzer etwas anderes mit der Klasse vorhat.

Gruß

Hm gut werde ich mir merken. Also in der Entwicklung erstmal nicht an Speed denken, sondern erst wenns sich bemerkbar macht?

Das würden die meisten wohl so sagen. Und es stimmt eigentlich auch. Wenn man irgendwas macht, weil man glaubt, es wäre schneller, ist das oft Mist. Es gibt aber auch das andere Extrem. Wenn man code (in bezug auf Performance) komplett unüberlegt hinschreibt, kann sich das auch rächen. Man sollte auch immer überlegen, WAS der Code macht, und WIE er verwendet wird…

bei deinem Bsp wuerde ich IMMER die zweite Variante mit addxxx(int amount) machen. Es ist fuer den Benutzer weit mehr verstaendlich was da eigentlich passiert, als bei einem einfachen set. Woher soll man bei einem set wissen, dass man eigentlich was hinzuaddiert ?

Tut man ja nicht. Es ging wohl nur um die Frage, ob man das Addieren IN der add-Methode macht, oder dem Aufrufer einer set-Methode (mit passendem Argument) überläßt. Deswegen auch die Betonung: WAS soll damit WIE gemacht werden?

In Punkto Geschwindigkeit noch was anderes. Du wirst hierbei nix spüren und vermutlich noch nicht mal messen können, weil beide Varianten viel zu schnell durch sind und im Ergebnis wahrscheinlich sogar auf die selbe Zeit kommen. An solchen trivialen Stellen sich darüber Gedanken zu machen frisst mehr Zeit als es einfach zu machen. Wenn deine Begründung darin liegt, dass ja vermeindlich mehr Methodenaufgerufe und mehr Zugriffe stattfinden als bei einer anderen Variante, dann wirst du mit Clean Code ganz schön Probleme bekommen, denn es ist z.B. üblich, dass man größere Methoden in viele kleinere zerlegt, nicht wegen Wiederverwendbarkeit oder Redundanz, sondern Lesbarkeit, Verständnis und einfachere Darstellung des Algorithmuses. Das heißt es können dann durchaus etliche Methodenaufrufe stattfinden. Methodenaufrufe kosten heutzutage aber eigentlich nichts mehr und hinzu kommt auch noch, dass Rechenleistung und Arbeitsspeicher immer weiter zunehmen, weshalb das nochmal weniger ins Gewicht fällt. Hinzu kommt auch noch, dass die Compiler bestimmte Methoden auch als Inline-Code umsetzen (wenn der Compiler meint, es würde Sinn machen), sprich die Methode entfernen und ihren Aufruf durch ihren Code ersetzen, wodurch der Aufruf dann also weg fällt.

Verständlicher, einfach und gut lesbarer und selbsterklärender Code vor Pseudooptimierung! Man sollte natürlich dennoch die Performance im Hinterkopf behalten, denn String-Schleifen oder unnötig viele Ausführungen von komplexen und rechenintensiven Berechnungen können tatsächlich sehr viel Zeit fressen. Wer solche Fallen bereits kennt, kann sie auch sofort verhindern, ansonsten eben erst, wenn es wirklich bemerkbar ist und durch Profiler aufgedeckt wurde.

Premature optimization is the root of all evil – DonaldKnuth
In DonaldKnuth’s paper „StructuredProgrammingWithGoToStatements“, he wrote: „Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.“

Sind Getter und Setter nicht die besten Kandidaten für Method-Inlining? Warum also sollte man bei

  void add(Number value);
}```etwas anderes schreiben wollen als
```class Calcer implements Adder {
  private double value;

  public double getValue() {
    return value;
  }

  protected void setValue(double value) {
    // do some checks
    this.value = value;

  public void add(Number value) {
    setValue(getValue() + value.doubleValue());
  }
}```Sieht zwar nicht performant aber dafür optimal aus... Den Rest besorgt euch der JIT.

edit: Das Interface ist jetzt natürlich nur da, damit das Problem beschrieben werden kann. Also gar nicht beachten... ;)

Also ich würde schon ja sagen, aber ob es auch wirklich gemacht wird, ist ja letztendlich die Entscheidung vom Compiler bzw. JIT-Compiler. Ich wollte damit nur sagen, dass es sowieso keinen Sinn hat sich da zu viele Gedanken drum zu machen, wie der Code am besten optimiert werden kann, da letztendlich die Compiler da ihre Finger im Spiel haben und selbst entscheiden, was optimiert wird und was nicht, darauf hat man keinen Einfluss. Aber so wie in deinem Beispiel mache ich das auch oft, sprich sofern vorhanden Getter und Setter statt direkte Zugriffe. Spart auch bei nachträglich eingefügter Logik (können Getter und Setter ja durchaus haben) die Fehlersuche und man muss auch nicht zu viel überlegen. Wie gesagt, Methodenaufrufe sind inzwischen keine Last mehr, da lieber auf sauberen Code achten als sich Gedanken drum machen, wie viele Ticks der Prozessor dafür nun verbraucht.

Hier stand Murks - falsch gelesen!

[QUOTE=mymaksimus]Ich habe folgenden Salat:

In einer klasse gibt es viele verschiedene variablen, darunter x und y.
x und y wird immer um 2 hoch oder runtergezählt.
[…]
ist letztere methode auch so “in ordnung” ? Also eigentlich ist es ja egal, aber mal so reintheoretisch? [/QUOTE]Sie ist besser als die erste.
Gut wäre sie, wenn sie ausdrücken würde, was fachlich passiert, also statt public void addX(int ammount)besser public void moveRightBy(int units)

bye
TT

hmmm aber vielleicht brauche ich die methode ja auch mal um den spieler nicht zu bewegen - auch wenn das unwahrscheinlich ist.
Die “überbezeichnung” ist eigentlich: erhöhe den wert x…