Programación con un gestor de base de datos orientado a objetos

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
36 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Programación con un gestor de base de datos orientado a objetos

gerard alis
Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
pruebas, para trabajar con una base de datos orientada a objetos. Como
solo quería hacer unas pocas pruebas me he decantado por Magma y
Pharo.

Ahora bien, mi problema es que dudo sobre la manera en que deben
hacerse según que cosas cuando guardas datos como objetos.

1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
jornadas, correcto? Es lógico pensar que cada objeto temporada debería
de tener una colección de objetos jornada. Ahora bien, cada objeto
jornada debería tener una referencia a su tempoarada no? bien, al
menos en algunos ORMs lo he visto.

2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
temporada, y a su vez todos los partidos etc etc lo que vendría a ser
una ON DELETE CASCADE de las BBDD relacionales...

Básicamente da la sensación de que sería relativamente fácil en un
momento dado dejar datos inconsistentes en la BD, o que en volúmenes
de datos grandes a la hora de patearse una colección inmensa la demora
sería muy grande... o que no tienes según que automatismos, cómo los
triggers, para asegurarte que suceda algo al añadir un nuevo registro
etc etc

Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
objetos?

Saludos y gracias por la ayuda.

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Mariano Martinez Peck


2011/1/11 gerard <[hidden email]>
Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
pruebas, para trabajar con una base de datos orientada a objetos. Como
solo quería hacer unas pocas pruebas me he decantado por Magma y
Pharo.

Ahora bien, mi problema es que dudo sobre la manera en que deben
hacerse según que cosas cuando guardas datos como objetos.

1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
jornadas, correcto? Es lógico pensar que cada objeto temporada debería
de tener una colección de objetos jornada. Ahora bien, cada objeto
jornada debería tener una referencia a su tempoarada no? bien, al
menos en algunos ORMs lo he visto.

No necesariamente. En una verdadera base de objetos creo que eso debería ser indiferente. Si por tu negocio tiene sentido, entonces sí. Sino, no. Además podes pensar en responsabilidades, y no datos. Ponele, yo podría pedirle a una jornada su temporada, pero ésta no está como variable de instancia, sino que hace una búsqueda sobre todas las temporadas para ver quien tiene a dicha jornada. Todo esto para darte un ejemplo.
 

2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
temporada, y a su vez todos los partidos etc etc lo que vendría a ser
una ON DELETE CASCADE de las BBDD relacionales...

Acá tenes que tener en cuenta que en Smalltalk no podes borar un objecto. Lo máximo que podes hacer es desreferenciarlo.
En tu ejemplo, cuando elimines una temporada, se borrarán todas las referenias a las jornadas. Si algunas de esas jornadas estaba solamente siendo referenciadas por esa temporada, entonces cuando corra el garbage collector se la llevará. Mientras tanto (hasta que venga el GC) no pueden ser accedidas desde ningún otro objecto, así que no pasa nada.
 
El único problema sería si tu código de negocio haría chanchadas como Jornada allInstances   pues ahí si todavía estan visibles los objectos (hasta que pase el GC).
Pero por lo general las applicaciones tiene roots o objectos donde las cosas están almacenadas. No soles haces un allInstances.


Básicamente da la sensación de que sería relativamente fácil en un
momento dado dejar datos inconsistentes en la BD,

No. No debería haber inconcistencias.
 
o que en volúmenes
de datos grandes a la hora de patearse una colección inmensa la demora
sería muy grande...

es cierto que el GC en bases de objectos no es trivial y si, la performance es importante.
 
o que no tienes según que automatismos, cómo los
triggers, para asegurarte que suceda algo al añadir un nuevo registro
etc etc

Esto es fácil. Es Smalltalk. Las cosas se resuelven en los objectos. Suponete que quiero trigear algo cuando se agrega una jornada a una Temporada...fácil:

Temporada >> addJornada: unaJornada
self hacerLoQuiera.
self jornadas add: unaJornada

Y listo. Bueno, en magma deberías tener un diccionario donde desde algún lugar lleges a la temporada no....

 

Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
objetos?


Ni idea. Pero seguramente Smalltalk es de lo más existente en relación a bases de objetos
 
Saludos y gracias por la ayuda.


saludos
 
--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

fvozzi
In reply to this post by gerard alis
Hola,
Mariano ya te respondió casi todo, para agregar algo, podés leer sobre algunos enfoques de persistencia (incluído Magma) en el libro de Seaside: http://book.seaside.st/book/advanced/persistency

Vas a ver que hablan de persistencia basada en Imagen, que es solo eso guardar la imagen con una global que apunte a tu root (un singleton, por ejemplo). Después cambiar a que se persista con Magma o Goods es casi un tramite para GemStone tenés que laburar un cacho más.

Respecto de las relaciones, los delete cascade, triggers y cualquier yerba de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar una base de objetos y sacarle provecho tenés que hacer tu módelo lo más orientado a objetos que te salga y no preocuparte por problemas de otro paradigma. Quedate tranquilo que vas a tener otros problemas para resolver :-P pero, simplemente, no los mismos.

Saludos,
Facu

2011/1/11 gerard <[hidden email]>
Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
pruebas, para trabajar con una base de datos orientada a objetos. Como
solo quería hacer unas pocas pruebas me he decantado por Magma y
Pharo.

Ahora bien, mi problema es que dudo sobre la manera en que deben
hacerse según que cosas cuando guardas datos como objetos.

1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
jornadas, correcto? Es lógico pensar que cada objeto temporada debería
de tener una colección de objetos jornada. Ahora bien, cada objeto
jornada debería tener una referencia a su tempoarada no? bien, al
menos en algunos ORMs lo he visto.

2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
temporada, y a su vez todos los partidos etc etc lo que vendría a ser
una ON DELETE CASCADE de las BBDD relacionales...

Básicamente da la sensación de que sería relativamente fácil en un
momento dado dejar datos inconsistentes en la BD, o que en volúmenes
de datos grandes a la hora de patearse una colección inmensa la demora
sería muy grande... o que no tienes según que automatismos, cómo los
triggers, para asegurarte que suceda algo al añadir un nuevo registro
etc etc

Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
objetos?

Saludos y gracias por la ayuda.

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

gerard alis
Lo que hecho de menos es una "manera de hacer" estandar que prevenga
que uno haga algunas cosas no del todo recomendables... Aunque sean
objetos no deja de ser una BD, y seguro que pudes hacer algunas
animaladas espectaculares sólo por no tener claro un concepto.

Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
una por separado, de que en ese diccionario exista una entrada con el
mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
idea de que automáticamente ya existiera una colección vinculada a
cada clase Entity... pero ahora veo que quizás eso es una tontería y
que sería perfectamente válida una instancia root que tuviera un
montón de colecciones, una por cada entidad. Por otro lado veo algunos
ejemplos o screencast de Magma que usan el otro sistema: una entrada
en un diccionario por cada entidad.

En fin, me gustaría que todas las clases-entidades tuvieran un
comportamiento homogeneo. En un ORM, al generarse el código, sé que
una relación 1:N me va a generar una clase con una colección y una
serie de métodos estandard, para añadir un elemento a la colección, o
eliminarla etc Es decir un comportamiento general, dependiendo de las
relaciones.

¿Y grandes volúmenes de datos? Si tienes una lista inmensa de
facturación y debes de empezar a patearte los items para obtener las
facturas de un determinado cliente como lo haces? Por un lado podrias
hacer que cada cliente tuviera su propia colección de facturas, con lo
que podrías ir directamente a la colección de facturas del cliente,
perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
colecciones de facturas de los clientes, sería más trabajoso; debería
ir a una lista "general" de facturas y empezar a seleccionar las que
estan en el rango de fechas correcto; es decir, debo tener una
colección de facturas y otras colecciones parciales de facturas en
cada cliente. Podría ir más lejos en el ejemplo y plantear varias
entidades a las que les interesaría tener su propia relación con las
facturas... Bien: ahora el usuario quiere eliminar una factura, y
cuando lo haga debo de ser muy consciente de todas las colecciones
donde puede estar ubicada esa factura para poder eliminarla "bien".
Debo ir a la lista de facturas del cliente, a la lista general de
facturas que he mencionado etc etc   Veo muy complicado no dejarse
ningún cabo suelto. No me refería tanto a que pasara el GC, que
realmente da igual, sino a la posibilidad de dejarse instancias que ya
no deberian estar, de ahí la comparación con el ON DELETE ACTION.

No sé si me he expresado bien.

Saludos.



On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:

> Hola,
> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
> algunos enfoques de persistencia (incluído Magma) en el libro de Seaside:http://book.seaside.st/book/advanced/persistency.
>
> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
> guardar la imagen con una global que apunte a tu root (un singleton, por
> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
> tramite para GemStone tenés que laburar un cacho más.
>
> Respecto de las relaciones, los delete cascade, triggers y cualquier yerba
> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar una
> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
> orientado a objetos que te salga y no preocuparte por problemas de otro
> paradigma. Quedate tranquilo que vas a tener otros problemas para resolver
> :-P pero, simplemente, no los mismos.
>
> Saludos,
> Facu
>
> 2011/1/11 gerard <[hidden email]>
>
>
>
>
>
>
>
> > Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
> > pruebas, para trabajar con una base de datos orientada a objetos. Como
> > solo quería hacer unas pocas pruebas me he decantado por Magma y
> > Pharo.
>
> > Ahora bien, mi problema es que dudo sobre la manera en que deben
> > hacerse según que cosas cuando guardas datos como objetos.
>
> > 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
> > jornadas, correcto? Es lógico pensar que cada objeto temporada debería
> > de tener una colección de objetos jornada. Ahora bien, cada objeto
> > jornada debería tener una referencia a su tempoarada no? bien, al
> > menos en algunos ORMs lo he visto.
>
> > 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
> > que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
> > temporada, y a su vez todos los partidos etc etc lo que vendría a ser
> > una ON DELETE CASCADE de las BBDD relacionales...
>
> > Básicamente da la sensación de que sería relativamente fácil en un
> > momento dado dejar datos inconsistentes en la BD, o que en volúmenes
> > de datos grandes a la hora de patearse una colección inmensa la demora
> > sería muy grande... o que no tienes según que automatismos, cómo los
> > triggers, para asegurarte que suceda algo al añadir un nuevo registro
> > etc etc
>
> > Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
> > objetos?
>
> > Saludos y gracias por la ayuda.
>
> > --
> > To post to this group, send email to [hidden email]
> > To unsubscribe from this group, send email to
> > [hidden email]<clubSmalltalk%[hidden email]>
>
> >http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Andres Fortier-2
Que tal Gerard. Mas allá de lo que ya te comentaron, mi humilde aporte
es que no te vuelvas loco con potenciales problemas de performance antes
de tiempo. Uno muchas veces trae preconcpetos de otros paradigmas que no
aplican en el entorno de trabajo actual. Por ejemplo, en el caso que
mencionás de las facturas, tené en cuenta que los objetos se cargan por
demanda y, dependiendo de la BDOO, uno puede definir índices. O sea que
si en tu modelo te parece correcto que un cliente tenga sus facturas y
luego necesitás iterar por todas las facturas entre dos fechas pasando
por los clientes, eso no implica que tengas que traer a memoria todas
las facturas persistidas. Cuando se levante un cliente sus v.i.
seguramente serán proxies a disco y al hacer la consulta lo harás por el
índice, por lo que no vas a necesitar traer a memoria instancias que no
te sirven. Esto implica que va a ser igual de rápido que hacer un
"select" sobre la clase Factura directamente? Seguramente no, va a ser
mas lento, pero a lo que apunto es que no te mandes a hacer optimización
temprana por cosas que no sabés si van a ser un problema.

Respecto del problema de consistencia (i.e. de tener dos colecciones de
facturas -la del cliente vs. el listado general- que tienen que estar
sincronizadas) fijate que es un problema de diseño, no de persistencia.
Ese mismo problema lo tendrías si lo hacés en memoria. En líneas
generales deberías intentar evitar ese tipo de cosas, o asegurarte que
manejas bien la consistencia, cosa que puede ser simple o complicada
dependiendo de lo organizado que seas para programar :).

Mis 2 ctvs.

Saludos,
         Andrés


gerard escribió:

> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
> que uno haga algunas cosas no del todo recomendables... Aunque sean
> objetos no deja de ser una BD, y seguro que pudes hacer algunas
> animaladas espectaculares sólo por no tener claro un concepto.
>
> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
> una por separado, de que en ese diccionario exista una entrada con el
> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
> idea de que automáticamente ya existiera una colección vinculada a
> cada clase Entity... pero ahora veo que quizás eso es una tontería y
> que sería perfectamente válida una instancia root que tuviera un
> montón de colecciones, una por cada entidad. Por otro lado veo algunos
> ejemplos o screencast de Magma que usan el otro sistema: una entrada
> en un diccionario por cada entidad.
>
> En fin, me gustaría que todas las clases-entidades tuvieran un
> comportamiento homogeneo. En un ORM, al generarse el código, sé que
> una relación 1:N me va a generar una clase con una colección y una
> serie de métodos estandard, para añadir un elemento a la colección, o
> eliminarla etc Es decir un comportamiento general, dependiendo de las
> relaciones.
>
> ¿Y grandes volúmenes de datos? Si tienes una lista inmensa de
> facturación y debes de empezar a patearte los items para obtener las
> facturas de un determinado cliente como lo haces? Por un lado podrias
> hacer que cada cliente tuviera su propia colección de facturas, con lo
> que podrías ir directamente a la colección de facturas del cliente,
> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
> colecciones de facturas de los clientes, sería más trabajoso; debería
> ir a una lista "general" de facturas y empezar a seleccionar las que
> estan en el rango de fechas correcto; es decir, debo tener una
> colección de facturas y otras colecciones parciales de facturas en
> cada cliente. Podría ir más lejos en el ejemplo y plantear varias
> entidades a las que les interesaría tener su propia relación con las
> facturas... Bien: ahora el usuario quiere eliminar una factura, y
> cuando lo haga debo de ser muy consciente de todas las colecciones
> donde puede estar ubicada esa factura para poder eliminarla "bien".
> Debo ir a la lista de facturas del cliente, a la lista general de
> facturas que he mencionado etc etc   Veo muy complicado no dejarse
> ningún cabo suelto. No me refería tanto a que pasara el GC, que
> realmente da igual, sino a la posibilidad de dejarse instancias que ya
> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>
> No sé si me he expresado bien.
>
> Saludos.
>
>
>
> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>> Hola,
>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>> algunos enfoques de persistencia (incluído Magma) en el libro de Seaside:http://book.seaside.st/book/advanced/persistency.
>>
>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>> guardar la imagen con una global que apunte a tu root (un singleton, por
>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>> tramite para GemStone tenés que laburar un cacho más.
>>
>> Respecto de las relaciones, los delete cascade, triggers y cualquier yerba
>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar una
>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>> orientado a objetos que te salga y no preocuparte por problemas de otro
>> paradigma. Quedate tranquilo que vas a tener otros problemas para resolver
>> :-P pero, simplemente, no los mismos.
>>
>> Saludos,
>> Facu
>>
>> 2011/1/11 gerard <[hidden email]>
>>
>>
>>
>>
>>
>>
>>
>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>> Pharo.
>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>> hacerse según que cosas cuando guardas datos como objetos.
>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>> menos en algunos ORMs lo he visto.
>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>> una ON DELETE CASCADE de las BBDD relacionales...
>>> Básicamente da la sensación de que sería relativamente fácil en un
>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>> etc etc
>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>> objetos?
>>> Saludos y gracias por la ayuda.
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<clubSmalltalk%[hidden email]>
>>> http://www.clubSmalltalk.org
>

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

fvozzi
In reply to this post by gerard alis


2011/1/12 gerard <[hidden email]>
Lo que hecho de menos es una "manera de hacer" estandar que prevenga
que uno haga algunas cosas no del todo recomendables... Aunque sean
objetos no deja de ser una BD, y seguro que pudes hacer algunas
animaladas espectaculares sólo por no tener claro un concepto.
 
No, no es una BD es una base de objetos no de datos. Lo de hacer "animaladas", y bueno, sí, yo hice un montón y después con la experiencia vas haciendo menos. Creo que si te olvidás de la persistencia y grabás el image es la manera más simple de no pensar orientado a tablas pero bueno, paciencia.


Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
una por separado, de que en ese diccionario exista una entrada con el
mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
idea de que automáticamente ya existiera una colección vinculada a
cada clase Entity... pero ahora veo que quizás eso es una tontería y
que sería perfectamente válida una instancia root que tuviera un
montón de colecciones, una por cada entidad. Por otro lado veo algunos
ejemplos o screencast de Magma que usan el otro sistema: una entrada
en un diccionario por cada entidad.

Yo guardo una instancia de "XXXSystem" (un singleton) como root pero se puede guardar, como decís vos, cualquier otra cosa.
 

En fin, me gustaría que todas las clases-entidades tuvieran un
comportamiento homogeneo. En un ORM, al generarse el código, sé que
una relación 1:N me va a generar una clase con una colección y una
serie de métodos estandard, para añadir un elemento a la colección, o
eliminarla etc Es decir un comportamiento general, dependiendo de las
relaciones.

Bueno, si querés podés, si te sentís cómodo con eso, podés hacer algo similar no creo que dependa de la persistencia eso. Otra opción es usar los métodos estandar de Collection para hacer eso.
 

¿Y grandes volúmenes de datos? Si tienes una lista inmensa de
facturación y debes de empezar a patearte los items para obtener las
facturas de un determinado cliente como lo haces? Por un lado podrias
hacer que cada cliente tuviera su propia colección de facturas, con lo
que podrías ir directamente a la colección de facturas del cliente,
perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
colecciones de facturas de los clientes, sería más trabajoso; debería
ir a una lista "general" de facturas y empezar a seleccionar las que
estan en el rango de fechas correcto; es decir, debo tener una
colección de facturas y otras colecciones parciales de facturas en
cada cliente.

Cada cliente tiene su colección de facturas y cuando consultes un rango de fechas, le pedís a todos tus clientes las facturas, las ordenas y las seleccionás. Cuando eso se ponga lento porque tenés muchas facturas, o mejor dicho, muchos clientes, ahí agregar a tu sistema, o a tu empresa, una collección indexada con todas las facturas (es barato, es solo una referencia más a cada factura). Y sí, tenés que programar ordenadamente la consistencia como dice Andrés.
 
Podría ir más lejos en el ejemplo y plantear varias
entidades a las que les interesaría tener su propia relación con las
facturas... Bien: ahora el usuario quiere eliminar una factura, y
cuando lo haga debo de ser muy consciente de todas las colecciones
donde puede estar ubicada esa factura para poder eliminarla "bien".
Debo ir a la lista de facturas del cliente, a la lista general de
facturas que he mencionado etc etc   Veo muy complicado no dejarse
ningún cabo suelto. No me refería tanto a que pasara el GC, que
realmente da igual, sino a la posibilidad de dejarse instancias que ya
no deberian estar, de ahí la comparación con el ON DELETE ACTION.

Ummm, puede pasar que te olvides de sacarlo de algún lado pero salta con cualquier test. Lo agregás y listo. Debería ser en un solo lugar donde tocar.

 

No sé si me he expresado bien.

Sí, creo que te preguntas cosas porque ya conoces los problemas de otro paradigma y querés anticiparte a todo. Creo que lo mejor, aunque parezca disparatado, es no pensar y solo ponerse a mandar mensajes. Después aparecen solos los problemas y ahí hay que pensar un cacho.
 

Saludos.

Nos vemos
 



On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
> Hola,
> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
> algunos enfoques de persistencia (incluído Magma) en el libro de Seaside:http://book.seaside.st/book/advanced/persistency.
>
> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
> guardar la imagen con una global que apunte a tu root (un singleton, por
> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
> tramite para GemStone tenés que laburar un cacho más.
>
> Respecto de las relaciones, los delete cascade, triggers y cualquier yerba
> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar una
> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
> orientado a objetos que te salga y no preocuparte por problemas de otro
> paradigma. Quedate tranquilo que vas a tener otros problemas para resolver
> :-P pero, simplemente, no los mismos.
>
> Saludos,
> Facu
>
> 2011/1/11 gerard <[hidden email]>
>
>
>
>
>
>
>
> > Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
> > pruebas, para trabajar con una base de datos orientada a objetos. Como
> > solo quería hacer unas pocas pruebas me he decantado por Magma y
> > Pharo.
>
> > Ahora bien, mi problema es que dudo sobre la manera en que deben
> > hacerse según que cosas cuando guardas datos como objetos.
>
> > 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
> > jornadas, correcto? Es lógico pensar que cada objeto temporada debería
> > de tener una colección de objetos jornada. Ahora bien, cada objeto
> > jornada debería tener una referencia a su tempoarada no? bien, al
> > menos en algunos ORMs lo he visto.
>
> > 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
> > que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
> > temporada, y a su vez todos los partidos etc etc lo que vendría a ser
> > una ON DELETE CASCADE de las BBDD relacionales...
>
> > Básicamente da la sensación de que sería relativamente fácil en un
> > momento dado dejar datos inconsistentes en la BD, o que en volúmenes
> > de datos grandes a la hora de patearse una colección inmensa la demora
> > sería muy grande... o que no tienes según que automatismos, cómo los
> > triggers, para asegurarte que suceda algo al añadir un nuevo registro
> > etc etc
>
> > Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
> > objetos?
>
> > Saludos y gracias por la ayuda.
>
> > --
> > To post to this group, send email to [hidden email]
> > To unsubscribe from this group, send email to
> > [hidden email]<[hidden email]>
>
> >http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Juan-2
In reply to this post by Mariano Martinez Peck
Mariano

 
El único problema sería si tu código de negocio haría chanchadas como Jornada allInstances   pues ahí si todavía estan visibles los objectos (hasta que pase el GC).
Pero por lo general las applicaciones tiene roots o objectos donde las cosas están almacenadas. No soles haces un allInstances.
Tengo entendido q allInstances llama primero al gc. por lo menos en Dolphin
y Va no recuerdo si squeak . supongo que depende de cada smalltalk .
Hasta donde yo se
saludos
MDC
 


Básicamente da la sensación de que sería relativamente fácil en un
momento dado dejar datos inconsistentes en la BD,

No. No debería haber inconcistencias.
 
o que en volúmenes
de datos grandes a la hora de patearse una colección inmensa la demora
sería muy grande...

es cierto que el GC en bases de objectos no es trivial y si, la performance es importante.
 
o que no tienes según que automatismos, cómo los
triggers, para asegurarte que suceda algo al añadir un nuevo registro
etc etc

Esto es fácil. Es Smalltalk. Las cosas se resuelven en los objectos. Suponete que quiero trigear algo cuando se agrega una jornada a una Temporada...fácil:

Temporada >> addJornada: unaJornada
self hacerLoQuiera.
self jornadas add: unaJornada

Y listo. Bueno, en magma deberías tener un diccionario donde desde algún lugar lleges a la temporada no....

 

Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
objetos?


Ni idea. Pero seguramente Smalltalk es de lo más existente en relación a bases de objetos
 
Saludos y gracias por la ayuda.


saludos
 
--

To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Mariano Martinez Peck


2011/1/12 Juan <[hidden email]>
Mariano

 
El único problema sería si tu código de negocio haría chanchadas como Jornada allInstances   pues ahí si todavía estan visibles los objectos (hasta que pase el GC).
Pero por lo general las applicaciones tiene roots o objectos donde las cosas están almacenadas. No soles haces un allInstances.
Tengo entendido q allInstances llama primero al gc. por lo menos en Dolphin
y Va no recuerdo si squeak . supongo que depende de cada smalltalk .

jejejejjeje justo antes de mandar el mail, le pregunté exactamente lo mismo que vos. Revisé el código y no vi que lo llame. Después hice un:

| test |
Transcript show: 'TestCase instances: ', TestCase instanceCount asString.
test := TestCase new.
Transcript show: 'TestCase instances: ', TestCase instanceCount asString.
test := nil.
Transcript show: 'TestCase instances: ', TestCase instanceCount asString.
Smalltalk garbageCollect.
Transcript show: 'TestCase instances: ', TestCase instanceCount asString.

Y en el workspace vi:

TestCase instances: 0TestCase instances: 1TestCase instances: 1TestCase instances: 0


tal vez está mal mi "test"
 
Hasta donde yo se
saludos
MDC
 


Básicamente da la sensación de que sería relativamente fácil en un
momento dado dejar datos inconsistentes en la BD,

No. No debería haber inconcistencias.
 
o que en volúmenes
de datos grandes a la hora de patearse una colección inmensa la demora
sería muy grande...

es cierto que el GC en bases de objectos no es trivial y si, la performance es importante.
 
o que no tienes según que automatismos, cómo los
triggers, para asegurarte que suceda algo al añadir un nuevo registro
etc etc

Esto es fácil. Es Smalltalk. Las cosas se resuelven en los objectos. Suponete que quiero trigear algo cuando se agrega una jornada a una Temporada...fácil:

Temporada >> addJornada: unaJornada
self hacerLoQuiera.
self jornadas add: unaJornada

Y listo. Bueno, en magma deberías tener un diccionario donde desde algún lugar lleges a la temporada no....

 

Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
objetos?


Ni idea. Pero seguramente Smalltalk es de lo más existente en relación a bases de objetos
 
Saludos y gracias por la ayuda.


saludos
 
--

To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

hernanmd
In reply to this post by gerard alis
Hola Gerard,

El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
> que uno haga algunas cosas no del todo recomendables... Aunque sean
> objetos no deja de ser una BD, y seguro que pudes hacer algunas
> animaladas espectaculares sólo por no tener claro un concepto.
>

Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
the relational wall", te va a servir para lo conceptual.

> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
> una por separado, de que en ese diccionario exista una entrada con el
> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
> idea de que automáticamente ya existiera una colección vinculada a
> cada clase Entity... pero ahora veo que quizás eso es una tontería y
> que sería perfectamente válida una instancia root que tuviera un
> montón de colecciones, una por cada entidad. Por otro lado veo algunos
> ejemplos o screencast de Magma que usan el otro sistema: una entrada
> en un diccionario por cada entidad.
>

Es preferible que el objeto raíz sea un objeto de "primera clase"
(Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
existir varias variables de instancia nombradas que podés hacer
colecciones. Magma no te hace problemas si agregas nuevas variables de
instancia a ese objeto raíz.

> En fin, me gustaría que todas las clases-entidades tuvieran un
> comportamiento homogeneo. En un ORM, al generarse el código, sé que
> una relación 1:N me va a generar una clase con una colección y una
> serie de métodos estandard, para añadir un elemento a la colección, o
> eliminarla etc Es decir un comportamiento general, dependiendo de las
> relaciones.
>
> ¿Y grandes volúmenes de datos?

¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
índices, analizar las consultas que vas a tener, las profundidades de
tus objetos y en base a eso escribir ReadStrategies razonables para
tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
pasando los 128-bits son un dolor de cabeza si tenés millones de
objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
8). Más bits en los indices, más reducidos los resultados de un
#where:, y menos escaneo lineal del #select: posterior, pero más
procesamiento por cada objeto.

> Si tienes una lista inmensa de
> facturación y debes de empezar a patearte los items para obtener las
> facturas de un determinado cliente como lo haces? Por un lado podrias
> hacer que cada cliente tuviera su propia colección de facturas, con lo
> que podrías ir directamente a la colección de facturas del cliente,
> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
> colecciones de facturas de los clientes, sería más trabajoso; debería
> ir a una lista "general" de facturas y empezar a seleccionar las que
> estan en el rango de fechas correcto; es decir, debo tener una
> colección de facturas y otras colecciones parciales de facturas en
> cada cliente.

Lo de las colecciones maestras grandes es una costumbre del mundo
relacional, los programadores relacionales se acostumbran a usarlas
furiosamente, en vez de dispersarlas en el dominio en colecciones más
chicas que no son tan violentadas. Esto no significa que tenés que ir
a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
performance viene cambiando la indexación, pero es una opción para
reducir complejidad.

Una opción interesante es que podés usar #where: y persistir los
resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
te daría consultas predefinidas. Lo bueno es que si persistís un
Reader y agregás más objetos a la colección original luego, es decir,
a la cual le hiciste el #where:, los objetos agregados van a aparecer
la próxima vez que enumeres el Reader. Pero antes de enumerar un
Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
para resultados paginados) tenés que revisar la profundidad de los
objetos que van a ser consultados y hacerte una ReadStrategy
apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader

> Podría ir más lejos en el ejemplo y plantear varias
> entidades a las que les interesaría tener su propia relación con las
> facturas... Bien: ahora el usuario quiere eliminar una factura, y
> cuando lo haga debo de ser muy consciente de todas las colecciones
> donde puede estar ubicada esa factura para poder eliminarla "bien".
> Debo ir a la lista de facturas del cliente, a la lista general de
> facturas que he mencionado etc etc   Veo muy complicado no dejarse
> ningún cabo suelto. No me refería tanto a que pasara el GC, que
> realmente da igual, sino a la posibilidad de dejarse instancias que ya
> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>

Las consultas tambien pueden ser objetos, y como tales pueden ser
persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
performance, usá un Message spy. Si no tenés problemas, escribí como
si nada pasara :)

Saludos


> No sé si me he expresado bien.
>
> Saludos.
>
>
>
> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>> Hola,
>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>> algunos enfoques de persistencia (incluído Magma) en el libro de Seaside:http://book.seaside.st/book/advanced/persistency.
>>
>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>> guardar la imagen con una global que apunte a tu root (un singleton, por
>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>> tramite para GemStone tenés que laburar un cacho más.
>>
>> Respecto de las relaciones, los delete cascade, triggers y cualquier yerba
>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar una
>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>> orientado a objetos que te salga y no preocuparte por problemas de otro
>> paradigma. Quedate tranquilo que vas a tener otros problemas para resolver
>> :-P pero, simplemente, no los mismos.
>>
>> Saludos,
>> Facu
>>
>> 2011/1/11 gerard <[hidden email]>
>>
>>
>>
>>
>>
>>
>>
>> > Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>> > pruebas, para trabajar con una base de datos orientada a objetos. Como
>> > solo quería hacer unas pocas pruebas me he decantado por Magma y
>> > Pharo.
>>
>> > Ahora bien, mi problema es que dudo sobre la manera en que deben
>> > hacerse según que cosas cuando guardas datos como objetos.
>>
>> > 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>> > jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>> > de tener una colección de objetos jornada. Ahora bien, cada objeto
>> > jornada debería tener una referencia a su tempoarada no? bien, al
>> > menos en algunos ORMs lo he visto.
>>
>> > 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>> > que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>> > temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>> > una ON DELETE CASCADE de las BBDD relacionales...
>>
>> > Básicamente da la sensación de que sería relativamente fácil en un
>> > momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>> > de datos grandes a la hora de patearse una colección inmensa la demora
>> > sería muy grande... o que no tienes según que automatismos, cómo los
>> > triggers, para asegurarte que suceda algo al añadir un nuevo registro
>> > etc etc
>>
>> > Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>> > objetos?
>>
>> > Saludos y gracias por la ayuda.
>>
>> > --
>> > To post to this group, send email to [hidden email]
>> > To unsubscribe from this group, send email to
>> > [hidden email]<clubSmalltalk%[hidden email]>
>>
>> >http://www.clubSmalltalk.org
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org



--
Hernán Morales
Information Technology Manager,
Institute of Veterinary Genetics.
National Scientific and Technical Research Council (CONICET).
La Plata (1900), Buenos Aires, Argentina.
Telephone: +54 (0221) 421-1799.
Internal: 422
Fax: 425-7980 or 421-1799.

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Gastón Dall' Oglio
Hola gente.

Capaz es una burrada pero bueno, no me quiero quedar con las dudas.

Supongamos que tengo unaFactura que esta referenciada desde una colección perteneciente a un cliente (sus facturas) y también desde una colección de todas las facturas. Para el tema de resolver el "borrado en cascada" puedo hacer algo como:

unaFactura become: nil

1) Esto me asegura que ya nadie la referencia, y será liberada.
2) Ambas colecciones quedan con la misma cantidad de elementos, solo que ahora tienen una referencia a nil. Que exista una factura nil es fácil de ignorar con un #select: o permanente con un #removeAll:
3) El tiempo normal que demora un #become: aumenta considerablemente por tratarse de objetos persistidos por Magma.

Saludos!

El 12 de enero de 2011 18:40, Hernán Morales Durand <[hidden email]> escribió:
Hola Gerard,

El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
> que uno haga algunas cosas no del todo recomendables... Aunque sean
> objetos no deja de ser una BD, y seguro que pudes hacer algunas
> animaladas espectaculares sólo por no tener claro un concepto.
>

Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
the relational wall", te va a servir para lo conceptual.

> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
> una por separado, de que en ese diccionario exista una entrada con el
> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
> idea de que automáticamente ya existiera una colección vinculada a
> cada clase Entity... pero ahora veo que quizás eso es una tontería y
> que sería perfectamente válida una instancia root que tuviera un
> montón de colecciones, una por cada entidad. Por otro lado veo algunos
> ejemplos o screencast de Magma que usan el otro sistema: una entrada
> en un diccionario por cada entidad.
>

Es preferible que el objeto raíz sea un objeto de "primera clase"
(Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
existir varias variables de instancia nombradas que podés hacer
colecciones. Magma no te hace problemas si agregas nuevas variables de
instancia a ese objeto raíz.

> En fin, me gustaría que todas las clases-entidades tuvieran un
> comportamiento homogeneo. En un ORM, al generarse el código, sé que
> una relación 1:N me va a generar una clase con una colección y una
> serie de métodos estandard, para añadir un elemento a la colección, o
> eliminarla etc Es decir un comportamiento general, dependiendo de las
> relaciones.
>
> ¿Y grandes volúmenes de datos?

¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
índices, analizar las consultas que vas a tener, las profundidades de
tus objetos y en base a eso escribir ReadStrategies razonables para
tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
pasando los 128-bits son un dolor de cabeza si tenés millones de
objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
8). Más bits en los indices, más reducidos los resultados de un
#where:, y menos escaneo lineal del #select: posterior, pero más
procesamiento por cada objeto.

> Si tienes una lista inmensa de
> facturación y debes de empezar a patearte los items para obtener las
> facturas de un determinado cliente como lo haces? Por un lado podrias
> hacer que cada cliente tuviera su propia colección de facturas, con lo
> que podrías ir directamente a la colección de facturas del cliente,
> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
> colecciones de facturas de los clientes, sería más trabajoso; debería
> ir a una lista "general" de facturas y empezar a seleccionar las que
> estan en el rango de fechas correcto; es decir, debo tener una
> colección de facturas y otras colecciones parciales de facturas en
> cada cliente.

Lo de las colecciones maestras grandes es una costumbre del mundo
relacional, los programadores relacionales se acostumbran a usarlas
furiosamente, en vez de dispersarlas en el dominio en colecciones más
chicas que no son tan violentadas. Esto no significa que tenés que ir
a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
performance viene cambiando la indexación, pero es una opción para
reducir complejidad.

Una opción interesante es que podés usar #where: y persistir los
resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
te daría consultas predefinidas. Lo bueno es que si persistís un
Reader y agregás más objetos a la colección original luego, es decir,
a la cual le hiciste el #where:, los objetos agregados van a aparecer
la próxima vez que enumeres el Reader. Pero antes de enumerar un
Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
para resultados paginados) tenés que revisar la profundidad de los
objetos que van a ser consultados y hacerte una ReadStrategy
apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader

> Podría ir más lejos en el ejemplo y plantear varias
> entidades a las que les interesaría tener su propia relación con las
> facturas... Bien: ahora el usuario quiere eliminar una factura, y
> cuando lo haga debo de ser muy consciente de todas las colecciones
> donde puede estar ubicada esa factura para poder eliminarla "bien".
> Debo ir a la lista de facturas del cliente, a la lista general de
> facturas que he mencionado etc etc   Veo muy complicado no dejarse
> ningún cabo suelto. No me refería tanto a que pasara el GC, que
> realmente da igual, sino a la posibilidad de dejarse instancias que ya
> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>

Las consultas tambien pueden ser objetos, y como tales pueden ser
persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
performance, usá un Message spy. Si no tenés problemas, escribí como
si nada pasara :)

Saludos


> No sé si me he expresado bien.
>
> Saludos.
>
>
>
> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>> Hola,
>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>> algunos enfoques de persistencia (incluído Magma) en el libro de Seaside:http://book.seaside.st/book/advanced/persistency.
>>
>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>> guardar la imagen con una global que apunte a tu root (un singleton, por
>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>> tramite para GemStone tenés que laburar un cacho más.
>>
>> Respecto de las relaciones, los delete cascade, triggers y cualquier yerba
>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar una
>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>> orientado a objetos que te salga y no preocuparte por problemas de otro
>> paradigma. Quedate tranquilo que vas a tener otros problemas para resolver
>> :-P pero, simplemente, no los mismos.
>>
>> Saludos,
>> Facu
>>
>> 2011/1/11 gerard <[hidden email]>
>>
>>
>>
>>
>>
>>
>>
>> > Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>> > pruebas, para trabajar con una base de datos orientada a objetos. Como
>> > solo quería hacer unas pocas pruebas me he decantado por Magma y
>> > Pharo.
>>
>> > Ahora bien, mi problema es que dudo sobre la manera en que deben
>> > hacerse según que cosas cuando guardas datos como objetos.
>>
>> > 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>> > jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>> > de tener una colección de objetos jornada. Ahora bien, cada objeto
>> > jornada debería tener una referencia a su tempoarada no? bien, al
>> > menos en algunos ORMs lo he visto.
>>
>> > 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>> > que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>> > temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>> > una ON DELETE CASCADE de las BBDD relacionales...
>>
>> > Básicamente da la sensación de que sería relativamente fácil en un
>> > momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>> > de datos grandes a la hora de patearse una colección inmensa la demora
>> > sería muy grande... o que no tienes según que automatismos, cómo los
>> > triggers, para asegurarte que suceda algo al añadir un nuevo registro
>> > etc etc
>>
>> > Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>> > objetos?
>>
>> > Saludos y gracias por la ayuda.
>>
>> > --
>> > To post to this group, send email to [hidden email]
>> > To unsubscribe from this group, send email to
>> > [hidden email]<[hidden email]>
>>
>> >http://www.clubSmalltalk.org
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org



--
Hernán Morales
Information Technology Manager,
Institute of Veterinary Genetics.
National Scientific and Technical Research Council (CONICET).
La Plata (1900), Buenos Aires, Argentina.
Telephone: +54 (0221) 421-1799.
Internal: 422
Fax: 425-7980 or 421-1799.

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

hernanmd
In reply to this post by Mariano Martinez Peck
El día 12 de enero de 2011 18:12, Mariano Martinez Peck
<[hidden email]> escribió:

>
>
> 2011/1/12 Juan <[hidden email]>
>>
>> Mariano
>>
>>>
>>> El único problema sería si tu código de negocio haría chanchadas como
>>> Jornada allInstances   pues ahí si todavía estan visibles los objectos
>>> (hasta que pase el GC).
>>> Pero por lo general las applicaciones tiene roots o objectos donde las
>>> cosas están almacenadas. No soles haces un allInstances.
>>
>> Tengo entendido q allInstances llama primero al gc. por lo menos en
>> Dolphin

Eso es porque el #allInstances sino te puede dar instancias que van a
ser reclamadas por el GC, en Squeak/Pharo en cambio sí te puede dar
moribundas, asi que siempre conviene mandar un #garbageCollect antes
para asegurarte que tenés las activas. Viste como es esto, en Dolphin
cuidan al cliente... o trataban por lo menos :)
Saludos,

Hernán

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

hernanmd
In reply to this post by Gastón Dall' Oglio
Hola Gastón,

Sólo para comentar algo, porque de esto se ha escrito mucho ya. En
Squeak y Pharo (VW tambien), tenés dos tipos de become, el #become: es
bidireccional (llamado two-way) y el #becomeForward: (el one-way) es
unidireccional, en VW se llama #oneWayBecome:.

#become: nil *nunca* puede ser enviado porque intercambia los objetos
receptor y nil (si mal no recuerdo en realidad por adentro sólo
intercambia los encabezados de los objetos, pero algunas veces se
necesitan intercambiar contenidos... de todos modos tiene uno o dos
usos válidos en el ambiente), el receptor va a apuntar a nil y nil va
a apuntar al receptor, y como mucho apunta a la nada y la nada ahora
es algo y algo es la nada, la nada nueva (el algo) no se puede
recolectar más y todo esto más otra serie de eventos lamentables
destruyen tu ambiente.

#becomeForward: nil solo convierte al receptor en nil, pero no es
recomendable utilizarlo (en esta lista capaz te encontrás verdaderos
detractores de los become ;). Es usado para mantenimiento muchas
veces, pero en contadas ocasiones se necesita realmente, por ej. podés
eliminar instancias obsoletas sin usar ningún #becomeForward:.

En Magma no podés hacer un #becomeForward:, por lo menos hasta hace un
tiempo era así y tal vez hace poco existe el soporte (por lo que vi lo
dudo). Pero estimo que hay muchas formas de solucionarlo, la de usar
consultas predefinidas es una, particionar las colecciones es otra,
creo que Ale Reimondo alguna vez comentó en Smalltalking sobre como
solucionar este tipo de problemáticas... si alguien tiene un enlace
mejor.
Saludos,

Hernán

El día 13 de enero de 2011 01:02, Gastón Dall' Oglio
<[hidden email]> escribió:

> Hola gente.
>
> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
> Supongamos que tengo unaFactura que esta referenciada desde una colección
> perteneciente a un cliente (sus facturas) y también desde una colección de
> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
> hacer algo como:
> unaFactura become: nil
> 1) Esto me asegura que ya nadie la referencia, y será liberada.
> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
> ignorar con un #select: o permanente con un #removeAll:
> 3) El tiempo normal que demora un #become: aumenta considerablemente por
> tratarse de objetos persistidos por Magma.
> Saludos!
> El 12 de enero de 2011 18:40, Hernán Morales Durand
> <[hidden email]> escribió:
>>
>> Hola Gerard,
>>
>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>> > Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>> > que uno haga algunas cosas no del todo recomendables... Aunque sean
>> > objetos no deja de ser una BD, y seguro que pudes hacer algunas
>> > animaladas espectaculares sólo por no tener claro un concepto.
>> >
>>
>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>> the relational wall", te va a servir para lo conceptual.
>>
>> > Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>> > clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>> > una por separado, de que en ese diccionario exista una entrada con el
>> > mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>> > idea de que automáticamente ya existiera una colección vinculada a
>> > cada clase Entity... pero ahora veo que quizás eso es una tontería y
>> > que sería perfectamente válida una instancia root que tuviera un
>> > montón de colecciones, una por cada entidad. Por otro lado veo algunos
>> > ejemplos o screencast de Magma que usan el otro sistema: una entrada
>> > en un diccionario por cada entidad.
>> >
>>
>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>> existir varias variables de instancia nombradas que podés hacer
>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>> instancia a ese objeto raíz.
>>
>> > En fin, me gustaría que todas las clases-entidades tuvieran un
>> > comportamiento homogeneo. En un ORM, al generarse el código, sé que
>> > una relación 1:N me va a generar una clase con una colección y una
>> > serie de métodos estandard, para añadir un elemento a la colección, o
>> > eliminarla etc Es decir un comportamiento general, dependiendo de las
>> > relaciones.
>> >
>> > ¿Y grandes volúmenes de datos?
>>
>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>> índices, analizar las consultas que vas a tener, las profundidades de
>> tus objetos y en base a eso escribir ReadStrategies razonables para
>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>> 8). Más bits en los indices, más reducidos los resultados de un
>> #where:, y menos escaneo lineal del #select: posterior, pero más
>> procesamiento por cada objeto.
>>
>> > Si tienes una lista inmensa de
>> > facturación y debes de empezar a patearte los items para obtener las
>> > facturas de un determinado cliente como lo haces? Por un lado podrias
>> > hacer que cada cliente tuviera su propia colección de facturas, con lo
>> > que podrías ir directamente a la colección de facturas del cliente,
>> > perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>> > més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>> > colecciones de facturas de los clientes, sería más trabajoso; debería
>> > ir a una lista "general" de facturas y empezar a seleccionar las que
>> > estan en el rango de fechas correcto; es decir, debo tener una
>> > colección de facturas y otras colecciones parciales de facturas en
>> > cada cliente.
>>
>> Lo de las colecciones maestras grandes es una costumbre del mundo
>> relacional, los programadores relacionales se acostumbran a usarlas
>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>> performance viene cambiando la indexación, pero es una opción para
>> reducir complejidad.
>>
>> Una opción interesante es que podés usar #where: y persistir los
>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>> te daría consultas predefinidas. Lo bueno es que si persistís un
>> Reader y agregás más objetos a la colección original luego, es decir,
>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>> para resultados paginados) tenés que revisar la profundidad de los
>> objetos que van a ser consultados y hacerte una ReadStrategy
>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>
>> > Podría ir más lejos en el ejemplo y plantear varias
>> > entidades a las que les interesaría tener su propia relación con las
>> > facturas... Bien: ahora el usuario quiere eliminar una factura, y
>> > cuando lo haga debo de ser muy consciente de todas las colecciones
>> > donde puede estar ubicada esa factura para poder eliminarla "bien".
>> > Debo ir a la lista de facturas del cliente, a la lista general de
>> > facturas que he mencionado etc etc   Veo muy complicado no dejarse
>> > ningún cabo suelto. No me refería tanto a que pasara el GC, que
>> > realmente da igual, sino a la posibilidad de dejarse instancias que ya
>> > no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>> >
>>
>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>> performance, usá un Message spy. Si no tenés problemas, escribí como
>> si nada pasara :)
>>
>> Saludos
>>
>>
>> > No sé si me he expresado bien.
>> >
>> > Saludos.
>> >
>> >
>> >
>> > On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>> >> Hola,
>> >> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>> >> algunos enfoques de persistencia (incluído Magma) en el libro de
>> >> Seaside:http://book.seaside.st/book/advanced/persistency.
>> >>
>> >> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>> >> guardar la imagen con una global que apunte a tu root (un singleton,
>> >> por
>> >> ejemplo). Después cambiar a que se persista con Magma o Goods es casi
>> >> un
>> >> tramite para GemStone tenés que laburar un cacho más.
>> >>
>> >> Respecto de las relaciones, los delete cascade, triggers y cualquier
>> >> yerba
>> >> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>> >> una
>> >> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>> >> orientado a objetos que te salga y no preocuparte por problemas de otro
>> >> paradigma. Quedate tranquilo que vas a tener otros problemas para
>> >> resolver
>> >> :-P pero, simplemente, no los mismos.
>> >>
>> >> Saludos,
>> >> Facu
>> >>
>> >> 2011/1/11 gerard <[hidden email]>
>> >>
>> >>
>> >>
>> >>
>> >>
>> >>
>> >>
>> >> > Buenas. estoy realizando una pequeña aplicación, sólo con propósito
>> >> > de
>> >> > pruebas, para trabajar con una base de datos orientada a objetos.
>> >> > Como
>> >> > solo quería hacer unas pocas pruebas me he decantado por Magma y
>> >> > Pharo.
>> >>
>> >> > Ahora bien, mi problema es que dudo sobre la manera en que deben
>> >> > hacerse según que cosas cuando guardas datos como objetos.
>> >>
>> >> > 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>> >> > jornadas, correcto? Es lógico pensar que cada objeto temporada
>> >> > debería
>> >> > de tener una colección de objetos jornada. Ahora bien, cada objeto
>> >> > jornada debería tener una referencia a su tempoarada no? bien, al
>> >> > menos en algunos ORMs lo he visto.
>> >>
>> >> > 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en
>> >> > cuenta
>> >> > que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>> >> > temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>> >> > una ON DELETE CASCADE de las BBDD relacionales...
>> >>
>> >> > Básicamente da la sensación de que sería relativamente fácil en un
>> >> > momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>> >> > de datos grandes a la hora de patearse una colección inmensa la
>> >> > demora
>> >> > sería muy grande... o que no tienes según que automatismos, cómo los
>> >> > triggers, para asegurarte que suceda algo al añadir un nuevo registro
>> >> > etc etc
>> >>
>> >> > Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>> >> > objetos?
>> >>
>> >> > Saludos y gracias por la ayuda.
>> >>
>> >> > --
>> >> > To post to this group, send email to [hidden email]
>> >> > To unsubscribe from this group, send email to
>> >> >
>> >> > [hidden email]<clubSmalltalk%[hidden email]>
>> >>
>> >> >http://www.clubSmalltalk.org
>> >
>> > --
>> > To post to this group, send email to [hidden email]
>> > To unsubscribe from this group, send email to
>> > [hidden email]
>> >
>> > http://www.clubSmalltalk.org
>>
>>
>>
>> --
>> Hernán Morales
>> Information Technology Manager,
>> Institute of Veterinary Genetics.
>> National Scientific and Technical Research Council (CONICET).
>> La Plata (1900), Buenos Aires, Argentina.
>> Telephone: +54 (0221) 421-1799.
>> Internal: 422
>> Fax: 425-7980 or 421-1799.
>>
>> --
>> To post to this group, send email to [hidden email]
>> To unsubscribe from this group, send email to
>> [hidden email]
>>
>> http://www.clubSmalltalk.org
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to
> [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Andres Fortier-2
In reply to this post by Gastón Dall' Oglio
Yo personalmente evitaría eso porque:

1. Estás asumiendo cosas sobre las colecciones que contienen a la
factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones
y esas colecciones por algún motivo no pueden contener nils las rompés.
2. Tenés que redefinir el protocolo de colecciones para manejar tus
casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que
hacer (select:[..| noNil]) size).
3. Estás asumiendo que nadie mas referencia a la factura (ej. un
inspector, un reporte, un histórico de facturas, etc). Si así fuera
rompés todo.
4. Como regla genérica el #become no se debe usar para resolver
problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es
definir alguien que sepa sincronizar bien las colecciones de facturas.
Por ejemplo, podés definir que el indexador global de facturas no puede
agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:

(private) IndexadorDeFacturas>>agregarFactura: unaFacura
                                                self factuas add: unaFactura.

(public) Cliente>>agregarFactura: unaFacura
                                self factuas add: unaFactura.
                                IndexadorDeFacturas instance agregarFactura: unaFacura.

Si uno es lo suficientemente disciplinado como para no usar el protocolo
privado del indexador de facturas ya no hay problemas.

IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que
te trae el become.

HTH,
Andrés

Gastón Dall' Oglio escribió:

> Hola gente.
>
> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>
> Supongamos que tengo unaFactura que esta referenciada desde una colección
> perteneciente a un cliente (sus facturas) y también desde una colección de
> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
> hacer algo como:
>
> unaFactura become: nil
>
> 1) Esto me asegura que ya nadie la referencia, y será liberada.
> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
> ignorar con un #select: o permanente con un #removeAll:
> 3) El tiempo normal que demora un #become: aumenta considerablemente por
> tratarse de objetos persistidos por Magma.
>
> Saludos!
>
> El 12 de enero de 2011 18:40, Hernán Morales Durand <
> [hidden email]> escribió:
>
>> Hola Gerard,
>>
>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>
>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>> the relational wall", te va a servir para lo conceptual.
>>
>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>> una por separado, de que en ese diccionario exista una entrada con el
>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>> idea de que automáticamente ya existiera una colección vinculada a
>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>> que sería perfectamente válida una instancia root que tuviera un
>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>> en un diccionario por cada entidad.
>>>
>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>> existir varias variables de instancia nombradas que podés hacer
>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>> instancia a ese objeto raíz.
>>
>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>> una relación 1:N me va a generar una clase con una colección y una
>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>> relaciones.
>>>
>>> ¿Y grandes volúmenes de datos?
>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>> índices, analizar las consultas que vas a tener, las profundidades de
>> tus objetos y en base a eso escribir ReadStrategies razonables para
>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>> 8). Más bits en los indices, más reducidos los resultados de un
>> #where:, y menos escaneo lineal del #select: posterior, pero más
>> procesamiento por cada objeto.
>>
>>> Si tienes una lista inmensa de
>>> facturación y debes de empezar a patearte los items para obtener las
>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>> que podrías ir directamente a la colección de facturas del cliente,
>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>> estan en el rango de fechas correcto; es decir, debo tener una
>>> colección de facturas y otras colecciones parciales de facturas en
>>> cada cliente.
>> Lo de las colecciones maestras grandes es una costumbre del mundo
>> relacional, los programadores relacionales se acostumbran a usarlas
>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>> performance viene cambiando la indexación, pero es una opción para
>> reducir complejidad.
>>
>> Una opción interesante es que podés usar #where: y persistir los
>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>> te daría consultas predefinidas. Lo bueno es que si persistís un
>> Reader y agregás más objetos a la colección original luego, es decir,
>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>> para resultados paginados) tenés que revisar la profundidad de los
>> objetos que van a ser consultados y hacerte una ReadStrategy
>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>
>>> Podría ir más lejos en el ejemplo y plantear varias
>>> entidades a las que les interesaría tener su propia relación con las
>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>
>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>> performance, usá un Message spy. Si no tenés problemas, escribí como
>> si nada pasara :)
>>
>> Saludos
>>
>>
>>> No sé si me he expresado bien.
>>>
>>> Saludos.
>>>
>>>
>>>
>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>> Hola,
>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>
>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>> yerba
>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>> una
>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>> resolver
>>>> :-P pero, simplemente, no los mismos.
>>>>
>>>> Saludos,
>>>> Facu
>>>>
>>>> 2011/1/11 gerard <[hidden email]>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>> Pharo.
>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>> menos en algunos ORMs lo he visto.
>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>> etc etc
>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>> objetos?
>>>>> Saludos y gracias por la ayuda.
>>>>> --
>>>>> To post to this group, send email to [hidden email]
>>>>> To unsubscribe from this group, send email to
>>>>> [hidden email]<clubSmalltalk%[hidden email]>
>> <clubSmalltalk%[hidden email]<clubSmalltalk%[hidden email]>
>>>>> http://www.clubSmalltalk.org
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>> [hidden email]<clubSmalltalk%[hidden email]>
>>> http://www.clubSmalltalk.org
>>
>>
>> --
>> Hernán Morales
>> Information Technology Manager,
>> Institute of Veterinary Genetics.
>> National Scientific and Technical Research Council (CONICET).
>> La Plata (1900), Buenos Aires, Argentina.
>> Telephone: +54 (0221) 421-1799.
>> Internal: 422
>> Fax: 425-7980 or 421-1799.
>>
>> --
>> To post to this group, send email to [hidden email]
>> To unsubscribe from this group, send email to
>> [hidden email]<clubSmalltalk%[hidden email]>
>>
>> http://www.clubSmalltalk.org
>>
>

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

EstebanLM
hola,
bueno, me meto en el thread :)
IMHO, el problema es que seguís pensando tu estructura de datos en relacional, no en objetos (por eso lo pensás como una estructura de datos y no como un grafo de objetos, je).
Yo la primer pregunta que me haría es "para qué quiero la colección de todas las facturas? las necesito, o es solo que 'me parece' que tienen que estar en una colección aparte (como si la colección fuera una tabla)"
realmente me parece que es una instancia muy nueva de tu aplicación (por lo que veo) para saber si realmente necesitas tener una colección de facturas aparte. En estos momentos no hay nada que te impida hacer algo como:

allInvoices
        ^self customers
                inject: Set new
                into: [ :all :each | all, each invoices ]

eso puede demostrarse no eficiente con el tiempo, pero también puede demostrarse que no necesitás #allInvoices y entonces te ahorrás todo el problema de mantener invoices en dos lugares.
Si pese a todo decidís que sí necesitas mantenerlo aparte, lo que te recomiendo es lo mismo que te recomendó Andrés, y le agrego que, para borrar facturas, hagas algo como:

Customer>>removeInvoice: anInvoice
        self invoices remove: anInvoice.
        IndexadorDeFacturas instance remove: anInvoice.

usar el become (forward o no), suele no ser una respuesta correcta. Entre otras cosas porque te hace un scan de todos los objetos en memoria, en pharo/squeak, dado que no tienen object table.

nunca dejes de pensar desde el punto de vista del modelo, olvidate de pensar en la estructura!
 
Saludos,
Esteban

El 13/01/2011, a las 7:42a.m., andres escribió:

> Yo personalmente evitaría eso porque:
>
> 1. Estás asumiendo cosas sobre las colecciones que contienen a la factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones y esas colecciones por algún motivo no pueden contener nils las rompés.
> 2. Tenés que redefinir el protocolo de colecciones para manejar tus casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que hacer (select:[..| noNil]) size).
> 3. Estás asumiendo que nadie mas referencia a la factura (ej. un inspector, un reporte, un histórico de facturas, etc). Si así fuera rompés todo.
> 4. Como regla genérica el #become no se debe usar para resolver problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es definir alguien que sepa sincronizar bien las colecciones de facturas. Por ejemplo, podés definir que el indexador global de facturas no puede agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:
>
> (private) IndexadorDeFacturas>>agregarFactura: unaFacura
> self factuas add: unaFactura.
>
> (public) Cliente>>agregarFactura: unaFacura
> self factuas add: unaFactura.
> IndexadorDeFacturas instance agregarFactura: unaFacura.
>
> Si uno es lo suficientemente disciplinado como para no usar el protocolo privado del indexador de facturas ya no hay problemas.
>
> IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que te trae el become.
>
> HTH,
> Andrés
>
> Gastón Dall' Oglio escribió:
>> Hola gente.
>> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>> Supongamos que tengo unaFactura que esta referenciada desde una colección
>> perteneciente a un cliente (sus facturas) y también desde una colección de
>> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
>> hacer algo como:
>> unaFactura become: nil
>> 1) Esto me asegura que ya nadie la referencia, y será liberada.
>> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
>> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
>> ignorar con un #select: o permanente con un #removeAll:
>> 3) El tiempo normal que demora un #become: aumenta considerablemente por
>> tratarse de objetos persistidos por Magma.
>> Saludos!
>> El 12 de enero de 2011 18:40, Hernán Morales Durand <
>> [hidden email]> escribió:
>>> Hola Gerard,
>>>
>>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>>
>>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>>> the relational wall", te va a servir para lo conceptual.
>>>
>>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>>> una por separado, de que en ese diccionario exista una entrada con el
>>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>>> idea de que automáticamente ya existiera una colección vinculada a
>>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>>> que sería perfectamente válida una instancia root que tuviera un
>>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>>> en un diccionario por cada entidad.
>>>>
>>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>>> existir varias variables de instancia nombradas que podés hacer
>>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>>> instancia a ese objeto raíz.
>>>
>>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>>> una relación 1:N me va a generar una clase con una colección y una
>>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>>> relaciones.
>>>>
>>>> ¿Y grandes volúmenes de datos?
>>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>>> índices, analizar las consultas que vas a tener, las profundidades de
>>> tus objetos y en base a eso escribir ReadStrategies razonables para
>>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>>> 8). Más bits en los indices, más reducidos los resultados de un
>>> #where:, y menos escaneo lineal del #select: posterior, pero más
>>> procesamiento por cada objeto.
>>>
>>>> Si tienes una lista inmensa de
>>>> facturación y debes de empezar a patearte los items para obtener las
>>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>>> que podrías ir directamente a la colección de facturas del cliente,
>>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>>> estan en el rango de fechas correcto; es decir, debo tener una
>>>> colección de facturas y otras colecciones parciales de facturas en
>>>> cada cliente.
>>> Lo de las colecciones maestras grandes es una costumbre del mundo
>>> relacional, los programadores relacionales se acostumbran a usarlas
>>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>>> performance viene cambiando la indexación, pero es una opción para
>>> reducir complejidad.
>>>
>>> Una opción interesante es que podés usar #where: y persistir los
>>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>>> te daría consultas predefinidas. Lo bueno es que si persistís un
>>> Reader y agregás más objetos a la colección original luego, es decir,
>>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>>> para resultados paginados) tenés que revisar la profundidad de los
>>> objetos que van a ser consultados y hacerte una ReadStrategy
>>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>>
>>>> Podría ir más lejos en el ejemplo y plantear varias
>>>> entidades a las que les interesaría tener su propia relación con las
>>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>>
>>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>>> performance, usá un Message spy. Si no tenés problemas, escribí como
>>> si nada pasara :)
>>>
>>> Saludos
>>>
>>>
>>>> No sé si me he expresado bien.
>>>>
>>>> Saludos.
>>>>
>>>>
>>>>
>>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>>> Hola,
>>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>>
>>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>>> yerba
>>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>>> una
>>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>>> resolver
>>>>> :-P pero, simplemente, no los mismos.
>>>>>
>>>>> Saludos,
>>>>> Facu
>>>>>
>>>>> 2011/1/11 gerard <[hidden email]>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>>> Pharo.
>>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>>> menos en algunos ORMs lo he visto.
>>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>>> etc etc
>>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>>> objetos?
>>>>>> Saludos y gracias por la ayuda.
>>>>>> --
>>>>>> To post to this group, send email to [hidden email]
>>>>>> To unsubscribe from this group, send email to
>>>>>> [hidden email]<clubSmalltalk%[hidden email]>
>>> <clubSmalltalk%[hidden email]<clubSmalltalk%[hidden email]>
>>>>>> http://www.clubSmalltalk.org
>>>> --
>>>> To post to this group, send email to [hidden email]
>>>> To unsubscribe from this group, send email to
>>> [hidden email]<clubSmalltalk%[hidden email]>
>>>> http://www.clubSmalltalk.org
>>>
>>>
>>> --
>>> Hernán Morales
>>> Information Technology Manager,
>>> Institute of Veterinary Genetics.
>>> National Scientific and Technical Research Council (CONICET).
>>> La Plata (1900), Buenos Aires, Argentina.
>>> Telephone: +54 (0221) 421-1799.
>>> Internal: 422
>>> Fax: 425-7980 or 421-1799.
>>>
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<clubSmalltalk%[hidden email]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Gastón Dall' Oglio
Muchas gracias por sus comentarios!

Sí, el become ya me parecía una mala idea por lo que he leído.

Saludos.

El 13 de enero de 2011 08:48, Esteban Lorenzano <[hidden email]> escribió:
hola,
bueno, me meto en el thread :)
IMHO, el problema es que seguís pensando tu estructura de datos en relacional, no en objetos (por eso lo pensás como una estructura de datos y no como un grafo de objetos, je).
Yo la primer pregunta que me haría es "para qué quiero la colección de todas las facturas? las necesito, o es solo que 'me parece' que tienen que estar en una colección aparte (como si la colección fuera una tabla)"
realmente me parece que es una instancia muy nueva de tu aplicación (por lo que veo) para saber si realmente necesitas tener una colección de facturas aparte. En estos momentos no hay nada que te impida hacer algo como:

allInvoices
       ^self customers
               inject: Set new
               into: [ :all :each | all, each invoices ]

eso puede demostrarse no eficiente con el tiempo, pero también puede demostrarse que no necesitás #allInvoices y entonces te ahorrás todo el problema de mantener invoices en dos lugares.
Si pese a todo decidís que sí necesitas mantenerlo aparte, lo que te recomiendo es lo mismo que te recomendó Andrés, y le agrego que, para borrar facturas, hagas algo como:

Customer>>removeInvoice: anInvoice
       self invoices remove: anInvoice.
       IndexadorDeFacturas instance remove: anInvoice.

usar el become (forward o no), suele no ser una respuesta correcta. Entre otras cosas porque te hace un scan de todos los objetos en memoria, en pharo/squeak, dado que no tienen object table.

nunca dejes de pensar desde el punto de vista del modelo, olvidate de pensar en la estructura!

Saludos,
Esteban

El 13/01/2011, a las 7:42a.m., andres escribió:

> Yo personalmente evitaría eso porque:
>
> 1. Estás asumiendo cosas sobre las colecciones que contienen a la factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones y esas colecciones por algún motivo no pueden contener nils las rompés.
> 2. Tenés que redefinir el protocolo de colecciones para manejar tus casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que hacer (select:[..| noNil]) size).
> 3. Estás asumiendo que nadie mas referencia a la factura (ej. un inspector, un reporte, un histórico de facturas, etc). Si así fuera rompés todo.
> 4. Como regla genérica el #become no se debe usar para resolver problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es definir alguien que sepa sincronizar bien las colecciones de facturas. Por ejemplo, podés definir que el indexador global de facturas no puede agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:
>
> (private) IndexadorDeFacturas>>agregarFactura: unaFacura
>                                               self factuas add: unaFactura.
>
> (public) Cliente>>agregarFactura: unaFacura
>                               self factuas add: unaFactura.
>                               IndexadorDeFacturas instance agregarFactura: unaFacura.
>
> Si uno es lo suficientemente disciplinado como para no usar el protocolo privado del indexador de facturas ya no hay problemas.
>
> IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que te trae el become.
>
> HTH,
> Andrés
>
> Gastón Dall' Oglio escribió:
>> Hola gente.
>> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>> Supongamos que tengo unaFactura que esta referenciada desde una colección
>> perteneciente a un cliente (sus facturas) y también desde una colección de
>> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
>> hacer algo como:
>> unaFactura become: nil
>> 1) Esto me asegura que ya nadie la referencia, y será liberada.
>> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
>> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
>> ignorar con un #select: o permanente con un #removeAll:
>> 3) El tiempo normal que demora un #become: aumenta considerablemente por
>> tratarse de objetos persistidos por Magma.
>> Saludos!
>> El 12 de enero de 2011 18:40, Hernán Morales Durand <
>> [hidden email]> escribió:
>>> Hola Gerard,
>>>
>>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>>
>>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>>> the relational wall", te va a servir para lo conceptual.
>>>
>>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>>> una por separado, de que en ese diccionario exista una entrada con el
>>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>>> idea de que automáticamente ya existiera una colección vinculada a
>>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>>> que sería perfectamente válida una instancia root que tuviera un
>>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>>> en un diccionario por cada entidad.
>>>>
>>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>>> existir varias variables de instancia nombradas que podés hacer
>>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>>> instancia a ese objeto raíz.
>>>
>>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>>> una relación 1:N me va a generar una clase con una colección y una
>>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>>> relaciones.
>>>>
>>>> ¿Y grandes volúmenes de datos?
>>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>>> índices, analizar las consultas que vas a tener, las profundidades de
>>> tus objetos y en base a eso escribir ReadStrategies razonables para
>>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>>> 8). Más bits en los indices, más reducidos los resultados de un
>>> #where:, y menos escaneo lineal del #select: posterior, pero más
>>> procesamiento por cada objeto.
>>>
>>>> Si tienes una lista inmensa de
>>>> facturación y debes de empezar a patearte los items para obtener las
>>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>>> que podrías ir directamente a la colección de facturas del cliente,
>>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>>> estan en el rango de fechas correcto; es decir, debo tener una
>>>> colección de facturas y otras colecciones parciales de facturas en
>>>> cada cliente.
>>> Lo de las colecciones maestras grandes es una costumbre del mundo
>>> relacional, los programadores relacionales se acostumbran a usarlas
>>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>>> performance viene cambiando la indexación, pero es una opción para
>>> reducir complejidad.
>>>
>>> Una opción interesante es que podés usar #where: y persistir los
>>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>>> te daría consultas predefinidas. Lo bueno es que si persistís un
>>> Reader y agregás más objetos a la colección original luego, es decir,
>>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>>> para resultados paginados) tenés que revisar la profundidad de los
>>> objetos que van a ser consultados y hacerte una ReadStrategy
>>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>>
>>>> Podría ir más lejos en el ejemplo y plantear varias
>>>> entidades a las que les interesaría tener su propia relación con las
>>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>>
>>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>>> performance, usá un Message spy. Si no tenés problemas, escribí como
>>> si nada pasara :)
>>>
>>> Saludos
>>>
>>>
>>>> No sé si me he expresado bien.
>>>>
>>>> Saludos.
>>>>
>>>>
>>>>
>>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>>> Hola,
>>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>>
>>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>>> yerba
>>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>>> una
>>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>>> resolver
>>>>> :-P pero, simplemente, no los mismos.
>>>>>
>>>>> Saludos,
>>>>> Facu
>>>>>
>>>>> 2011/1/11 gerard <[hidden email]>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>>> Pharo.
>>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>>> menos en algunos ORMs lo he visto.
>>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>>> etc etc
>>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>>> objetos?
>>>>>> Saludos y gracias por la ayuda.
>>>>>> --
>>>>>> To post to this group, send email to [hidden email]
>>>>>> To unsubscribe from this group, send email to
>>>>>> [hidden email]<[hidden email]>
>>> <[hidden email]<[hidden email]>
>>>>>> http://www.clubSmalltalk.org
>>>> --
>>>> To post to this group, send email to [hidden email]
>>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>> http://www.clubSmalltalk.org
>>>
>>>
>>> --
>>> Hernán Morales
>>> Information Technology Manager,
>>> Institute of Veterinary Genetics.
>>> National Scientific and Technical Research Council (CONICET).
>>> La Plata (1900), Buenos Aires, Argentina.
>>> Telephone: +54 (0221) 421-1799.
>>> Internal: 422
>>> Fax: 425-7980 or 421-1799.
>>>
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Gaboto
Buenas, ya que estamos yo también me meto jeje.
Solo un comentario. Para hacer un buen modelo en la base de objetos lo que quizá deberías hacer es pensar en que tenés un programa en memoria y que nunca se apaga. Es decir, imaginate que vos tenes que hacer un programa que no tiene que persistir nada porque la compu siempre está prendida, Entonces, en ese caso como harías? yo tendría las colecciones que correspondan y agregaría algún diccionario por eficiencia, etc.
La consistencia del modelo la tendría que manejar el modelo mismo, asegurandose de poner y sacar las cosas de las colecciones cuando corresponda. No hay ningún trigger mágico ni nada de eso, que viene de otro paradigma.
Yo creo que la idea de una base de objetos es justamente esa, hacer lo más transparente posible la persistencia, aunque en realidad haya algunas sutiles diferencias en la práctica...
Luego con el tiempo, como ya mencionaron acá, te vas a ir dando cuenta de si hay que hacer alguna "chanchada" o algo para ir optimizando los tiempos.

2011/1/13 Gastón Dall' Oglio <[hidden email]>
Muchas gracias por sus comentarios!

Sí, el become ya me parecía una mala idea por lo que he leído.

Saludos.

El 13 de enero de 2011 08:48, Esteban Lorenzano <[hidden email]> escribió:

hola,
bueno, me meto en el thread :)
IMHO, el problema es que seguís pensando tu estructura de datos en relacional, no en objetos (por eso lo pensás como una estructura de datos y no como un grafo de objetos, je).
Yo la primer pregunta que me haría es "para qué quiero la colección de todas las facturas? las necesito, o es solo que 'me parece' que tienen que estar en una colección aparte (como si la colección fuera una tabla)"
realmente me parece que es una instancia muy nueva de tu aplicación (por lo que veo) para saber si realmente necesitas tener una colección de facturas aparte. En estos momentos no hay nada que te impida hacer algo como:

allInvoices
       ^self customers
               inject: Set new
               into: [ :all :each | all, each invoices ]

eso puede demostrarse no eficiente con el tiempo, pero también puede demostrarse que no necesitás #allInvoices y entonces te ahorrás todo el problema de mantener invoices en dos lugares.
Si pese a todo decidís que sí necesitas mantenerlo aparte, lo que te recomiendo es lo mismo que te recomendó Andrés, y le agrego que, para borrar facturas, hagas algo como:

Customer>>removeInvoice: anInvoice
       self invoices remove: anInvoice.
       IndexadorDeFacturas instance remove: anInvoice.

usar el become (forward o no), suele no ser una respuesta correcta. Entre otras cosas porque te hace un scan de todos los objetos en memoria, en pharo/squeak, dado que no tienen object table.

nunca dejes de pensar desde el punto de vista del modelo, olvidate de pensar en la estructura!

Saludos,
Esteban

El 13/01/2011, a las 7:42a.m., andres escribió:

> Yo personalmente evitaría eso porque:
>
> 1. Estás asumiendo cosas sobre las colecciones que contienen a la factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones y esas colecciones por algún motivo no pueden contener nils las rompés.
> 2. Tenés que redefinir el protocolo de colecciones para manejar tus casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que hacer (select:[..| noNil]) size).
> 3. Estás asumiendo que nadie mas referencia a la factura (ej. un inspector, un reporte, un histórico de facturas, etc). Si así fuera rompés todo.
> 4. Como regla genérica el #become no se debe usar para resolver problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es definir alguien que sepa sincronizar bien las colecciones de facturas. Por ejemplo, podés definir que el indexador global de facturas no puede agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:
>
> (private) IndexadorDeFacturas>>agregarFactura: unaFacura
>                                               self factuas add: unaFactura.
>
> (public) Cliente>>agregarFactura: unaFacura
>                               self factuas add: unaFactura.
>                               IndexadorDeFacturas instance agregarFactura: unaFacura.
>
> Si uno es lo suficientemente disciplinado como para no usar el protocolo privado del indexador de facturas ya no hay problemas.
>
> IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que te trae el become.
>
> HTH,
> Andrés
>
> Gastón Dall' Oglio escribió:
>> Hola gente.
>> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>> Supongamos que tengo unaFactura que esta referenciada desde una colección
>> perteneciente a un cliente (sus facturas) y también desde una colección de
>> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
>> hacer algo como:
>> unaFactura become: nil
>> 1) Esto me asegura que ya nadie la referencia, y será liberada.
>> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
>> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
>> ignorar con un #select: o permanente con un #removeAll:
>> 3) El tiempo normal que demora un #become: aumenta considerablemente por
>> tratarse de objetos persistidos por Magma.
>> Saludos!
>> El 12 de enero de 2011 18:40, Hernán Morales Durand <
>> [hidden email]> escribió:
>>> Hola Gerard,
>>>
>>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>>
>>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>>> the relational wall", te va a servir para lo conceptual.
>>>
>>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>>> una por separado, de que en ese diccionario exista una entrada con el
>>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>>> idea de que automáticamente ya existiera una colección vinculada a
>>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>>> que sería perfectamente válida una instancia root que tuviera un
>>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>>> en un diccionario por cada entidad.
>>>>
>>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>>> existir varias variables de instancia nombradas que podés hacer
>>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>>> instancia a ese objeto raíz.
>>>
>>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>>> una relación 1:N me va a generar una clase con una colección y una
>>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>>> relaciones.
>>>>
>>>> ¿Y grandes volúmenes de datos?
>>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>>> índices, analizar las consultas que vas a tener, las profundidades de
>>> tus objetos y en base a eso escribir ReadStrategies razonables para
>>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>>> 8). Más bits en los indices, más reducidos los resultados de un
>>> #where:, y menos escaneo lineal del #select: posterior, pero más
>>> procesamiento por cada objeto.
>>>
>>>> Si tienes una lista inmensa de
>>>> facturación y debes de empezar a patearte los items para obtener las
>>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>>> que podrías ir directamente a la colección de facturas del cliente,
>>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>>> estan en el rango de fechas correcto; es decir, debo tener una
>>>> colección de facturas y otras colecciones parciales de facturas en
>>>> cada cliente.
>>> Lo de las colecciones maestras grandes es una costumbre del mundo
>>> relacional, los programadores relacionales se acostumbran a usarlas
>>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>>> performance viene cambiando la indexación, pero es una opción para
>>> reducir complejidad.
>>>
>>> Una opción interesante es que podés usar #where: y persistir los
>>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>>> te daría consultas predefinidas. Lo bueno es que si persistís un
>>> Reader y agregás más objetos a la colección original luego, es decir,
>>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>>> para resultados paginados) tenés que revisar la profundidad de los
>>> objetos que van a ser consultados y hacerte una ReadStrategy
>>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>>
>>>> Podría ir más lejos en el ejemplo y plantear varias
>>>> entidades a las que les interesaría tener su propia relación con las
>>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>>
>>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>>> performance, usá un Message spy. Si no tenés problemas, escribí como
>>> si nada pasara :)
>>>
>>> Saludos
>>>
>>>
>>>> No sé si me he expresado bien.
>>>>
>>>> Saludos.
>>>>
>>>>
>>>>
>>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>>> Hola,
>>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>>
>>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>>> yerba
>>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>>> una
>>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>>> resolver
>>>>> :-P pero, simplemente, no los mismos.
>>>>>
>>>>> Saludos,
>>>>> Facu
>>>>>
>>>>> 2011/1/11 gerard <[hidden email]>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>>> Pharo.
>>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>>> menos en algunos ORMs lo he visto.
>>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>>> etc etc
>>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>>> objetos?
>>>>>> Saludos y gracias por la ayuda.
>>>>>> --
>>>>>> To post to this group, send email to [hidden email]
>>>>>> To unsubscribe from this group, send email to
>>>>>> [hidden email]<[hidden email]>
>>> <[hidden email]<[hidden email]>
>>>>>> http://www.clubSmalltalk.org
>>>> --
>>>> To post to this group, send email to [hidden email]
>>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>> http://www.clubSmalltalk.org
>>>
>>>
>>> --
>>> Hernán Morales
>>> Information Technology Manager,
>>> Institute of Veterinary Genetics.
>>> National Scientific and Technical Research Council (CONICET).
>>> La Plata (1900), Buenos Aires, Argentina.
>>> Telephone: +54 (0221) 421-1799.
>>> Internal: 422
>>> Fax: 425-7980 or 421-1799.
>>>
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Gastón Dall' Oglio
> Buenas, ya que estamos yo también me meto jeje.

Buenas. Yo creo que la lista esta para que todo el que tenga algo que aportar lo haga :)

Ya que estamos con el tema base de objetos y de datos, les consulto si alguno sabe que orientación tienen las bases de datos que se encuadran bajo el enfoque nosql. ¿Están tratando de hacer algo orientado a objetos o algo totalmente novedoso?




El 13 de enero de 2011 10:58, Gaboto <[hidden email]> escribió:
Buenas, ya que estamos yo también me meto jeje.
Solo un comentario. Para hacer un buen modelo en la base de objetos lo que quizá deberías hacer es pensar en que tenés un programa en memoria y que nunca se apaga. Es decir, imaginate que vos tenes que hacer un programa que no tiene que persistir nada porque la compu siempre está prendida, Entonces, en ese caso como harías? yo tendría las colecciones que correspondan y agregaría algún diccionario por eficiencia, etc.
La consistencia del modelo la tendría que manejar el modelo mismo, asegurandose de poner y sacar las cosas de las colecciones cuando corresponda. No hay ningún trigger mágico ni nada de eso, que viene de otro paradigma.
Yo creo que la idea de una base de objetos es justamente esa, hacer lo más transparente posible la persistencia, aunque en realidad haya algunas sutiles diferencias en la práctica...
Luego con el tiempo, como ya mencionaron acá, te vas a ir dando cuenta de si hay que hacer alguna "chanchada" o algo para ir optimizando los tiempos.

2011/1/13 Gastón Dall' Oglio <[hidden email]>
Muchas gracias por sus comentarios!

Sí, el become ya me parecía una mala idea por lo que he leído.

Saludos.

El 13 de enero de 2011 08:48, Esteban Lorenzano <[hidden email]> escribió:

hola,
bueno, me meto en el thread :)
IMHO, el problema es que seguís pensando tu estructura de datos en relacional, no en objetos (por eso lo pensás como una estructura de datos y no como un grafo de objetos, je).
Yo la primer pregunta que me haría es "para qué quiero la colección de todas las facturas? las necesito, o es solo que 'me parece' que tienen que estar en una colección aparte (como si la colección fuera una tabla)"
realmente me parece que es una instancia muy nueva de tu aplicación (por lo que veo) para saber si realmente necesitas tener una colección de facturas aparte. En estos momentos no hay nada que te impida hacer algo como:

allInvoices
       ^self customers
               inject: Set new
               into: [ :all :each | all, each invoices ]

eso puede demostrarse no eficiente con el tiempo, pero también puede demostrarse que no necesitás #allInvoices y entonces te ahorrás todo el problema de mantener invoices en dos lugares.
Si pese a todo decidís que sí necesitas mantenerlo aparte, lo que te recomiendo es lo mismo que te recomendó Andrés, y le agrego que, para borrar facturas, hagas algo como:

Customer>>removeInvoice: anInvoice
       self invoices remove: anInvoice.
       IndexadorDeFacturas instance remove: anInvoice.

usar el become (forward o no), suele no ser una respuesta correcta. Entre otras cosas porque te hace un scan de todos los objetos en memoria, en pharo/squeak, dado que no tienen object table.

nunca dejes de pensar desde el punto de vista del modelo, olvidate de pensar en la estructura!

Saludos,
Esteban

El 13/01/2011, a las 7:42a.m., andres escribió:

> Yo personalmente evitaría eso porque:
>
> 1. Estás asumiendo cosas sobre las colecciones que contienen a la factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones y esas colecciones por algún motivo no pueden contener nils las rompés.
> 2. Tenés que redefinir el protocolo de colecciones para manejar tus casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que hacer (select:[..| noNil]) size).
> 3. Estás asumiendo que nadie mas referencia a la factura (ej. un inspector, un reporte, un histórico de facturas, etc). Si así fuera rompés todo.
> 4. Como regla genérica el #become no se debe usar para resolver problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es definir alguien que sepa sincronizar bien las colecciones de facturas. Por ejemplo, podés definir que el indexador global de facturas no puede agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:
>
> (private) IndexadorDeFacturas>>agregarFactura: unaFacura
>                                               self factuas add: unaFactura.
>
> (public) Cliente>>agregarFactura: unaFacura
>                               self factuas add: unaFactura.
>                               IndexadorDeFacturas instance agregarFactura: unaFacura.
>
> Si uno es lo suficientemente disciplinado como para no usar el protocolo privado del indexador de facturas ya no hay problemas.
>
> IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que te trae el become.
>
> HTH,
> Andrés
>
> Gastón Dall' Oglio escribió:
>> Hola gente.
>> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>> Supongamos que tengo unaFactura que esta referenciada desde una colección
>> perteneciente a un cliente (sus facturas) y también desde una colección de
>> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
>> hacer algo como:
>> unaFactura become: nil
>> 1) Esto me asegura que ya nadie la referencia, y será liberada.
>> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
>> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
>> ignorar con un #select: o permanente con un #removeAll:
>> 3) El tiempo normal que demora un #become: aumenta considerablemente por
>> tratarse de objetos persistidos por Magma.
>> Saludos!
>> El 12 de enero de 2011 18:40, Hernán Morales Durand <
>> [hidden email]> escribió:
>>> Hola Gerard,
>>>
>>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>>
>>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>>> the relational wall", te va a servir para lo conceptual.
>>>
>>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>>> una por separado, de que en ese diccionario exista una entrada con el
>>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>>> idea de que automáticamente ya existiera una colección vinculada a
>>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>>> que sería perfectamente válida una instancia root que tuviera un
>>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>>> en un diccionario por cada entidad.
>>>>
>>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>>> existir varias variables de instancia nombradas que podés hacer
>>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>>> instancia a ese objeto raíz.
>>>
>>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>>> una relación 1:N me va a generar una clase con una colección y una
>>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>>> relaciones.
>>>>
>>>> ¿Y grandes volúmenes de datos?
>>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>>> índices, analizar las consultas que vas a tener, las profundidades de
>>> tus objetos y en base a eso escribir ReadStrategies razonables para
>>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>>> 8). Más bits en los indices, más reducidos los resultados de un
>>> #where:, y menos escaneo lineal del #select: posterior, pero más
>>> procesamiento por cada objeto.
>>>
>>>> Si tienes una lista inmensa de
>>>> facturación y debes de empezar a patearte los items para obtener las
>>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>>> que podrías ir directamente a la colección de facturas del cliente,
>>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>>> estan en el rango de fechas correcto; es decir, debo tener una
>>>> colección de facturas y otras colecciones parciales de facturas en
>>>> cada cliente.
>>> Lo de las colecciones maestras grandes es una costumbre del mundo
>>> relacional, los programadores relacionales se acostumbran a usarlas
>>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>>> performance viene cambiando la indexación, pero es una opción para
>>> reducir complejidad.
>>>
>>> Una opción interesante es que podés usar #where: y persistir los
>>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>>> te daría consultas predefinidas. Lo bueno es que si persistís un
>>> Reader y agregás más objetos a la colección original luego, es decir,
>>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>>> para resultados paginados) tenés que revisar la profundidad de los
>>> objetos que van a ser consultados y hacerte una ReadStrategy
>>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>>
>>>> Podría ir más lejos en el ejemplo y plantear varias
>>>> entidades a las que les interesaría tener su propia relación con las
>>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>>
>>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>>> performance, usá un Message spy. Si no tenés problemas, escribí como
>>> si nada pasara :)
>>>
>>> Saludos
>>>
>>>
>>>> No sé si me he expresado bien.
>>>>
>>>> Saludos.
>>>>
>>>>
>>>>
>>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>>> Hola,
>>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>>
>>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>>> yerba
>>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>>> una
>>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>>> resolver
>>>>> :-P pero, simplemente, no los mismos.
>>>>>
>>>>> Saludos,
>>>>> Facu
>>>>>
>>>>> 2011/1/11 gerard <[hidden email]>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>>> Pharo.
>>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>>> menos en algunos ORMs lo he visto.
>>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>>> etc etc
>>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>>> objetos?
>>>>>> Saludos y gracias por la ayuda.
>>>>>> --
>>>>>> To post to this group, send email to [hidden email]
>>>>>> To unsubscribe from this group, send email to
>>>>>> [hidden email]<[hidden email]>
>>> <[hidden email]<[hidden email]>
>>>>>> http://www.clubSmalltalk.org
>>>> --
>>>> To post to this group, send email to [hidden email]
>>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>> http://www.clubSmalltalk.org
>>>
>>>
>>> --
>>> Hernán Morales
>>> Information Technology Manager,
>>> Institute of Veterinary Genetics.
>>> National Scientific and Technical Research Council (CONICET).
>>> La Plata (1900), Buenos Aires, Argentina.
>>> Telephone: +54 (0221) 421-1799.
>>> Internal: 422
>>> Fax: 425-7980 or 421-1799.
>>>
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Gaboto
Hasta donde yo tengo entendido, nosql es más que nada como una movida de nuevas propuestas para la persistencia que son novedosas ya que no siguen el modelo relacional. No es un paradigma determinado.
Una base de objetos por ejemplo sería parte del movimiento nosql, pero existe hace mucho más tiempo ;).
Pero hay otros modelos, uno por ejemplo consiste en tener una especie de diccionarios con clave valor (creo que era cassandra).

2011/1/13 Gastón Dall' Oglio <[hidden email]>
> Buenas, ya que estamos yo también me meto jeje.

Buenas. Yo creo que la lista esta para que todo el que tenga algo que aportar lo haga :)

Ya que estamos con el tema base de objetos y de datos, les consulto si alguno sabe que orientación tienen las bases de datos que se encuadran bajo el enfoque nosql. ¿Están tratando de hacer algo orientado a objetos o algo totalmente novedoso?




El 13 de enero de 2011 10:58, Gaboto <[hidden email]> escribió:
Buenas, ya que estamos yo también me meto jeje.
Solo un comentario. Para hacer un buen modelo en la base de objetos lo que quizá deberías hacer es pensar en que tenés un programa en memoria y que nunca se apaga. Es decir, imaginate que vos tenes que hacer un programa que no tiene que persistir nada porque la compu siempre está prendida, Entonces, en ese caso como harías? yo tendría las colecciones que correspondan y agregaría algún diccionario por eficiencia, etc.
La consistencia del modelo la tendría que manejar el modelo mismo, asegurandose de poner y sacar las cosas de las colecciones cuando corresponda. No hay ningún trigger mágico ni nada de eso, que viene de otro paradigma.
Yo creo que la idea de una base de objetos es justamente esa, hacer lo más transparente posible la persistencia, aunque en realidad haya algunas sutiles diferencias en la práctica...
Luego con el tiempo, como ya mencionaron acá, te vas a ir dando cuenta de si hay que hacer alguna "chanchada" o algo para ir optimizando los tiempos.

2011/1/13 Gastón Dall' Oglio <[hidden email]>
Muchas gracias por sus comentarios!

Sí, el become ya me parecía una mala idea por lo que he leído.

Saludos.

El 13 de enero de 2011 08:48, Esteban Lorenzano <[hidden email]> escribió:

hola,
bueno, me meto en el thread :)
IMHO, el problema es que seguís pensando tu estructura de datos en relacional, no en objetos (por eso lo pensás como una estructura de datos y no como un grafo de objetos, je).
Yo la primer pregunta que me haría es "para qué quiero la colección de todas las facturas? las necesito, o es solo que 'me parece' que tienen que estar en una colección aparte (como si la colección fuera una tabla)"
realmente me parece que es una instancia muy nueva de tu aplicación (por lo que veo) para saber si realmente necesitas tener una colección de facturas aparte. En estos momentos no hay nada que te impida hacer algo como:

allInvoices
       ^self customers
               inject: Set new
               into: [ :all :each | all, each invoices ]

eso puede demostrarse no eficiente con el tiempo, pero también puede demostrarse que no necesitás #allInvoices y entonces te ahorrás todo el problema de mantener invoices en dos lugares.
Si pese a todo decidís que sí necesitas mantenerlo aparte, lo que te recomiendo es lo mismo que te recomendó Andrés, y le agrego que, para borrar facturas, hagas algo como:

Customer>>removeInvoice: anInvoice
       self invoices remove: anInvoice.
       IndexadorDeFacturas instance remove: anInvoice.

usar el become (forward o no), suele no ser una respuesta correcta. Entre otras cosas porque te hace un scan de todos los objetos en memoria, en pharo/squeak, dado que no tienen object table.

nunca dejes de pensar desde el punto de vista del modelo, olvidate de pensar en la estructura!

Saludos,
Esteban

El 13/01/2011, a las 7:42a.m., andres escribió:

> Yo personalmente evitaría eso porque:
>
> 1. Estás asumiendo cosas sobre las colecciones que contienen a la factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones y esas colecciones por algún motivo no pueden contener nils las rompés.
> 2. Tenés que redefinir el protocolo de colecciones para manejar tus casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que hacer (select:[..| noNil]) size).
> 3. Estás asumiendo que nadie mas referencia a la factura (ej. un inspector, un reporte, un histórico de facturas, etc). Si así fuera rompés todo.
> 4. Como regla genérica el #become no se debe usar para resolver problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es definir alguien que sepa sincronizar bien las colecciones de facturas. Por ejemplo, podés definir que el indexador global de facturas no puede agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:
>
> (private) IndexadorDeFacturas>>agregarFactura: unaFacura
>                                               self factuas add: unaFactura.
>
> (public) Cliente>>agregarFactura: unaFacura
>                               self factuas add: unaFactura.
>                               IndexadorDeFacturas instance agregarFactura: unaFacura.
>
> Si uno es lo suficientemente disciplinado como para no usar el protocolo privado del indexador de facturas ya no hay problemas.
>
> IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que te trae el become.
>
> HTH,
> Andrés
>
> Gastón Dall' Oglio escribió:
>> Hola gente.
>> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>> Supongamos que tengo unaFactura que esta referenciada desde una colección
>> perteneciente a un cliente (sus facturas) y también desde una colección de
>> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
>> hacer algo como:
>> unaFactura become: nil
>> 1) Esto me asegura que ya nadie la referencia, y será liberada.
>> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
>> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
>> ignorar con un #select: o permanente con un #removeAll:
>> 3) El tiempo normal que demora un #become: aumenta considerablemente por
>> tratarse de objetos persistidos por Magma.
>> Saludos!
>> El 12 de enero de 2011 18:40, Hernán Morales Durand <
>> [hidden email]> escribió:
>>> Hola Gerard,
>>>
>>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>>
>>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>>> the relational wall", te va a servir para lo conceptual.
>>>
>>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>>> una por separado, de que en ese diccionario exista una entrada con el
>>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>>> idea de que automáticamente ya existiera una colección vinculada a
>>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>>> que sería perfectamente válida una instancia root que tuviera un
>>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>>> en un diccionario por cada entidad.
>>>>
>>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>>> existir varias variables de instancia nombradas que podés hacer
>>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>>> instancia a ese objeto raíz.
>>>
>>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>>> una relación 1:N me va a generar una clase con una colección y una
>>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>>> relaciones.
>>>>
>>>> ¿Y grandes volúmenes de datos?
>>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>>> índices, analizar las consultas que vas a tener, las profundidades de
>>> tus objetos y en base a eso escribir ReadStrategies razonables para
>>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>>> 8). Más bits en los indices, más reducidos los resultados de un
>>> #where:, y menos escaneo lineal del #select: posterior, pero más
>>> procesamiento por cada objeto.
>>>
>>>> Si tienes una lista inmensa de
>>>> facturación y debes de empezar a patearte los items para obtener las
>>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>>> que podrías ir directamente a la colección de facturas del cliente,
>>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>>> estan en el rango de fechas correcto; es decir, debo tener una
>>>> colección de facturas y otras colecciones parciales de facturas en
>>>> cada cliente.
>>> Lo de las colecciones maestras grandes es una costumbre del mundo
>>> relacional, los programadores relacionales se acostumbran a usarlas
>>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>>> performance viene cambiando la indexación, pero es una opción para
>>> reducir complejidad.
>>>
>>> Una opción interesante es que podés usar #where: y persistir los
>>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>>> te daría consultas predefinidas. Lo bueno es que si persistís un
>>> Reader y agregás más objetos a la colección original luego, es decir,
>>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>>> para resultados paginados) tenés que revisar la profundidad de los
>>> objetos que van a ser consultados y hacerte una ReadStrategy
>>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>>
>>>> Podría ir más lejos en el ejemplo y plantear varias
>>>> entidades a las que les interesaría tener su propia relación con las
>>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>>
>>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>>> performance, usá un Message spy. Si no tenés problemas, escribí como
>>> si nada pasara :)
>>>
>>> Saludos
>>>
>>>
>>>> No sé si me he expresado bien.
>>>>
>>>> Saludos.
>>>>
>>>>
>>>>
>>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>>> Hola,
>>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>>
>>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>>> yerba
>>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>>> una
>>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>>> resolver
>>>>> :-P pero, simplemente, no los mismos.
>>>>>
>>>>> Saludos,
>>>>> Facu
>>>>>
>>>>> 2011/1/11 gerard <[hidden email]>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>>> Pharo.
>>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>>> menos en algunos ORMs lo he visto.
>>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>>> etc etc
>>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>>> objetos?
>>>>>> Saludos y gracias por la ayuda.
>>>>>> --
>>>>>> To post to this group, send email to [hidden email]
>>>>>> To unsubscribe from this group, send email to
>>>>>> [hidden email]<[hidden email]>
>>> <[hidden email]<[hidden email]>
>>>>>> http://www.clubSmalltalk.org
>>>> --
>>>> To post to this group, send email to [hidden email]
>>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>> http://www.clubSmalltalk.org
>>>
>>>
>>> --
>>> Hernán Morales
>>> Information Technology Manager,
>>> Institute of Veterinary Genetics.
>>> National Scientific and Technical Research Council (CONICET).
>>> La Plata (1900), Buenos Aires, Argentina.
>>> Telephone: +54 (0221) 421-1799.
>>> Internal: 422
>>> Fax: 425-7980 or 421-1799.
>>>
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Juan-2
In reply to this post by Gastón Dall' Oglio
Hola gente

Bueno aporto un poco, creo que gaboto dijo algo claro y clave.
Tenes que pensar el dominio para modelarlo sin restricciones , lo de
la base de datos ,yo y quizas todo el mundo ,no se, lo llamo programacion
orientada al modelo de datos. o sea en bases de datos relacionales
se programa , los progamas son orientados a la representacion de los datos.
Entonces cuando cambias algun tipo de dato o definicion el programa sufre cambios
a veces muy grandes.
El mapeo es una solucion intermedia. o sea se programa en "objetos" o en lenguajes objetosos, excepto claro esta el smalltalk. y se mapea los "objetos" a la db , teniendo
mas o menos exito.
En gral cuando se parte de esta formacion se tiende a mapear, una clase una tabla una instancia una row.
Ese es el modelo de pensamiento que hay que romper, hay que pensar tu objeto tu parte del modelo que necesita conocer? , las facturas ? ,ok. son muchas ? bueno conocera una coleccion , y cada factura que necesita conocer? , (por conocer digamos ,normalmente lo tiene o lo usa) podes arrancar con un modelo exploratorio , en verdad deberias. y experimentar con los colaboradores ( cosas q conoce otros objetos del dominio) e ir moviendolos agregando sacando etc, hasta que pueda cumplir con su cometido ( el modelo funcione) .
Luego pensa en la persistencia, no al reves. lo ultimo. o sea que el modelo ande primero
luego la persistencia , asi como tambien te indicaron aqui y por necesidades de perfomance u otras haces las "chanchadas" o sea ensucias a tu modelo.
por ensuciar digamos que es la parte donde la persistencia afecta a tu modelo .
bueno acoto hasta aca.
saludos
mdc

2011/1/13 Gastón Dall' Oglio <[hidden email]>
> Buenas, ya que estamos yo también me meto jeje.

Buenas. Yo creo que la lista esta para que todo el que tenga algo que aportar lo haga :)

Ya que estamos con el tema base de objetos y de datos, les consulto si alguno sabe que orientación tienen las bases de datos que se encuadran bajo el enfoque nosql. ¿Están tratando de hacer algo orientado a objetos o algo totalmente novedoso?




El 13 de enero de 2011 10:58, Gaboto <[hidden email]> escribió:

Buenas, ya que estamos yo también me meto jeje.
Solo un comentario. Para hacer un buen modelo en la base de objetos lo que quizá deberías hacer es pensar en que tenés un programa en memoria y que nunca se apaga. Es decir, imaginate que vos tenes que hacer un programa que no tiene que persistir nada porque la compu siempre está prendida, Entonces, en ese caso como harías? yo tendría las colecciones que correspondan y agregaría algún diccionario por eficiencia, etc.
La consistencia del modelo la tendría que manejar el modelo mismo, asegurandose de poner y sacar las cosas de las colecciones cuando corresponda. No hay ningún trigger mágico ni nada de eso, que viene de otro paradigma.
Yo creo que la idea de una base de objetos es justamente esa, hacer lo más transparente posible la persistencia, aunque en realidad haya algunas sutiles diferencias en la práctica...
Luego con el tiempo, como ya mencionaron acá, te vas a ir dando cuenta de si hay que hacer alguna "chanchada" o algo para ir optimizando los tiempos.

2011/1/13 Gastón Dall' Oglio <[hidden email]>
Muchas gracias por sus comentarios!

Sí, el become ya me parecía una mala idea por lo que he leído.

Saludos.

El 13 de enero de 2011 08:48, Esteban Lorenzano <[hidden email]> escribió:

hola,
bueno, me meto en el thread :)
IMHO, el problema es que seguís pensando tu estructura de datos en relacional, no en objetos (por eso lo pensás como una estructura de datos y no como un grafo de objetos, je).
Yo la primer pregunta que me haría es "para qué quiero la colección de todas las facturas? las necesito, o es solo que 'me parece' que tienen que estar en una colección aparte (como si la colección fuera una tabla)"
realmente me parece que es una instancia muy nueva de tu aplicación (por lo que veo) para saber si realmente necesitas tener una colección de facturas aparte. En estos momentos no hay nada que te impida hacer algo como:

allInvoices
       ^self customers
               inject: Set new
               into: [ :all :each | all, each invoices ]

eso puede demostrarse no eficiente con el tiempo, pero también puede demostrarse que no necesitás #allInvoices y entonces te ahorrás todo el problema de mantener invoices en dos lugares.
Si pese a todo decidís que sí necesitas mantenerlo aparte, lo que te recomiendo es lo mismo que te recomendó Andrés, y le agrego que, para borrar facturas, hagas algo como:

Customer>>removeInvoice: anInvoice
       self invoices remove: anInvoice.
       IndexadorDeFacturas instance remove: anInvoice.

usar el become (forward o no), suele no ser una respuesta correcta. Entre otras cosas porque te hace un scan de todos los objetos en memoria, en pharo/squeak, dado que no tienen object table.

nunca dejes de pensar desde el punto de vista del modelo, olvidate de pensar en la estructura!

Saludos,
Esteban

El 13/01/2011, a las 7:42a.m., andres escribió:

> Yo personalmente evitaría eso porque:
>
> 1. Estás asumiendo cosas sobre las colecciones que contienen a la factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones y esas colecciones por algún motivo no pueden contener nils las rompés.
> 2. Tenés que redefinir el protocolo de colecciones para manejar tus casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que hacer (select:[..| noNil]) size).
> 3. Estás asumiendo que nadie mas referencia a la factura (ej. un inspector, un reporte, un histórico de facturas, etc). Si así fuera rompés todo.
> 4. Como regla genérica el #become no se debe usar para resolver problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es definir alguien que sepa sincronizar bien las colecciones de facturas. Por ejemplo, podés definir que el indexador global de facturas no puede agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:
>
> (private) IndexadorDeFacturas>>agregarFactura: unaFacura
>                                               self factuas add: unaFactura.
>
> (public) Cliente>>agregarFactura: unaFacura
>                               self factuas add: unaFactura.
>                               IndexadorDeFacturas instance agregarFactura: unaFacura.
>
> Si uno es lo suficientemente disciplinado como para no usar el protocolo privado del indexador de facturas ya no hay problemas.
>
> IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que te trae el become.
>
> HTH,
> Andrés
>
> Gastón Dall' Oglio escribió:
>> Hola gente.
>> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>> Supongamos que tengo unaFactura que esta referenciada desde una colección
>> perteneciente a un cliente (sus facturas) y también desde una colección de
>> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
>> hacer algo como:
>> unaFactura become: nil
>> 1) Esto me asegura que ya nadie la referencia, y será liberada.
>> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
>> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
>> ignorar con un #select: o permanente con un #removeAll:
>> 3) El tiempo normal que demora un #become: aumenta considerablemente por
>> tratarse de objetos persistidos por Magma.
>> Saludos!
>> El 12 de enero de 2011 18:40, Hernán Morales Durand <
>> [hidden email]> escribió:
>>> Hola Gerard,
>>>
>>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>>
>>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>>> the relational wall", te va a servir para lo conceptual.
>>>
>>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>>> una por separado, de que en ese diccionario exista una entrada con el
>>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>>> idea de que automáticamente ya existiera una colección vinculada a
>>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>>> que sería perfectamente válida una instancia root que tuviera un
>>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>>> en un diccionario por cada entidad.
>>>>
>>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>>> existir varias variables de instancia nombradas que podés hacer
>>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>>> instancia a ese objeto raíz.
>>>
>>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>>> una relación 1:N me va a generar una clase con una colección y una
>>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>>> relaciones.
>>>>
>>>> ¿Y grandes volúmenes de datos?
>>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>>> índices, analizar las consultas que vas a tener, las profundidades de
>>> tus objetos y en base a eso escribir ReadStrategies razonables para
>>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>>> 8). Más bits en los indices, más reducidos los resultados de un
>>> #where:, y menos escaneo lineal del #select: posterior, pero más
>>> procesamiento por cada objeto.
>>>
>>>> Si tienes una lista inmensa de
>>>> facturación y debes de empezar a patearte los items para obtener las
>>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>>> que podrías ir directamente a la colección de facturas del cliente,
>>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>>> estan en el rango de fechas correcto; es decir, debo tener una
>>>> colección de facturas y otras colecciones parciales de facturas en
>>>> cada cliente.
>>> Lo de las colecciones maestras grandes es una costumbre del mundo
>>> relacional, los programadores relacionales se acostumbran a usarlas
>>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>>> performance viene cambiando la indexación, pero es una opción para
>>> reducir complejidad.
>>>
>>> Una opción interesante es que podés usar #where: y persistir los
>>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>>> te daría consultas predefinidas. Lo bueno es que si persistís un
>>> Reader y agregás más objetos a la colección original luego, es decir,
>>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>>> para resultados paginados) tenés que revisar la profundidad de los
>>> objetos que van a ser consultados y hacerte una ReadStrategy
>>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>>
>>>> Podría ir más lejos en el ejemplo y plantear varias
>>>> entidades a las que les interesaría tener su propia relación con las
>>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>>
>>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>>> performance, usá un Message spy. Si no tenés problemas, escribí como
>>> si nada pasara :)
>>>
>>> Saludos
>>>
>>>
>>>> No sé si me he expresado bien.
>>>>
>>>> Saludos.
>>>>
>>>>
>>>>
>>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>>> Hola,
>>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>>
>>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>>> yerba
>>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>>> una
>>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>>> resolver
>>>>> :-P pero, simplemente, no los mismos.
>>>>>
>>>>> Saludos,
>>>>> Facu
>>>>>
>>>>> 2011/1/11 gerard <[hidden email]>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>>> Pharo.
>>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>>> menos en algunos ORMs lo he visto.
>>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>>> etc etc
>>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>>> objetos?
>>>>>> Saludos y gracias por la ayuda.
>>>>>> --
>>>>>> To post to this group, send email to [hidden email]
>>>>>> To unsubscribe from this group, send email to
>>>>>> [hidden email]<[hidden email]>
>>> <[hidden email]<[hidden email]>
>>>>>> http://www.clubSmalltalk.org
>>>> --
>>>> To post to this group, send email to [hidden email]
>>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>> http://www.clubSmalltalk.org
>>>
>>>
>>> --
>>> Hernán Morales
>>> Information Technology Manager,
>>> Institute of Veterinary Genetics.
>>> National Scientific and Technical Research Council (CONICET).
>>> La Plata (1900), Buenos Aires, Argentina.
>>> Telephone: +54 (0221) 421-1799.
>>> Internal: 422
>>> Fax: 425-7980 or 421-1799.
>>>
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
Reply | Threaded
Open this post in threaded view
|

Re: Programación con un gestor de base de datos orientado a objetos

Guillermo Schwarz
Me parece muy superficial la discusiòn.

De partida el modelamiento de base de datos relacionales parte de la idea E. F. Codd (http://www.dcc.uchile.cl/~rbaeza/inf/codd.html) de modelar las dependencias funcionales (http://cs.gmu.edu/~aobaidi/spring-02/Normalization.ppt), que no son otra cosa que pares X -> Y (como un Dictionary o un HashMap). Eso se puede representar directamente en Smalltalk.

La representación E-R y la representación en tablas son sólo el resultado de tratar de convertir las dependencias funcionales en una representación entendible por humanos y por máquinas respectivamente. Lo simpàtico del asunto es que las dependencias funcionales podrìan representarse directamente en Smalltalk sin necesidad de mecanismos intermedios, derivando luego el modelo E-R o el modelo en tablas según sea necesario.

Podrìas tener aplicaciones funcionando, cambiar las dependencias funcionales, y que la aplicación se adapte a los cambios sin necesidad de reprogramar nada ni de detener la aplicación.

Para los que tengan dificultades entendiendo lo anterior, serìa factible hacer un generador de còdigo que genere interfaces de usuario, modelo de datos y migrador de datos en forma automática, aunque claramente prefiero que la aplicación no se detenga y siga funcionando sin necesidad de programar nada.

Saludos,
Guillermo.

2011/1/13 Juan <[hidden email]>
Hola gente

Bueno aporto un poco, creo que gaboto dijo algo claro y clave.
Tenes que pensar el dominio para modelarlo sin restricciones , lo de
la base de datos ,yo y quizas todo el mundo ,no se, lo llamo programacion
orientada al modelo de datos. o sea en bases de datos relacionales
se programa , los progamas son orientados a la representacion de los datos.
Entonces cuando cambias algun tipo de dato o definicion el programa sufre cambios
a veces muy grandes.
El mapeo es una solucion intermedia. o sea se programa en "objetos" o en lenguajes objetosos, excepto claro esta el smalltalk. y se mapea los "objetos" a la db , teniendo
mas o menos exito.
En gral cuando se parte de esta formacion se tiende a mapear, una clase una tabla una instancia una row.
Ese es el modelo de pensamiento que hay que romper, hay que pensar tu objeto tu parte del modelo que necesita conocer? , las facturas ? ,ok. son muchas ? bueno conocera una coleccion , y cada factura que necesita conocer? , (por conocer digamos ,normalmente lo tiene o lo usa) podes arrancar con un modelo exploratorio , en verdad deberias. y experimentar con los colaboradores ( cosas q conoce otros objetos del dominio) e ir moviendolos agregando sacando etc, hasta que pueda cumplir con su cometido ( el modelo funcione) .
Luego pensa en la persistencia, no al reves. lo ultimo. o sea que el modelo ande primero
luego la persistencia , asi como tambien te indicaron aqui y por necesidades de perfomance u otras haces las "chanchadas" o sea ensucias a tu modelo.
por ensuciar digamos que es la parte donde la persistencia afecta a tu modelo .
bueno acoto hasta aca.
saludos
mdc


2011/1/13 Gastón Dall' Oglio <[hidden email]>
> Buenas, ya que estamos yo también me meto jeje.

Buenas. Yo creo que la lista esta para que todo el que tenga algo que aportar lo haga :)

Ya que estamos con el tema base de objetos y de datos, les consulto si alguno sabe que orientación tienen las bases de datos que se encuadran bajo el enfoque nosql. ¿Están tratando de hacer algo orientado a objetos o algo totalmente novedoso?




El 13 de enero de 2011 10:58, Gaboto <[hidden email]> escribió:

Buenas, ya que estamos yo también me meto jeje.
Solo un comentario. Para hacer un buen modelo en la base de objetos lo que quizá deberías hacer es pensar en que tenés un programa en memoria y que nunca se apaga. Es decir, imaginate que vos tenes que hacer un programa que no tiene que persistir nada porque la compu siempre está prendida, Entonces, en ese caso como harías? yo tendría las colecciones que correspondan y agregaría algún diccionario por eficiencia, etc.
La consistencia del modelo la tendría que manejar el modelo mismo, asegurandose de poner y sacar las cosas de las colecciones cuando corresponda. No hay ningún trigger mágico ni nada de eso, que viene de otro paradigma.
Yo creo que la idea de una base de objetos es justamente esa, hacer lo más transparente posible la persistencia, aunque en realidad haya algunas sutiles diferencias en la práctica...
Luego con el tiempo, como ya mencionaron acá, te vas a ir dando cuenta de si hay que hacer alguna "chanchada" o algo para ir optimizando los tiempos.

2011/1/13 Gastón Dall' Oglio <[hidden email]>
Muchas gracias por sus comentarios!

Sí, el become ya me parecía una mala idea por lo que he leído.

Saludos.

El 13 de enero de 2011 08:48, Esteban Lorenzano <[hidden email]> escribió:

hola,
bueno, me meto en el thread :)
IMHO, el problema es que seguís pensando tu estructura de datos en relacional, no en objetos (por eso lo pensás como una estructura de datos y no como un grafo de objetos, je).
Yo la primer pregunta que me haría es "para qué quiero la colección de todas las facturas? las necesito, o es solo que 'me parece' que tienen que estar en una colección aparte (como si la colección fuera una tabla)"
realmente me parece que es una instancia muy nueva de tu aplicación (por lo que veo) para saber si realmente necesitas tener una colección de facturas aparte. En estos momentos no hay nada que te impida hacer algo como:

allInvoices
       ^self customers
               inject: Set new
               into: [ :all :each | all, each invoices ]

eso puede demostrarse no eficiente con el tiempo, pero también puede demostrarse que no necesitás #allInvoices y entonces te ahorrás todo el problema de mantener invoices en dos lugares.
Si pese a todo decidís que sí necesitas mantenerlo aparte, lo que te recomiendo es lo mismo que te recomendó Andrés, y le agrego que, para borrar facturas, hagas algo como:

Customer>>removeInvoice: anInvoice
       self invoices remove: anInvoice.
       IndexadorDeFacturas instance remove: anInvoice.

usar el become (forward o no), suele no ser una respuesta correcta. Entre otras cosas porque te hace un scan de todos los objetos en memoria, en pharo/squeak, dado que no tienen object table.

nunca dejes de pensar desde el punto de vista del modelo, olvidate de pensar en la estructura!

Saludos,
Esteban

El 13/01/2011, a las 7:42a.m., andres escribió:

> Yo personalmente evitaría eso porque:
>
> 1. Estás asumiendo cosas sobre las colecciones que contienen a la factura. Si el día de mañana se te ocurre cambiar el tipo de colecciones y esas colecciones por algún motivo no pueden contener nils las rompés.
> 2. Tenés que redefinir el protocolo de colecciones para manejar tus casos ad-hoc (ej. si tenés un array el #size ya no te sirve; tenés que hacer (select:[..| noNil]) size).
> 3. Estás asumiendo que nadie mas referencia a la factura (ej. un inspector, un reporte, un histórico de facturas, etc). Si así fuera rompés todo.
> 4. Como regla genérica el #become no se debe usar para resolver problemas de diseño; eso te lleva a una seguidilla de hackasos. Mejor es definir alguien que sepa sincronizar bien las colecciones de facturas. Por ejemplo, podés definir que el indexador global de facturas no puede agregar o eliminar facturas, sólo el cliente lo hace. Entonces te queda:
>
> (private) IndexadorDeFacturas>>agregarFactura: unaFacura
>                                               self factuas add: unaFactura.
>
> (public) Cliente>>agregarFactura: unaFacura
>                               self factuas add: unaFactura.
>                               IndexadorDeFacturas instance agregarFactura: unaFacura.
>
> Si uno es lo suficientemente disciplinado como para no usar el protocolo privado del indexador de facturas ya no hay problemas.
>
> IMHO es mucho menos esfuerzo hacer ese diseño que todo el quilombo que te trae el become.
>
> HTH,
> Andrés
>
> Gastón Dall' Oglio escribió:
>> Hola gente.
>> Capaz es una burrada pero bueno, no me quiero quedar con las dudas.
>> Supongamos que tengo unaFactura que esta referenciada desde una colección
>> perteneciente a un cliente (sus facturas) y también desde una colección de
>> todas las facturas. Para el tema de resolver el "borrado en cascada" puedo
>> hacer algo como:
>> unaFactura become: nil
>> 1) Esto me asegura que ya nadie la referencia, y será liberada.
>> 2) Ambas colecciones quedan con la misma cantidad de elementos, solo que
>> ahora tienen una referencia a nil. Que exista una factura nil es fácil de
>> ignorar con un #select: o permanente con un #removeAll:
>> 3) El tiempo normal que demora un #become: aumenta considerablemente por
>> tratarse de objetos persistidos por Magma.
>> Saludos!
>> El 12 de enero de 2011 18:40, Hernán Morales Durand <
>> [hidden email]> escribió:
>>> Hola Gerard,
>>>
>>> El día 12 de enero de 2011 10:59, gerard <[hidden email]> escribió:
>>>> Lo que hecho de menos es una "manera de hacer" estandar que prevenga
>>>> que uno haga algunas cosas no del todo recomendables... Aunque sean
>>>> objetos no deja de ser una BD, y seguro que pudes hacer algunas
>>>> animaladas espectaculares sólo por no tener claro un concepto.
>>>>
>>> Hay un texto muy bueno que se llama algo como "Objectivity: Hitting
>>> the relational wall", te va a servir para lo conceptual.
>>>
>>>> Otro ejemplo, yo guardo como root un Dictionary. Tengo definidas unas
>>>> clases "Entity", que al arrancar la imagen Smalltalk se aseguran, cada
>>>> una por separado, de que en ese diccionario exista una entrada con el
>>>> mismo nombre de la clase y una OrderedCollection. Eso lo hice con la
>>>> idea de que automáticamente ya existiera una colección vinculada a
>>>> cada clase Entity... pero ahora veo que quizás eso es una tontería y
>>>> que sería perfectamente válida una instancia root que tuviera un
>>>> montón de colecciones, una por cada entidad. Por otro lado veo algunos
>>>> ejemplos o screencast de Magma que usan el otro sistema: una entrada
>>>> en un diccionario por cada entidad.
>>>>
>>> Es preferible que el objeto raíz sea un objeto de "primera clase"
>>> (Mundo, Fabrica, etc). Como dijiste, dentro de ese objeto pueden
>>> existir varias variables de instancia nombradas que podés hacer
>>> colecciones. Magma no te hace problemas si agregas nuevas variables de
>>> instancia a ese objeto raíz.
>>>
>>>> En fin, me gustaría que todas las clases-entidades tuvieran un
>>>> comportamiento homogeneo. En un ORM, al generarse el código, sé que
>>>> una relación 1:N me va a generar una clase con una colección y una
>>>> serie de métodos estandard, para añadir un elemento a la colección, o
>>>> eliminarla etc Es decir un comportamiento general, dependiendo de las
>>>> relaciones.
>>>>
>>>> ¿Y grandes volúmenes de datos?
>>> ¿Cuanto es grande? En el caso de Magma es casi obligatorio hacer
>>> índices, analizar las consultas que vas a tener, las profundidades de
>>> tus objetos y en base a eso escribir ReadStrategies razonables para
>>> tus requerimientos. Magma aguanta índices de hasta 4096 bits, pero
>>> pasando los 128-bits son un dolor de cabeza si tenés millones de
>>> objetos (en mi caso tengo 20 millones). Lo normal es que trabajes con
>>> índices de 32 o 64 a 128 bits (fijate que tienen que ser múltiplos de
>>> 8). Más bits en los indices, más reducidos los resultados de un
>>> #where:, y menos escaneo lineal del #select: posterior, pero más
>>> procesamiento por cada objeto.
>>>
>>>> Si tienes una lista inmensa de
>>>> facturación y debes de empezar a patearte los items para obtener las
>>>> facturas de un determinado cliente como lo haces? Por un lado podrias
>>>> hacer que cada cliente tuviera su propia colección de facturas, con lo
>>>> que podrías ir directamente a la colección de facturas del cliente,
>>>> perfecto. Pero ¿y si quiero todas aquellas facturas creadas el último
>>>> més sea cual sea el cliente? Entonces ya no tiene sentido acudir a las
>>>> colecciones de facturas de los clientes, sería más trabajoso; debería
>>>> ir a una lista "general" de facturas y empezar a seleccionar las que
>>>> estan en el rango de fechas correcto; es decir, debo tener una
>>>> colección de facturas y otras colecciones parciales de facturas en
>>>> cada cliente.
>>> Lo de las colecciones maestras grandes es una costumbre del mundo
>>> relacional, los programadores relacionales se acostumbran a usarlas
>>> furiosamente, en vez de dispersarlas en el dominio en colecciones más
>>> chicas que no son tan violentadas. Esto no significa que tenés que ir
>>> a hacer 40 colecciones chicas, y en todo casi si lo hacés, la
>>> performance viene cambiando la indexación, pero es una opción para
>>> reducir complejidad.
>>>
>>> Una opción interesante es que podés usar #where: y persistir los
>>> resultados, es decir, los MagmaReaders, en otra MagmaCollection y esto
>>> te daría consultas predefinidas. Lo bueno es que si persistís un
>>> Reader y agregás más objetos a la colección original luego, es decir,
>>> a la cual le hiciste el #where:, los objetos agregados van a aparecer
>>> la próxima vez que enumeres el Reader. Pero antes de enumerar un
>>> Reader entero (no te lo recomiento tampoco, es mejor cuando lo usás
>>> para resultados paginados) tenés que revisar la profundidad de los
>>> objetos que van a ser consultados y hacerte una ReadStrategy
>>> apropiada. Fijate en MagmaCollectionTester>>#testPersistentReader
>>>
>>>> Podría ir más lejos en el ejemplo y plantear varias
>>>> entidades a las que les interesaría tener su propia relación con las
>>>> facturas... Bien: ahora el usuario quiere eliminar una factura, y
>>>> cuando lo haga debo de ser muy consciente de todas las colecciones
>>>> donde puede estar ubicada esa factura para poder eliminarla "bien".
>>>> Debo ir a la lista de facturas del cliente, a la lista general de
>>>> facturas que he mencionado etc etc   Veo muy complicado no dejarse
>>>> ningún cabo suelto. No me refería tanto a que pasara el GC, que
>>>> realmente da igual, sino a la posibilidad de dejarse instancias que ya
>>>> no deberian estar, de ahí la comparación con el ON DELETE ACTION.
>>>>
>>> Las consultas tambien pueden ser objetos, y como tales pueden ser
>>> persistidas. Fijate si lo de arriba te sirve. Si tenés problemas de
>>> performance, usá un Message spy. Si no tenés problemas, escribí como
>>> si nada pasara :)
>>>
>>> Saludos
>>>
>>>
>>>> No sé si me he expresado bien.
>>>>
>>>> Saludos.
>>>>
>>>>
>>>>
>>>> On 12 ene, 14:11, Facundo Vozzi <[hidden email]> wrote:
>>>>> Hola,
>>>>> Mariano ya te respondió casi todo, para agregar algo, podés leer sobre
>>>>> algunos enfoques de persistencia (incluído Magma) en el libro de
>>> Seaside:http://book.seaside.st/book/advanced/persistency.
>>>>> Vas a ver que hablan de persistencia basada en Imagen, que es solo eso
>>>>> guardar la imagen con una global que apunte a tu root (un singleton, por
>>>>> ejemplo). Después cambiar a que se persista con Magma o Goods es casi un
>>>>> tramite para GemStone tenés que laburar un cacho más.
>>>>>
>>>>> Respecto de las relaciones, los delete cascade, triggers y cualquier
>>> yerba
>>>>> de la BD relacional tenés que hacer lo siguiente: OLVIDARTE. Para usar
>>> una
>>>>> base de objetos y sacarle provecho tenés que hacer tu módelo lo más
>>>>> orientado a objetos que te salga y no preocuparte por problemas de otro
>>>>> paradigma. Quedate tranquilo que vas a tener otros problemas para
>>> resolver
>>>>> :-P pero, simplemente, no los mismos.
>>>>>
>>>>> Saludos,
>>>>> Facu
>>>>>
>>>>> 2011/1/11 gerard <[hidden email]>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>> Buenas. estoy realizando una pequeña aplicación, sólo con propósito de
>>>>>> pruebas, para trabajar con una base de datos orientada a objetos. Como
>>>>>> solo quería hacer unas pocas pruebas me he decantado por Magma y
>>>>>> Pharo.
>>>>>> Ahora bien, mi problema es que dudo sobre la manera en que deben
>>>>>> hacerse según que cosas cuando guardas datos como objetos.
>>>>>> 1. Relaciones 1:N. Por ejemplo, una temporada de fútbol tiene varias
>>>>>> jornadas, correcto? Es lógico pensar que cada objeto temporada debería
>>>>>> de tener una colección de objetos jornada. Ahora bien, cada objeto
>>>>>> jornada debería tener una referencia a su tempoarada no? bien, al
>>>>>> menos en algunos ORMs lo he visto.
>>>>>> 2. Al eliminar, por ejemplo, una temporada, deberíamos tener en cuenta
>>>>>> que debemos cargarnos tambien aquellas jornadas que pertenecen a esa
>>>>>> temporada, y a su vez todos los partidos etc etc lo que vendría a ser
>>>>>> una ON DELETE CASCADE de las BBDD relacionales...
>>>>>> Básicamente da la sensación de que sería relativamente fácil en un
>>>>>> momento dado dejar datos inconsistentes en la BD, o que en volúmenes
>>>>>> de datos grandes a la hora de patearse una colección inmensa la demora
>>>>>> sería muy grande... o que no tienes según que automatismos, cómo los
>>>>>> triggers, para asegurarte que suceda algo al añadir un nuevo registro
>>>>>> etc etc
>>>>>> Finalmente, ¿existe algún manual de "buenas prácticas" con DB de
>>>>>> objetos?
>>>>>> Saludos y gracias por la ayuda.
>>>>>> --
>>>>>> To post to this group, send email to [hidden email]
>>>>>> To unsubscribe from this group, send email to
>>>>>> [hidden email]<[hidden email]>
>>> <[hidden email]<[hidden email]>
>>>>>> http://www.clubSmalltalk.org
>>>> --
>>>> To post to this group, send email to [hidden email]
>>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>> http://www.clubSmalltalk.org
>>>
>>>
>>> --
>>> Hernán Morales
>>> Information Technology Manager,
>>> Institute of Veterinary Genetics.
>>> National Scientific and Technical Research Council (CONICET).
>>> La Plata (1900), Buenos Aires, Argentina.
>>> Telephone: +54 (0221) 421-1799.
>>> Internal: 422
>>> Fax: 425-7980 or 421-1799.
>>>
>>> --
>>> To post to this group, send email to [hidden email]
>>> To unsubscribe from this group, send email to
>>> [hidden email]<[hidden email]>
>>>
>>> http://www.clubSmalltalk.org
>>>
>
> --
> To post to this group, send email to [hidden email]
> To unsubscribe from this group, send email to [hidden email]
>
> http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]

http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org



--
Saludos cordiales,

Guillermo Schwarz
Sun Certified Enterprise Architect

--
To post to this group, send email to [hidden email]
To unsubscribe from this group, send email to [hidden email]
 
http://www.clubSmalltalk.org
12