[Madrid-pm] Construcción e inicialización de objetos

DervishD bugs en dervishd.net
Mar Abr 3 00:35:54 PDT 2007


    Hola Victor :)

 * Victor Moral <victor en taquiones.net> dixit:
> El Lunes, 2 de Abril de 2007 16:08, DervishD escribió:
> > Pero pensemos en Perl: usando "inside-out objects", que en mi
> > opinión son una idea genial, separar la construcción (que sería un
> > simple "bless") de la inicialización permite implementar incluso
> > herencia múltiple, haciendo que el hijo haga el "bless" y luego
> > llame por turnos a todos los "init" de las clases padre.
> 
> Hombre, tanto como "por turnos", será cuestión más bien que despacha
> hacia arriba la inicialización y luego, con lo que vuelva, añade la
> suya. Que eso daría para hablar mucho sobre el mecanismo SUPER, que
> tiene bastantes carencias y no nos queda otra que vivir con él. 

    Por eso precisamente decía "por turnos": en el caso de herencia
múltiple, no vale con usar SUPER, hay que ir padre por padre invocando
el método correcto. Si usas SUPER::init, encontrará el método init de
uno sólo de los padres.

    Otra razón por la que no me acaba de gustar la herencia múltiple,
pero bueno. Y es cierto lo que dices de SUPER, pero de momento habrá que
apañarse con eso.

> > Sin embargo, Conway en su libro "Object Oriented Perl" dice que
> > separar por completo ambas cosas puede ser contraproducente. No
> > recuerdo las frases exactas pero menciona algo de "excesiva
> > paranoia" o algo así, refiriéndose a que es poco o nada necesario
> > hacerlo.
> 
> Y estoy de acuerdo con eso. Desde el punto de vista del usuario de la
> clase es más fácil acostumbrarse a que el constructor retorne el
> objeto inicializado, que hacerlo en una llamada posterior e
> independiente. Eso sí, creo que se debe dar la posibilidad de tener un
> método "init" para el caso, aunque sea el constructor el que lo llame;
> cuestión de claridez en el código y posibilidad de sobrecargar dicho
> método en clases derivadas.

    Exacto, creo que eso tiene lo mejor de ambos mundos: por un lado no
añade el engorro de llamar a dos métodos para inicializar un objeto, por
otro permite "ajuste fino".

> >     Yo en general opino que esta separación es útil sólo para
> > implementar herencia múltiple (al menos a mí no se me ocurren más
> > ventajas) y este tipo de herencia me parece muy mala idea, no da más que
> > quebraderos de cabeza y al menos en mi experiencia personal, siempre que
> > en un diseño ha salido herencia múltiple se ha podido cambiar por un
> > diseño más sencillo y más fácil de manejar usando sólo herencia simple y
> > relaciones de uso, no de gen-spec (muchas veces se usa herencia múltiple
> > cuando se quiere especializar una clase y usar los servicios de otra, y
> > eso yo lo considero un error). De ahí que aunque vea claros beneficios
> > en el hecho de separar construcción de inicialización no me parezca una
> > buena idea y personalmente no lo haga.
> 
> Interesante. ¿ No lo separas ni siquiera en la implementación ? Yo uso algo 
> como esto:

    Sí, en la implementación sí lo hago, pero no exporto el método
"init". Y bueno, para ser sincero, no siempre uso un método "init" si la
inicialización es muy simple y no espero derivar de la clase.

> > Por supuesto no quiero empezar una flamewar sobre si la herencia
> > múltiple es buena o mala, para gustos los colores, y tampoco digo que en
> > el futuro no vaya a usar separación entre construcción e inicialización
> 
> El problema de la herencia múltiple es que no siempre tienes opción de 
> evitarla.

    Obviamente, si tú no haces el diseño completo, en cuanto estás
usando clases de otros hay veces que no te quedan más narices :((

> Es más muchas veces no sabes que estás usándola a menos que leas el
> código que utilizas. Sí, ya se, no usas mucho módulos de CPAN y sueles
> construirte los tuyos, pero como yo sí, te digo que a veces es
> inevitable.

    Te creo. Algunas veces en algunos trabajos me han acusado de que me
gusta mucho rehacer cosas que ya están hechas, pero para mi satisfacción
he acabado demostrando que en muchas ocasiones es más rentable a medio y
largo plazo, sobre todo si el proyecto va a evolucionar bastante. Esto
ha significado que he podido arreglar algunos diseños que hubiesen sido
nefastos de usar soluciones existentes.

    Obviamente no estoy loco, así que ni de coña me meto en determinados
berenjenales, pero si después de estudiar lo que hay valoro que puede
dar dolores de cabeza y mucho gasto en mantenimiento, prefiero dedicar
tiempo ahora a mejorar el diseño si se puede (y pocas veces se puede,
pero bueno).

> Un ejemplo de ello, y esto es una disgresión, es el módulo
> DBIx::Class, con varias mejoras sobre Class::DBI, pero que utiliza
> Class::C3 para lidiar con la herencia múltiple que él mismo produce.
> El resultado es bastante caótico y muy difícil de utilizar como base
> de herencia. Acabo de hacer la prueba y he tenido que dejarlo por
> imposible; Class::C3 toquetea directamente la tabla de símbolos y la
> herencia "normal" de Perl deja de funcionar como esperas.

    A esto me refiero cuando digo que muchas veces es mejor rehacer las
cosas. Claro que cualquiera se mete con esto que mencionas... Creo que
en este caso es mejor aguantar el chaparrón y ver qué se puede apañar.
 
> Resumiendo, creo que se debe separar la inicialización de la construcción en 
> el lado de implementación, pero no en el lado de uso.

    Yo opino parecido, sólo que algunas veces ni siquiera separo en el
lado de la implementación, según me parezca. Tampoco he programado
muchos diseños orientados a objetos en Perl, el grueso lo he hecho en C.

    Raúl Núñez de Arenas Coronado

-- 
Linux Registered User 88736 | http://www.dervishd.net
It's my PC and I'll cry if I want to... RAmen!


Más información sobre la lista de distribución Madrid-pm