Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: amchacon en 9 Abril 2014, 16:49 pm



Título: Representación de Coordenadas
Publicado por: amchacon en 9 Abril 2014, 16:49 pm
Buenas.

Frecuentemente hay que trabajar con coordenadas en la programación. Actualmente conozco tres formas de pasarlas:

1º A "pelo" con dos variables int:

Código
  1. int x = 1;
  2. int y = 1;
  3.  
  4. pintar(x,y);

2º Creandote una estructura "Cord":

Código
  1. struct Cord
  2. {
  3.    int X,Y;
  4.  
  5.   Cord(int x,int y) : X(x),Y(y) {}
  6. };
  7.  
  8. //...
  9.  
  10. pintar(Cord(1,1));

3º Un objeto Cord con su encapsulamiento y su todo:
Código
  1. class Cord
  2. {
  3. int X,Y;
  4.  
  5. public:
  6.  
  7. Cord(int x,int y) : X(x),Y(y) {}
  8.  
  9. int getX() const {return X;}
  10. int getY() const {return Y;}
  11. void setX(int x){X = x;}
  12. void setY(int y){Y = y;}
  13.  
  14. bool operator==(const Cord a) const {return X == a.X && Y == a.Y;}
  15. bool operator!=(const Cord a) const {return X != a.X || Y != a.Y;}
  16.        Cord operator+(const Cord a) const{return Cord(A.X+X,A.Y+Y);}
  17. };
  18.  
  19. //...
  20.  
  21. Pintar(Cord(1,1));]

En vuestra opinión. ¿Cual es la forma más adecuada? Con la primera quizás se escribe menos, aunque se te acumulan los argumentos en la función.


Título: Re: Representación de Coordenadas
Publicado por: eferion en 9 Abril 2014, 17:01 pm
A mi me gusta más la tercera opción por varias razones:

* Existe encapsulamiento.

* Permite obtener un código más legible, sobretodo si se sobrecargan varios operadores ( suma, resta, ... )

* Su mantenimiento luego es más sencillo y se limitan la cantidad de "gazapos" por parte del que usa el objeto.

* Es muy sencillo acoplarle una batería te test para asegurar el correcto funcionamiento.

Se que tiene varias desventajas, pero desde mi punto de vista y mi experiencia ( trabajo en un cad orientado al sector naval ) me dicen que la tercera opción es la que más beneficios tiene.

Algunas desventajas:

* Resevas de memoria al crear copias del objeto, lo que reduce sensiblemente el rendimiento.

* Hay que currárselo todo al principio.


Título: Re: Representación de Coordenadas
Publicado por: Eternal Idol en 9 Abril 2014, 17:33 pm
La segunda manera tambien usa un objeto, en C++ las estructuras son a todos los efectos clases con sus miembros y clases bases publicos por defecto. Los constructores no existen en C.


Título: Re: Representación de Coordenadas
Publicado por: eferion en 9 Abril 2014, 17:42 pm
La segunda manera tambien usa un objeto, en C++ las estructuras son a todos los efectos clases con sus miembros y clases bases publicos por defecto. Los constructores no existen en C.

Ya, lo que sucede es que en las estructuras, por defecto, sus miembros son públicos, lo que viola el concepto de encapsulamiento.

Además en C++ la gente espera encontrar clases... es más natural. Las estructuras, en los grupos en los que he estado, se reservan para tareas específicas, por ejemplo, para cuando hay que enviar tramas de datos por red... aunque hay que tener cuidado de no tener estructuras con herencia para no enviar basura.


Título: Re: Representación de Coordenadas
Publicado por: Eternal Idol en 9 Abril 2014, 17:53 pm
Ya, lo que sucede es que en las estructuras, por defecto, sus miembros son públicos, lo que viola el concepto de encapsulamiento.

Lo que decis es correcto - ademas las clases base se heredan por defecto como publicas tambien - pero no invalida mi afirmacion en lo absoluto, en ambos casos al llamar a pintar se usa un objeto y es lo que queria aclarar.


Título: Re: Representación de Coordenadas
Publicado por: ivancea96 en 9 Abril 2014, 18:04 pm
Yo voto a favor de la estuctura. No es necesario ningún método si solo vas a usar un X y un Y, que no interfieren en nada el uno del otro.

No es necesario controlarlos con una clase. Es más: se hace más engorroso poner coord.getX() que poner coord.x.

Pero bueno. La primera opción, desde luego, si usas muchas coordenadas, es lioso. x1 x2 x3 y1 y2 y3. Y si no lioso, menos legible.

En cualquier caso, también se puede hacer una clase con miembros públicos. Es lo mismo prácticamente. Funciones le vas a poder poner igual a clase como a estructura.

Y como dato final, yo prefiero hacer vectores, no coordenadas. Aunque prácticamente son lo mismo, tienen más usos cuerdos. No es cuerdo sumar coordenadas, en cambio sí lo es sumar vectores. No es cuerdo un producto mixto de coordenadas, pero sí uno de vectores. En fin.


Título: Re: Representación de Coordenadas
Publicado por: amchacon en 9 Abril 2014, 18:29 pm
A mi me gusta más la tercera opción por varias razones:

* Existe encapsulamiento.

* Permite obtener un código más legible, sobretodo si se sobrecargan varios operadores ( suma, resta, ... )

* Su mantenimiento luego es más sencillo y se limitan la cantidad de "gazapos" por parte del que usa el objeto.

* Es muy sencillo acoplarle una batería te test para asegurar el correcto funcionamiento.

Se que tiene varias desventajas, pero desde mi punto de vista y mi experiencia ( trabajo en un cad orientado al sector naval ) me dicen que la tercera opción es la que más beneficios tiene.

Algunas desventajas:

* Resevas de memoria al crear copias del objeto, lo que reduce sensiblemente el rendimiento.

* Hay que currárselo todo al principio.

Vaya no lo había visto así. ¿Pero es necesario el encapsulamiento en un objeto así?

La segunda manera tambien usa un objeto, en C++ las estructuras son a todos los efectos clases con sus miembros y clases bases publicos por defecto. Los constructores no existen en C.
Muy cierto, quizás debería haber sido más preciso en la terminología ^^

Y como dato final, yo prefiero hacer vectores, no coordenadas. Aunque prácticamente son lo mismo, tienen más usos cuerdos. No es cuerdo sumar coordenadas, en cambio sí lo es sumar vectores. No es cuerdo un producto mixto de coordenadas, pero sí uno de vectores. En fin.
Las coordenadas se pueden interpretar como un vector desde la posición (0,0) a la posición (x,y). Ergo si tiene un uso cuerdo.

Quizás para no liar se puede cambiar el nombre de Cord -> Vector.


Título: Re: Representación de Coordenadas
Publicado por: ivancea96 en 9 Abril 2014, 18:36 pm
Las coordenadas se pueden interpretar como un vector desde la posición (0,0) a la posición (x,y).

Se puede interpretar. Pero sigue sin ser cuerdo, por ejemplo, ver "coordenada.longitud()".


Título: Re: Representación de Coordenadas
Publicado por: amchacon en 9 Abril 2014, 18:37 pm
Se puede interpretar. Pero sigue sin ser cuerdo, por ejemplo, ver "coordenada.longitud()".
Cierto.

Pues le cambio el nombre de Cord a vector y listo ^^


Título: Re: Representación de Coordenadas
Publicado por: dato000 en 9 Abril 2014, 19:55 pm
ummmm me voy más con la segunda opción, es algo que herede de conocimientos de amchacon y kaltorak, que trabajan de esta forma el código, y aún no estoy acostumbrado al encapsulamiento (apenas lo estoy comenzando a aplicar para c# con patrón singleton y es todo un dilema aplicarle encapsulamiento del vikingo a esa clase control) y menos en c++, y para un caso particular como este, se me hace un poco enredado utilizar tanto metodo para estas variables, prácticamente cada variable requiere de su clase y sus metodos de control, y a mi se me hace adecuado solo en ciertos casos con variables realmente importantes.

Yo voto a favor de la estuctura. No es necesario ningún método si solo vas a usar un X y un Y, que no interfieren en nada el uno del otro.

No es necesario controlarlos con una clase. Es más: se hace más engorroso poner coord.getX() que poner coord.x.

Pero bueno. La primera opción, desde luego, si usas muchas coordenadas, es lioso. x1 x2 x3 y1 y2 y3. Y si no lioso, menos legible.

En cualquier caso, también se puede hacer una clase con miembros públicos. Es lo mismo prácticamente. Funciones le vas a poder poner igual a clase como a estructura.

Y como dato final, yo prefiero hacer vectores, no coordenadas. Aunque prácticamente son lo mismo, tienen más usos cuerdos. No es cuerdo sumar coordenadas, en cambio sí lo es sumar vectores. No es cuerdo un producto mixto de coordenadas, pero sí uno de vectores. En fin.

Creo estoy de acuerdo con ivancea96 en todo, excepto en lo de vectores, bueno, casi, depende del caso.


Título: Re: Representación de Coordenadas
Publicado por: eferion en 10 Abril 2014, 08:39 am
Vaya no lo había visto así. ¿Pero es necesario el encapsulamiento en un objeto así?

En el caso concreto de las coordenadas no hay mucha diferencia... Sin embargo me gustaría matizar un detalle:

* Si cambias la implementación de la función, sin cambiar la firma, únicamente necesitas recompilar la clase para que todo siga funcionando.

* Si expones la variable directamente y después necesitas cambiarlo a función porque te das cuenta de que necesitas realizar algún chequeo u operación adicional, te ves obligado a recompilar todo el código ( en mi caso unas 6 horas ).

* Los getters y los setters pueden ser convertidos a inline por el compilador, por lo que tendrían exactamente el mismo rendimiento que exponer la variable directamente.

Por ese motivo a mí me gusta más la tercera opción... pero creo que es también cuestión de costumbre.

No es necesario controlarlos con una clase. Es más: se hace más engorroso poner coord.getX() que poner coord.x.

también puedes declarar la clase tal que:

Código
  1. class Coord
  2. {
  3.  public:
  4.    int X( ) const;
  5.    void X( int x );
  6.  
  7.    int Y( ) const;
  8.    void Y( int y );
  9.  
  10.    void SetValues( int x, int y );
  11. };

Tampoco hay demasiada diferencia entre poner coord.X( valor ) y coord.X = valor.

Por otro lado, si es cierto que estaría genial que en alguna revisión incorporasen el concepto de propiedades a C++... reconozco que el uso del operador = es más intuitivo.

También recordar que gracias a la sobrecarga de operadores, es posible "linealizar" este tipo de estructuras para poder acceder a sus elementos de forma secuencial:

Código
  1. class Coord
  2. {
  3.  public:
  4.    int X( ) const;
  5.    void X( int x );
  6.  
  7.    int Y( ) const;
  8.    void Y( int y );
  9.  
  10.    int& operator[]( int index ) const
  11.    {
  12.      int to_return = 0;
  13.  
  14.      if ( index == 0 )
  15.        to_return = x;
  16.      else if ( index == 1 )
  17.        to_return = y;
  18.  
  19.      return to_return;
  20.    }
  21. };

Otra ventaja importante de usar getters y setters es que se pueden poner breakpoints en los mismos... mientras que para los accesos directos a variables esto es imposible.


Título: Re: Representación de Coordenadas
Publicado por: amchacon en 10 Abril 2014, 12:41 pm
* Si expones la variable directamente y después necesitas cambiarlo a función porque te das cuenta de que necesitas realizar algún chequeo u operación adicional, te ves obligado a recompilar todo el código ( en mi caso unas 6 horas ).
Un inciso.

Si cambias el tipo de la coordenada de int a float (o añades algún método/operador nuevo)... ¿No tendrías que recompilar todo el código? Para que te coja la declaración de la clase digo.

Lo pregunto por si conoces algún atajo que yo no sepa.


Título: Re: Representación de Coordenadas
Publicado por: eferion en 10 Abril 2014, 13:00 pm
Si cambias el tipo de la coordenada de int a float (o añades algún método/operador nuevo)... ¿No tendrías que recompilar todo el código? Para que te coja la declaración de la clase digo.

Es que eso no es un chequeo u operación adicional... eso es un cambio de variable directamente.

Yo me refería a, por ejemplo, tener que añadir una comprobación para evitar coordenadas con valores negativos, o limitar el número de decimales, en el caso del tipo float, para evitar "oscilaciones" debido a la falta de precisión.



Título: Re: Representación de Coordenadas
Publicado por: Eternal Idol en 10 Abril 2014, 13:42 pm
Otra ventaja importante de usar getters y setters es que se pueden poner breakpoints en los mismos... mientras que para los accesos directos a variables esto es imposible.

Depende de que no sean metodos inline (cosa mas bien comun ya que suelen ser de un par de lineas), por otro lado si tenes muchos objetos de esa clase en uso tendras muchos breaks y si te interesa uno en particular es posible poner breakpoints en memoria (aplica a los miembros de una clase y a variables).


Título: Re: Representación de Coordenadas
Publicado por: eferion en 10 Abril 2014, 14:29 pm
Si compilas en Debug, desde luego no van a ser inline porque no se aplicarán optimizaciones... por otro lado, breakpoints en memoria, estoy seguro que muchísima gente no sabe utilizarlos o, directamente, no sabe que existen.


Título: Re: Representación de Coordenadas
Publicado por: Eternal Idol en 10 Abril 2014, 15:06 pm
Por eso dije que depende, en mi experiencia de miles de horas de depuracion en Release suele suceder mucho. Que lo aprendan en el foro seria muy bueno, es muy util si la funcion es llamada multitud de veces.