¿Se prefiere un único objeto sobre múltiples variables?

8

Fue bastante difícil poner lo que quise decir en un título, pero es fácil ponerlo en código.

C ++

Es esto

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

¿Ser preferido sobre esto?

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

(Tenga en cuenta que Vector no es como std::vector, es un vector 2D. Esta clase tiene muchos métodos que no necesito aquí, como normalize()y scale(). ¿Debería tener una Pointclase más básica para esto?)

JavaScript

Es esto

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

¿Ser preferido sobre esto?

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

Respuestas:

12

He "heredado" mucho código heredado usando su primera variante, y también escribí mucho código usando yo Point2Dy Point3Dclases en su lugar (esencialmente de lo que Vector<int>se trata). La primera variante siempre conduce a funciones con demasiados parámetros y demasiadas construcciones repetidas donde la adición simple de vectores o la multiplicación escalar se repite una y otra vez en varias líneas de código.

Sin embargo, el uso de clases de puntos o vectores 2D, especialmente cuando se necesitan muchas operaciones de vectores, hace que el código sea mucho más limpio, conciso, mejor legible y fácil de mantener. Si debe usar una existente Vector<int>, o escribir su propia Pointclase, es imposible decirlo sin saber más sobre los detalles de su código, pero en general, si una clase existente sufre su necesidad, ¿por qué no reutilizarla? Los métodos adicionales que no necesita típicos no duelen. Pero no usar ninguna clase de punto / vector 2D es casi siempre una decisión equivocada. Y en su ejemplo anterior: si tiene influencia en la element.movefunción, en mi humilde opinión, es mejor diseñarla de una manera que pueda llamar en element.move(offset)lugar de element.move(offset_x, offset_y).

Por ejemplo, supongamos que necesita una matriz de coordenadas de puntos y va a utilizar a std::vector. En el primer caso, necesitará dos std::vector<int> variables, debe asegurarse de que esos dos vectores estén "sincronizados" entre sí, y todo agregar nuevos elementos, encontrar elementos existentes, pasar esos elementos necesita dos líneas de código. de uno cuando había elegido usar un std::vector<Point2D>lugar.

Doc Brown
fuente
3

Para dar una respuesta más general, las variables deben agruparse en un objeto cuando tenga sentido lógico hacerlo.

  • ¿Son las variables diferentes aspectos o propiedades de una "cosa"?
  • ¿Siempre pertenecen juntos?
  • ¿Se usarán lo suficiente como para justificar cualquier trabajo adicional que pueda estar involucrado en la creación de un objeto?

En su caso, diría que su código mejora claramente cuando agrupa las variables.

Pero si las variables se juntan en un objeto que no está bien pensado, puede quedarse con un diseño difícil de manejar que es peor que usar variables normales.

Por el contrario, es posible sobrediseñar: pasar demasiado tiempo pensando y construyendo la estructura orientada a objetos "perfecta", hasta el punto de impedir que realmente haga las cosas.


fuente
1

En realidad, creo que la mejor manera es hacer esto:

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

Este código abstrae la dimensionalidad de sus vectores, y la misma línea de código ( element.moveBy(offset)) funcionará sin cambios si cambia sus vectores a 3D, o dobles, o incluso coordenadas polares, siempre que sus tipos implementen las operaciones requeridas correctamente.

Por ejemplo, considere el siguiente código:

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

Cualquiera con suficiente pista matemática de vectores entenderá lo que sucede aquí; Además, la función es corta, hasta el punto. No puede ver lo que Vecse define, pero eso generalmente no es muy interesante y también es trivial buscarlo; la claridad y brevedad del código lo compensan con creces. Después de todo, la codificación se trata de hacer abstracciones, y abstraer grupos de escalares en vectores es una abstracción muy poderosa. Para patadas, intente e implemente la función anterior sin hacer estas abstracciones, para vectores 2D, vectores 3D y escalares.

tdammers
fuente