[Python-es] ¿Como quereis la Interfaz (API) de la capa de persistencia?

Ernesto Revilla aerd en retemail.es
Mar Ago 13 20:17:52 CEST 2002


Estimados señores,

estoy diseñando una nueva capa de persistencia de objetos para Python >= 2.2
La idea es que uno especifica en un archivo de texto con las clases y sus
atributos respectivos (nombre, tipo, etc.). Posteriormente, el software
genera una parte de código y hace cosas especiales internamente. La capa de
persistencia permitirá persistir hacia bases de datos relacionales, no
relacionales (tipo BSDDB), archivos de texto plano, pickles y XML. Incluso
los atributos de una misma instancia de clase podrán persistir en diferentes
mecanismos de persistencias. La capa soportará transacciones.
(Ver final del correo para un ejemplo de uso.)

==========================================
Quiero que me digáis cuál es la manera que más os gusta para acceder a los
atributos de una instancia.

Suponed que la clase de 'Persona' tiene los atributos 'nombre' tipo string,
'apellidos' tipo string y 'edad' tipo entero.

=================
Alternativa 1:

p=Persona()
p.nombre='Pepe'        # establecer nuevo valor
p.apellidos='Pérez'     #  igual
p.edad=54                # igual

print "La edad de ",p.nombre, " es ", p.edad    # Lectura de atributos

# Acceder a meta-datos:
print "el nombre del campo es", p._class.apellidos.name
print " y su tipo es ", p._class.apellidos.type
if p._class.apellidos.validationRule:
    print "Regla de validación: ", p._class.apellidos.validationRule

=================
Alternativa 2:

p=Persona()
p.nombre.value='Pepe'        # establecer nuevo valor   (.value podria
obviarse)
p.apellidos.value='Pérez'     #  igual
p.edad.value=54                # igual

print "La edad de ",p.nombre.value, " es ", p.edad.value    # Lectura de
atributos
# Aqui .value no se puede obviar porque no se si accede al atributo o a su
valor, ver linea siguiente

# Acceder a meta-datos:
print "el nombre del campo es", p.apellidos.name, " y su tipo es ",
p.apellidos.type
if p.apellidos.validationRule: print "Regla de validación: ",
p.apellidos.validationRule
# Aquí _class no hace falta, porque al especificar
# .value explicitamente, puedo hacer que todos los
# demas atributops se busquen en la definición de la clase.


=====================
Alternativa 3 (tipo Webware.MiddleKit):

# para cada atributo 'x' se crea un atributo interno _x,
# un método para leerlo x() y otro para modificar setx():

p=Persona()
p.setnombre('Pepe')        # establecer nuevo valor   (.value podria
obviarse)
p.setapellidos('Pérez')     #  igual
p.setedad(54)                # igual

print "La edad de ",p.nombre(), " es ", p.edad()    # Lectura de atributos

# Acceder a meta-datos:
print "el nombre del campo es", p.klass().apellidos.name(), " y su tipo es
", p.klass().apellidos.type()
if p.klass().apellidos.validationRule(): print "Regla de validación: ",
p.klass().apellidos.validationRule()

=======================
El problema: Ya os habéis dado cuenta que mi problema es que:
x=objeto.atributo   # debería devolver el valor no la referencia al atributo
y=objeto.atributo.type    # debería devolver el tipo de atributo (sacado de
la definición de clase)

pero dado que no sé cómo se puede hacer, tengo que buscar una alternativa.

=======================
Ejemplos de la api:

from Persistence import PersistenteManager  # es singleton

# Empezar una transacción. Todas las operaciones de usuario se realizan
sobre una transacción siempre.
trans=PersistenceManager.Transaction()

# Crear un objeto
vendedor=Agente()
vendedor.nombre="Erny"
trans.add(vendedor)    # Agregar objeto a la transacción

# Recuperar objetos:
resultado=trans.retrieve(oql="SELECT c FROM Clientes c WHERE c.nombre LIKE
'A*'")

# iterar sobre objetos
while resultado.hasMore():
    c=resultado.next()
    # Modificar un atributo
    c.vendedor=vendedor
    # llamar a un método
    c.display()

# borrar un elemento (el último de los anteriores)
del c        # No sé todavía si va a ser 'c.delete()' o 'del c'

# finalmente grabar todas las modificaciones realizadas.
trans.commit()

========================
Usos previstos:
Aplicaciones cualesquiera con un conjunto importante de clases persistentes
(>30) , en entorno web u otro.
Persistencia inicial prevista para cualquier base de datos relacional con
interfaz DB-API 2.0, texto plano, más tarde XML, (quizá pickle también).
Posibilidad de guardar versiones antiguas de los objetos en otra base de
datos.

========================
Anotaciones:
* La api y toda la capa están en diseño.
* Las transacciones se pueden reaprovechar, pero llamar a trans.begin() no
es necesario porque se hace automáticamente
* trans.commit() oculta la lógica de bloqueos y transacciones sobre los
mecanismos de persistencia
* trans.retrieve() probablemente devuelva una especie de cursor, los objetos
no se leen realmente hasta acceder a ellos.
* resultado.next(): al leer el objeto, se situarán bloqueos de lectura en la
base de datos, para obtener imágenes consistentes de objetos que se
almacenan en varias tablas
* existirá una caché compartida entre todas las transacciones.
* las modificaciones desde una transacción no serán visibles desde otras
transacciones (y por tanto otros usuarios) hasta realizar un 'commit'.
* Probablemente existirán diferentes versiones en caché de un mismo objeto.
El mecanismo en este caso sería como el de Postgresql
MultiVersionCurrencyControl
* Falta por resolver la actualización de sumas globales acumuladas, y otros
objetos (como contadores) frecuentemente actualizados desde muchos puestos
(en este caso, habría que recuperar el objeto y reaplicarle las operaciones
realizadas, como el aumento en una cantidad).
* La idea incial y gran parte del trabajo está basado en Webware / MiddleKit
de Chuck Esterbrook.

==========================
Documentación:
Webware MiddleKit :
http://webware.sourceforge.net/Webware-0.7/MiddleKit/Docs/index.html
Castor (Java Persistence Layer): www.castor.org
Persisten Layer (Java): http://player.sourceforge.net
Diseño de capas de persistencia (Scott Ambler, inglés):
http://www.ambysoft.com/persistenceLayer.html
y documentos relacionados.


Voluntarios bienvenidos. (ponerse en contacto conmigo: aerd en retemail.es)

Gracias,
Erny








Más información sobre la lista de distribución Python-es