[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