Ist ein einzelnes Objekt mehreren Variablen vorzuziehen?

8

Es war ziemlich schwer, das, was ich meinte, in einen Titel zu schreiben, aber es ist einfach, Code zu schreiben.

C ++

Ist das

int offset_x = 10;
int offset_y = 40;
...
element.move(offset_x, offset_y);

Dem vorzuziehen?

Vector<int> offset(10, 40);
...
element.move(offset.x, offset.y);

(Beachten Sie, dass Vektor nicht wie std::vector, es ist ein 2D-Vektor. Diese Klasse hat viele Methoden, die ich hier nicht brauche, wie normalize()und scale(). Sollte ich eine grundlegendere PointKlasse dafür haben?)

JavaScript

Ist das

var offsetX = 10;
var offsetY = 40;
...
element.move(offsetX, offsetY);

Dem vorzuziehen?

var offset = {x: 10, y: 40};
...
element.move(offset.x, offset.y);
Futlib
quelle

Antworten:

12

Ich habe mit Ihrer ersten Variante viel Legacy-Code "geerbt" Point2Dund Point3Dstattdessen auch viel Code mit und Klassen geschrieben (im Wesentlichen dasselbe, worum es bei Ihnen Vector<int>geht). Die erste Variante führt immer zu Funktionen mit zu vielen Parametern und zu vielen wiederholten Konstrukten, bei denen die einfache Vektoraddition oder Skalarmultiplikation in mehreren Codezeilen immer wieder wiederholt wird.

Die Verwendung von 2D-Punkt- oder Vektorklassen macht den Code jedoch viel sauberer, prägnanter, besser lesbar und wartbar, insbesondere wenn Sie viele Vektoroperationen benötigen. Wenn Sie eine vorhandene Klasse verwenden Vector<int>oder Pointstattdessen eine eigene Klasse schreiben sollten , ist es unmöglich zu sagen, ohne mehr über die Details Ihres Codes zu wissen. Wenn eine vorhandene Klasse jedoch unter Ihren Anforderungen leidet, warum sollten Sie sie nicht wiederverwenden? Die zusätzlichen Methoden, die Sie normalerweise nicht benötigen, schaden nicht. Die Verwendung einer 2D-Punkt- / Vektorklasse ist jedoch fast immer die falsche Entscheidung. Und in Ihrem obigen Beispiel: Wenn Sie Einfluss auf die element.moveFunktion haben, ist es meiner Meinung nach besser, sie so zu gestalten, dass Sie sie element.move(offset)anstelle von aufrufen können element.move(offset_x, offset_y).

Angenommen, Sie benötigen ein Array von Punktkoordinaten und verwenden a std::vector. Im ersten Fall benötigen Sie zwei std::vector<int> Variablen. Sie müssen sicherstellen, dass diese beiden Vektoren "synchron" sind. Für das Hinzufügen neuer Elemente, das Auffinden vorhandener Elemente und das Weitergeben dieser Elemente sind stattdessen zwei Codezeilen erforderlich von einem, als Sie sich entschieden hatten, std::vector<Point2D>stattdessen ein zu verwenden.

Doc Brown
quelle
3

Um eine allgemeinere Antwort zu geben, sollten Variablen zu einem Objekt zusammengefasst werden, wenn dies logisch sinnvoll ist.

  • Sind die Variablen unterschiedliche Aspekte oder Eigenschaften einer "Sache"?
  • Gehören sie immer zusammen?
  • Werden sie ausreichend verwendet, um zusätzliche Arbeiten zu rechtfertigen, die beim Erstellen eines Objekts erforderlich sind?

In Ihrem Fall würde ich sagen, dass sich Ihr Code deutlich verbessert, wenn Sie die Variablen zusammenfassen.

Wenn jedoch Variablen in einem Objekt zusammengefügt werden, das nicht gut durchdacht ist, kann es sein, dass Sie an einem unhandlichen Design festhalten, das schlechter ist als die Verwendung normaler Variablen.

Umgekehrt ist es möglich, zu viel zu entwerfen: zu viel Zeit damit zu verbringen, über die "perfekte" objektorientierte Struktur nachzudenken und sie aufzubauen, bis zu dem Punkt, an dem Sie daran gehindert werden, Dinge tatsächlich zu erledigen.


quelle
1

Eigentlich denke ich, dass der beste Weg dies zu tun ist:

Vector<int> offset(10, 40);
element.moveBy(offset);

Dieser Code abstrahiert die Dimensionalität Ihrer Vektoren, und dieselbe Codezeile ( element.moveBy(offset)) funktioniert unverändert, wenn Sie Ihre Vektoren in 3D oder Doppel- oder sogar Polarkoordinaten ändern, solange Ihre Typen die erforderlichen Operationen korrekt implementieren.

Betrachten Sie beispielsweise den folgenden Code:

Vec wallBounce(Obj& o, cont Wall& w) {
    assert(isUnit(w.normal));
    Vec perp = dot(w.normal, o.velocity) * w.normal;
    o.velocity -= 2 * perp;
}

Jeder mit genügend vektormathematischen Hinweisen wird verstehen, was hier passiert. Außerdem ist die Funktion auf den Punkt kurz. Sie können nicht sehen, wofür Vecgeschrieben wurde, aber das ist normalerweise nicht sehr interessant und auch trivial nachzuschlagen. Die Klarheit und Kürze des Codes machen dies mehr als wett. Beim Codieren geht es schließlich darum, Abstraktionen zu erstellen, und das Abstrahieren von Skalargruppen in Vektoren ist eine sehr leistungsfähige Abstraktion. Versuchen Sie für Kicks, die obige Funktion zu implementieren, ohne diese Abstraktionen vorzunehmen, für 2D-Vektoren, 3D-Vektoren und Skalare.

tdammers
quelle