Objetos almacenados sin dolor de cabeza: un ejemplo simple de trabajo con objetos Caché en ObjectScript y Python
Castillo NeuschwansteinEn junio de 2020, exactamente 50 años de almacenes de datos tabulares o, formalmente, un modelo de datos relacionales. Aquí hay un documento oficial,
ese mismo artículo famoso . Por lo cual le agradecemos al Dr. Edgar Frank Codd. Y, por cierto, el modelo de datos relacionales está en la lista de Forbes de las innovaciones globales más importantes de los últimos 100 años.
Por otro lado, curiosamente, Codd consideró las bases de datos relacionales y el lenguaje SQL como una implementación distorsionada de su teoría. Como guía, incluso desarrolló 12 reglas que todo sistema de gestión de bases de datos relacionales debe cumplir (de hecho, son 13 reglas). Y, en verdad, hoy, en el mundo, no puede encontrar DBMS que satisfagan al menos la "Regla 0" de Codd y, por lo tanto, nadie puede llamar a su DBMS 100% relacional :) Tal vez hay excepciones, ¿dime?
El modelo relacional no es muy complejo y se estudia a lo largo y ancho. Incluso puede ser demasiado estudiado. Mientras tanto, en este año de 2019, también celebraremos otro aniversario: exactamente hace 10 años, el hashtag #NoSQL más tarde sobre "no solo SQL" apareció en Twitter y comenzó su rápida penetración en la práctica de desarrollar modelos de bases de datos.
¿Por qué una presentación tan larga? El hecho de que el universo de programación consta de datos (y algoritmos, por supuesto), y la posición de monopolio del modelo relacional conduce, como es más cortés decir, una conciencia dividida del programador. Debido a que los objetos de trabajo en la cabeza del desarrollador (OOP también es total, ¿verdad?), Todas estas listas, colas, árboles, montones, diccionarios, hilos, etc., no son tablas.
¿Y si continúa y recuerda la arquitectura de almacenamiento en el DBMS moderno? Digamos directamente, nadie en su sano juicio almacena datos en forma de tablas. Los desarrolladores de DBMS utilizan con mayor frecuencia variedades del árbol B (por ejemplo, en PostrgeSQL) o, mucho menos a menudo, almacenamiento basado en diccionario. Por otro lado, las barricadas, desarrolladores que usan DBMS para almacenar, también operan en mesas que no son. Y esto obliga a los programadores a cerrar constantemente la brecha semántica con una torpe capa de datos intermedios. Y, por lo tanto, causa tensión dicotómica interna, molestias sistémicas e insomnio de depuración.
Es decir, en resumen, hay una contradicción: empaquetamos los datos en objetos adecuados para la tarea, y al guardarlos debemos ocuparnos de algunas tablas.
Desesperanza? No :) Pero, ¿qué pasa con el mapeo objeto-relacional, está en la gente común de ORM? Dejemos
esta guerra santa a Yegor Bugaenko con sus camaradas. Y toda esta historia del siglo pasado,
según el tío Bob, no debería preocuparnos .
Por supuesto, vale la pena mencionar que la "bolsa con bytes" (Robert Martin "Pure Architecture") se puede serializar y soltar en un archivo o insertar en otra secuencia adecuada. Pero, en primer lugar, nos limitará inmediatamente en el idioma, y en segundo lugar, ahora solo nos preocuparemos por almacenarlos en el DBMS.
Hay una agradable excepción a estos altibajos con las bolsas de bytes: el DBMS Intersystems Caché (y ahora la plataforma de datos InterSystems IRIS). Este es probablemente el único DBMS en el mundo que no oculta lo obvio del desarrollador e incluso va más allá: lo libera a uno de pensar "cómo almacenarlo todo correctamente". Es suficiente decir que la clase continúa con el género Persistente y el punto está en el sombrero,
es decir, en los globales (¡no debe confundirse con las variables globales!).
Se pueden almacenar todos los tipos de datos, incluidos los flujos de caracteres y binarios. Aquí hay un ejemplo simple:
// - // : , , , , Class FW.Events Extends %Persistent { Property "My name" As %String; } // // «» set haJS = ##class(FW.Events).%New() // write haJS.%Id()
Además, y esto es maravilloso, puede comunicarse con objetos almacenados no solo en ObjectScript, nativo de Caché, sino también en recuperarlos y guardarlos directamente en Python, Java, JavaScript, C ++, C #, Perl. E incluso, oh horror :). También es posible obtener información de los mismos objetos directamente a través de consultas SQL, y también es posible llamar a sus propios métodos en los objetos. Más precisamente, los métodos en este caso por sí mismos (y la palabra mágica SqlProc) se convierten en procedimientos almacenados. Toda la magia ya está bajo el capó del Caché DBMS.
¿Cómo obtener acceso de prueba gratuito a Intersystems Caché DBMS?
¡Esto es absolutamente real, no importa lo que digan los idiomas malvados! :) Puede descargar e instalar la versión completa de Caché para un solo usuario aquí (deberá registrarse de forma gratuita). Las compilaciones están disponibles para MacOS, Windows y Linux.
Es más conveniente trabajar con código ObjectScript y acceder directamente al servidor Caché DBMS (y también a la plataforma InterSystems IRIS) utilizando el Atelier IDE, que está basado en Eclipse. Todas las instrucciones de
descarga e instalación están
aquí .
Para quienes es más conveniente y familiar, puede usar el código Visual Studio cómodo y simple, que lo complementa con el complemento ObjectScript desarrollado por la comunidad.
Y ahora algunos ejemplos prácticos. Intentemos crear un par de objetos relacionados y trabajar con ellos en ObjectScript y Python. La integración con otros idiomas se implementa de manera muy similar. Python se elige por razones de "máxima afinidad" con ObjectScript: ambos lenguajes son programables, admiten OOP y no tienen una escritura fuerte :)
Para obtener ideas a modo de ejemplo, recurrimos a los vigorosos proyectos de Khabarovsk (¡no confundir con Khabrovsk!) Del "Marco de reunión". El código fuente ideológico se encuentra en
github.com/Hajsru/framework-weekend y nuestro código fuente es más bajo en el texto.
Un matiz importante para los usuarios de macOS. Al iniciar los módulos de soporte para Python, debe recordar que debe especificar la ruta DYLD_LIBRARY_PATH al directorio donde instaló Caché. Por ejemplo, así:
export DYLD_LIBRARY_PATH = / application / Cache / bin: $ DYLD_LIBRARY_PATH
Esto se indica específicamente en la documentación.
Creamos clases almacenadas en ObjectScript
Entonces vamos. Las clases en Caché serán muy simples. Puede prescindir de un IDE: copie el código de clase directamente a través del portal de su instancia de la plataforma Caché (sí, Caché DBMS está lejos de ser solo un DBMS): Navegador del sistema> Clases> Importar (USUARIO del espacio de nombres).
Después de guardar, los objetos aparecerán en los globos con nombres que coinciden con los nombres de las clases correspondientes. También busque en el portal de administración de Caché: Navegador del sistema> Globals (USUARIO del espacio de nombres).
// , , Class FW.Event Extends %Persistent { Property title as %String; Property description as %String; Property date as %Date; Property visitors as list of FW.Attendee; } // / Class FW.Attendee Extends %Persistent { Property name As %String; }
Acceso a objetos en Caché desde Python
Primero, conéctese a la base de datos Caché DBMS. Repetimos como
en la documentación .
Solo un hecho útil para trabajar. Gratis, también es una versión de entrenamiento del Caché DBMS, que le permitirá hacer todo lo que está disponible en la versión totalmente funcional, pero solo permite dos conexiones activas. Por lo tanto, al mismo tiempo, no será posible mantener una conexión desde el IDE e intentar ejecutar otro código para interactuar con el servidor. La solución más simple que se encuentra es cerrar el IDE mientras se ejecuta el código Python.
Y ahora crearemos una base de datos de objetos de eventos de TI y sus participantes. Muy muy simple. El primero es crear una clase para registrar y almacenar información sobre el participante del evento. Para simplificar la clase, solo el nombre del miembro.
Como puede ver, utilizamos funciones de contenedor listas para usar para métodos de acceso a los campos de objetos en Caché: set y en los parámetros pasamos el nombre de la propiedad entre comillas y openid con el nombre del paquete y la clase. Acerca de una función get similar, hay ejemplos a continuación. Para acceder a cualquier otro método, incluidos los heredados por la clase de sus antepasados, use la función run_obj_method () con el nombre del método y los parámetros de llamada, si es necesario.
La magia más importante en la línea: self.att.run_obj_method ("% Save", [])
Así es como tenemos la capacidad de guardar objetos con referencia directa y sin la necesidad de usar bibliotecas y marcos adicionales, como los ORM ubicuos y desagradables.
Además, dada la naturaleza orientada a objetos de ObjectScript, junto con los métodos de su clase (en nuestro ejemplo, no los hicimos), obtenemos una bonificación del acceso de Python a todo el conjunto de métodos heredados de la clase Persistente y sus antepasados.
Aquí está la lista completa , si eso.
Crea el primer miembro:
att = Attendee() att.new("")
Después de ejecutar este código, aparecerá un global en la base de datos con el nombre FW.AttendeeD y el contenido del objeto recién guardado como en la captura de pantalla:

Después de guardar, este objeto tiene su propia identificación (con el número 1). Por lo tanto, puede cargarlo en nuestro programa usando esta identificación:
att = Attendee() att.use(1) print (att.att.get("name"))
Y ahora, nuevamente conociendo la identificación, si es necesario, puede eliminar el objeto de la base de datos de participantes:
att = Attendee() att.use(1) att.clean()
Compruebe, después de ejecutar este ejemplo, el registro sobre el objeto debe desaparecer en el global. Aunque los datos descargados aún permanecen "en la memoria" de su objeto hasta que el programa finalice.
Vamos a dar el siguiente paso. Crea los registros de eventos reales.
La estructura de la clase es casi la misma que la anterior para el miembro de la clase. Lo más importante, ha aparecido un método para agregar participantes a la lista de participantes para este evento addAttendee (att).
Intentamos crear un registro de objeto sobre un nuevo evento y guardarlo en la base de datos:
haJS = Event() haJS.new("haJS", " ", "2019-01-19")
Debería resultar algo como esto (tenga en cuenta que la fecha se convierte automáticamente al formato ObjectScript y cuando se vuelve a cargar en el objeto Python, volverá al formato original):

Queda por agregar al participante al evento:
Entonces, estos ejemplos muestran que no es necesario pensar al mismo tiempo sobre su modelo de datos y su esquema de almacenamiento tabular. Puede usar herramientas más obvias para sus tareas.
Las instrucciones detalladas para conectar y usar Caché con Python y otros idiomas están siempre
disponibles para usted en la documentación y en el portal de la comunidad de desarrolladores de InterSystems; esto no es menos de 5,000 miembros de
community.intersystems.comAyuda: InterSystems Caché multimodel DBMS sigue siendo el líder mundial permanente en bases de datos de objetos
