Imprimir un objeto concreto

7 views
Skip to first unread message

Juan Manuel Ollé

unread,
Mar 3, 2018, 7:01:06 AM3/3/18
to cp...@googlegroups.com
Estimados,

Tengo un problema concreto, no obstante es muy común aunque no encuentro una forma simple de resolverlo sin complicarlo demasiado.
El problema es la de separar los datos de la forma de imprimirlos, el problema radica en que a la forma de imprimirlos se le suman datos adicionales que no se encuentran en el objeto original.
Por oto lado ya dispongo de la implementacion de las clases para implementar un dispatcher para poder evaluar en función del tipo especifico.
Vamos al codigo de ejemplo:


struct Der1;
struct Der2;

struct Visitor
{
    virtual void exec(Der1 &) = 0;
    virtual void exec(Der2 &) = 0;
};

struct Base
{
    virtual void accept(Visitor &) = 0;
};
struct Der1 : Base
{
    virtual void accept(Visitor & visitor)
    {
        visitor.exec(*this);
    }
};
struct Der2 : Base
{
    virtual void accept(Visitor & visitor)
    {
        visitor.exec(*this);
    }
};

struct Printer : Visitor
{    
    std::string output;

    virtual void exec(Der1 &)
    {
        // En este punto no tengo forma directa de tener la ExtraData
        // Lo que si puedo hacer es construir un printer concreto para cada Objeto Der al que le pase luego la extra data
        // En otras palabras esta clase podrida ser un printer builder para retornar un printer especifico para cada Der,
        // En ese caso, tambien me queda la duda de como almacenar la info de Der, ya que no me gustaria mantener una referencia por si luego ese printer se encola para procesarla luego.
        
    }
    virtual void exec(Der2 &)
    {
    
    
    }
};


struct ExtraData
{
    // data
};


int main()
{
    Der1 d;
    
    Printer p;   

    d.accept(p);

    std::cout << p.output;

}

Esto debe ser mas comun de lo que pienso y creo aun me la estoy complicando.
Hay que agregar que el echo que el accept no retorna nada no me simplifica la cosa, pero agregar otra funcion virtual que me retorne un printer me parece que estaria acoplando demasiado

Alguna idea?

Muchas Gracias




dgutson .

unread,
Mar 3, 2018, 8:01:23 AM3/3/18
to cppba
No entiendo.

Si la instancia de extra data no depende de los vositables, por que no se la pasas al visitor antes de empezar a visitar?

struct Visitor
{
    virtual void exec(Der1 &) = 0;
    virtual void exec(Der2 &) = 0;
    virtual setExtraData(const ExtraData&) =0;
};

y la setteás al principio. 

O si no es genérico de todos los visitors, entonces como arg al ctor de Printer.



--
--
¿Eres miembro de "CyC++ Buenos Aires" verdad? Si no lo eres, has recibido este mesaje por error.
En caso de duda visita "http://groups.google.com/group/cppba"
---
Has recibido este mensaje porque estás suscrito al grupo "CyC++ Buenos Aires" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a cppba+unsubscribe@googlegroups.com.
Para acceder a más opciones, visita https://groups.google.com/d/optout.

Juan Manuel Ollé

unread,
Mar 3, 2018, 8:21:00 AM3/3/18
to cp...@googlegroups.com
Ambos casos los explore.
Fui por el lado de tener printers para cada objeto ya que no se imprimen igual. No me termina de convencer de guardar una referencia y tampoco copiar la data que voy a necesitar despues.
cambiando el ejemplo original (suponer constructores y funciones varias)

struct Printer {};
struct Der1Printer : Printer {};
struct Der1Printer : Printer {};

struct PrinterBuilder : Visitor
{
    Printer * printer;

    virtual void exec(Der1 & d)
    {
        // No queria pasarle aca directamente el objeto para no gustar referencia. 
        // Salvo que solo extraiga la info que necesito para imprimir, pero implicacir copiar informacion que tampoco la quiero hacer
        printer = new Der1Printer(d);
    }
    virtual void exec(Der2 & d)
    {    
        printer = new Der2Printer(d);
    }
};


struct ExtraData
{
    // data
};


int main()
{
    ExtraData extra;
    Der1 d;
    
    PrinterBuilder p;

    d.accept(p);

    std::cout << p.printer->print(extra);

}


En este caso concreto necesito un json. lo que si puedo hacer es que el Printer tenga el documento de json, agregue los datos especificos para que luego llamando a una funcion mas agregue los datos de extra
De hacer eso posiblemente no necesite un printer especifico para cada objeto y el visitador que ya posee el dispatcher pordia armar lo que se necesita. dejando la jerarquia para un XMLPrinter : Visitor, JSONPrinter: Visitor etc

Suena razonable?
El la forma correcta de desacoplar los datos de la logica de impresion?


dgutson .

unread,
Mar 3, 2018, 8:24:54 AM3/3/18
to cppba
No entiendo el problema. Explicás mucho las soluciones que no te funcionaron en vez del problema en sí.
Por qué nonsirve un unico visotor concreto que haga cosas distintas en sus visit?

Tu problema no es de dual dispatching no?

Juan Manuel Ollé

unread,
Mar 3, 2018, 8:48:54 AM3/3/18
to cp...@googlegroups.com
Si, el espaniol me complica un poco.

" El problema es la de separar los datos de la forma de imprimirlos, el problema radica en que a la forma de imprimirlos se le suman datos adicionales que no se encuentran en el objeto original."

Resumiendo es como agregar esa info que no viene en el evento y no se la puedo pasar como parametro.

Puedo contruir el Visitor con esa info, despues procesarla ahi o crear otro objeto y pasarla.
Lo que si quiero evitar es copar info o guardar referencias.


dgutson .

unread,
Mar 3, 2018, 9:00:02 AM3/3/18
to cppba
Escribilo en inglés si no. Cuál es el problema de q el visitor tenga una ref a información extra?

Juan Manuel Ollé

unread,
Mar 3, 2018, 9:09:29 AM3/3/18
to cp...@googlegroups.com
No que me cuesta mas que el espaniol.

Que si el dia de maniana no lo proceso en el mismo hilo esa referencia puede ser invalida.

De todas maneras me parece que lo mas simple en este caso es crear un visitor concreto y visitar el objeto, luego agregar la exta data.

Muchas Gracias

dgutson .

unread,
Mar 3, 2018, 10:03:41 AM3/3/18
to cppba


El mar. 3, 2018 11:09 AM, "Juan Manuel Ollé" <juanman...@gmail.com> escribió:
No que me cuesta mas que el espaniol.

Que si el dia de maniana no lo proceso en el mismo hilo esa referencia puede ser invalida.


O sea ahora aparece concurrencia. Y de qué manera un printer para cada tipo de objeto visitable solucionaría tu problema? (Además del connascent hierarchies antipattern)

Juan Manuel Ollé

unread,
Mar 3, 2018, 10:07:16 AM3/3/18
to cp...@googlegroups.com
La verdad de ninguna. Por eso la descarte

dgutson .

unread,
Mar 3, 2018, 10:23:53 AM3/3/18
to cppba


El mar. 3, 2018 12:07 PM, "Juan Manuel Ollé" <juanman...@gmail.com> escribió:
La verdad de ninguna. Por eso la descarte

No sólo no tiene ninguna ventaja sinonque tiene al menos dos desventajas que por razones didácticas las voy a explicar:

* requería que hayan dos jerarquías connascientes (lo cual es un antipattern en casintodos los casos): la de objetos imprimibles y la de printers. Dos jerarquías de clases son connascientes cuando cada vez que una sufre una modificación, hay que hacerla en la otra, con lo cual tienen la misma estructura pero son jerarquías separadas (un caso particular de jerarquías connascientes es cuando cada clase de una tiene una correspondiente en la otra). De esta forma llevan a un esfuerzo innecesario de mantenimiento duplicado y generalmente en la caja traen un frasquito de givenchy aroma culo. Un triste ejemplo en los albores de la STL fueron los contenedores y los iteradores. Eso ya casi no es más así.

* requería operaciones de manejo de memoria en runtime (allocs/deallocs). Usar memoria dinámica como parte de un algoritmo es algo que debería ser evitado a oda costa a menos que de hecho el algoritmo utilice una estructura de datos dinámica como una lista o arbol. No era el caso así que no excusa. Este tipo de situaciones son 100% indeseables en: embedded (puede no haber un memory manager), high availability (x fragmentación), hpc, y control systems (memory management es no determinístico x default con lo cual desincroniza todos los lazos de control). Además siempre está la posibilidad de que te sacuda una excepción x falta de memoria y tengas que hacer recovery.

dgutson .

unread,
Mar 3, 2018, 10:26:32 AM3/3/18
to cppba
Pd: al final encontraste una solución? Xq yo sigo sin entender el problema:)

Juan Manuel Ollé

unread,
Mar 3, 2018, 2:29:56 PM3/3/18
to cp...@googlegroups.com
Si, gracias.

Lo de las dos jerarquías no conocía el nombre pero si había detectado el problema de mantenerlas.

Lo termine solucionando con un Visitor concreto, el cual es aceptado por los objetos y luego le paso el extra data. el único inconveniente es que al agregar una nueva especialización de las clases visitadas hay que agregar un método que la acepte.
Pero de todas formas alguien tienen que ejecutar la lógica.

El dia de maniana si a alguien se le ocurre en serializar a XML simplemente se crea el correspondiente

dgutson .

unread,
Mar 3, 2018, 4:16:29 PM3/3/18
to cppba


El mar. 3, 2018 16:29, "Juan Manuel Ollé" <juanman...@gmail.com> escribió:
Si, gracias.

Lo de las dos jerarquías no conocía el nombre pero si había detectado el problema de mantenerlas.

Lo termine solucionando con un Visitor concreto, el cual es aceptado por los objetos y luego le paso el extra data. el único inconveniente es que al agregar una nueva especialización de las clases visitadas hay que agregar un método que la acepte.

Esa es justamente la naturaleza y la principal característica del visitor. Pero si fuésemos marido y mujer te diría "ves que no me prestás atención" cuando te mencioné el dual dispatching. 
Reply all
Reply to author
Forward
0 new messages