Modelado de datos: el modelo de David Nuescheler

Origen

Los siguientes detalles son ideas y comentarios expresados por David Nuescheler.

David fue cofundador y director de tecnología de Day Software AG, un proveedor líder de software de gestión de contenido global e infraestructura de contenido, adquirido por Adobe en 2010. Ahora es miembro y vicepresidente de tecnología empresarial en Adobe y también dirige el desarrollo de JSR-170, la interfaz de programación de aplicaciones (API) del repositorio de contenido Java (JCR), el estándar tecnológico para la administración de contenido.

También se pueden ver más actualizaciones en https://wiki.apache.org/jackrabbit/DavidsModel.

Introducción de David

En varias discusiones encontré que los desarrolladores están un poco incómodos con las características y funcionalidades presentadas por JCR cuando se trata de modelado de contenido. Todavía no hay ninguna guía y poca experiencia sobre cómo modelar contenido en un repositorio y por qué un modelo de contenido es mejor que otro.

Mientras que en el mundo relacional la industria del software tiene mucha experiencia en cómo modelar datos, todavía estamos en las primeras etapas para el espacio del repositorio de contenido.

Me gustaría empezar a llenar este vacío expresando mis opiniones personales sobre cómo se debe modelar el contenido, con la esperanza de que esto algún día podría graduarse en algo más significativo para la comunidad de desarrolladores, que no es solo "mi opinión", sino algo que es más aplicable en general. Así que consideremos esto como mi primera puñalada que evoluciona rápidamente.

NOTA

Descargo de responsabilidad: estas directrices expresan mis puntos de vista personales, a veces controvertidos. Espero con interés debatir estas directrices y perfeccionarlas.

Siete reglas sencillas

#1 de regla: primero los datos y después la estructura. Tal vez.

Explicación

Recomiendo no preocuparse por una estructura de datos declarada en un sentido rojo. Inicialmente.

Aprende a amar a nt:unstructured (& amigos) en el desarrollo.

Creo que Stefano lo resume todo.

Mi conclusión: La estructura es costosa y en muchos casos es totalmente innecesario declarar explícitamente la estructura al almacenamiento subyacente.

Existe un contrato implícito sobre la estructura que la aplicación utiliza de forma inherente. Supongamos que almacenamos la fecha de modificación de una publicación de blog en una propiedad lastModified. Mi aplicación sabrá automáticamente volver a leer la fecha de modificación de esa misma propiedad, no es necesario declararla explícitamente.

Solo deben aplicarse otras restricciones de datos, como obligatorias o restricciones de tipo y valor, cuando sea necesario por motivos de integridad de los datos.

Ejemplo

El ejemplo anterior de uso de una lastModified La propiedad de fecha en, por ejemplo, el nodo "publicación de blog", en realidad no significa que haya una necesidad de un tipo de nodo especial. Definitivamente me vendría bien nt:unstructured para los nodos de mi entrada de blog al menos inicialmente. Ya que en mi aplicación de blogueo todo lo que voy a hacer es mostrar la fecha lastModified de todos modos (posiblemente "ordenar por") apenas me importa si es una fecha en absoluto. Dado que confío implícitamente en mi aplicación de escritura de blogs para poner una "fecha" de todos modos, no hay realmente necesidad de declarar la presencia de una lastModified fecha en forma de tipo de nodo.

Regla #2: Controle la jerarquía de contenido, no permita que ocurra.

Explicación

La jerarquía de contenido es un recurso muy valioso. Así que no dejes que suceda, diseña. Si no tiene un nombre "bueno" y legible en lenguaje natural para un nodo, probablemente sea algo que debería reconsiderar. Los números arbitrarios rara vez son un "buen nombre".

Si bien puede ser extremadamente fácil poner rápidamente un modelo relacional existente en un modelo jerárquico, uno debe poner algo de pensamiento en ese proceso.

En mi experiencia, si se piensa en el control de acceso y la contención, normalmente son buenos controladores para la jerarquía de contenido. Piense en ello como si fuera su sistema de archivos. Puede incluso utilizar archivos y carpetas para modelarlo en el disco local.

Personalmente, prefiero las convenciones de jerarquía sobre el sistema de escritura de nodos en muchos casos inicialmente, e introduzco la escritura más tarde.

PRECAUCIÓN

La forma en que se estructura un repositorio de contenido también puede afectar al rendimiento. Para obtener el mejor rendimiento, el número de nodos secundarios adjuntos a nodos individuales en un repositorio de contenido no debe exceder generalmente de 1000.

Consulte ¿Cuántos datos puede gestionar CRX? para obtener más información.

Ejemplo

Yo modelaría un sistema simple de blogueo de la siguiente manera. Tenga en cuenta que al principio ni siquiera me importan los tipos de nodos respectivos que utilizo en este punto.

/content/myblog
/content/myblog/posts
/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping

/content/myblog/comments/iphone_shipping/i_like_it_too
/content/myblog/comments/iphone_shipping/i_like_it_too/i_hate_it

Creo que una de las cosas que se hacen evidentes es que todos entendemos la estructura del contenido basado en el ejemplo sin más explicaciones.

Lo que puede ser inesperado inicialmente es por qué no almacenaría los "comentarios" con el "post", que se debe al control de acceso que me gustaría aplicar de una manera razonablemente jerárquica.

Con el modelo de contenido anterior, puedo permitir fácilmente que el usuario "anónimo" "cree" comentarios, pero mantener al usuario anónimo en modo de solo lectura para el resto del espacio de trabajo.

#3 de reglas: Los espacios de trabajo son para clone(), merge() y update().

Explicación

Si no utiliza el clone(), merge() o update() en su aplicación, un solo espacio de trabajo es probablemente el camino a seguir.

"Nodos correspondientes" es un concepto definido en la especificación JCR. Básicamente, se reduce a nodos que representan el mismo contenido, en diferentes espacios de trabajo.

JCR introduce el concepto muy abstracto de espacios de trabajo, lo que deja a muchos desarrolladores sin saber qué hacer con ellos. Me gustaría proponer poner su uso de espacios de trabajo a lo siguiente para probar.

Si tiene una superposición considerable de nodos "correspondientes" (esencialmente los nodos con el mismo UUID) en varios espacios de trabajo, probablemente haga un buen uso de los espacios de trabajo.

Si no hay superposición de nodos con el mismo UUID, probablemente esté abusando de los espacios de trabajo.

Los espacios de trabajo no deben utilizarse para el control de acceso. La visibilidad del contenido para un grupo particular de usuarios no es un buen argumento para separar cosas en diferentes espacios de trabajo. JCR incluye "Control de acceso" en el repositorio de contenido para proporcionarlo.

Los espacios de trabajo son el límite para referencias y consultas.

Ejemplo

Utilice espacios de trabajo para cosas como:

  • v1.2 del proyecto frente a a v1.3 del proyecto
  • un estado de "desarrollo", "control de calidad" y "publicado" de contenido

No utilice espacios de trabajo para tareas como las siguientes:

  • directorios principales del usuario
  • contenido distinto para distintas audiencias de destino como público, privado, local, …
  • bandejas de entrada de correo para distintos usuarios

Regla #4: Tenga cuidado con los hermanos del mismo nombre.

Explicación

Aunque se han introducido los hermanos del mismo nombre (SNS) en las especificaciones para permitir la compatibilidad con estructuras de datos diseñadas y expresadas a través de XML y, por lo tanto, son extremadamente valiosas para JCR, los SNS incluyen una carga y complejidad sustanciales para el repositorio.

Cualquier ruta al repositorio de contenido que contenga un SNS en uno de sus segmentos de ruta se vuelve mucho menos estable; si se elimina o reordena un SNS, afecta a las rutas de todos los demás SNS y sus elementos secundarios.

Para importar XML o interactuar con SNS XML existente puede ser necesario y útil, pero nunca he utilizado SNS, y nunca lo haré en mis modelos de datos de "campo verde".

Ejemplo

Uso

/content/myblog/posts/what_i_learned_today
/content/myblog/posts/iphone_shipping

en lugar de

/content/blog[1]/post[1]
/content/blog[1]/post[2]

Regla #5: Referencias consideradas perjudiciales.

Explicación

Las referencias implican integridad referencial. Considero importante comprender que las referencias no solo añaden un coste adicional para el repositorio que gestiona la integridad referencial, sino que también son costosas desde el punto de vista de la flexibilidad del contenido.

Personalmente, me aseguro de usar solo referencias cuando realmente no puedo lidiar con una referencia colgada y, de lo contrario, uso una ruta, un nombre o un UUID de cadena para hacer referencia a otro nodo.

Ejemplo

Supongamos que permito "referencias" de un documento a) a otro documento b). Si modelo esta relación con propiedades de referencia, significa que los dos documentos están vinculados en un nivel de repositorio. No puedo exportar/importar el documento (a) individualmente, ya que es posible que el destino de la propiedad de referencia no exista. Otras operaciones como combinar, actualizar, restaurar o clonar también se ven afectadas.

Por lo tanto, modelaría esas referencias como "referencias débiles" (en JCR v1.0, esto esencialmente se reduce a propiedades de cadena que contienen el uuid del nodo de destino) o simplemente utilizaría una ruta. A veces, la ruta es más significativa para empezar.

Creo que hay casos de uso en los que un sistema no puede funcionar si una referencia está colgando, pero no puedo encontrar un buen ejemplo "real" pero simple de mi experiencia directa.

Regla #6: Los archivos son archivos.

Explicación

Si un modelo de contenido expone algo que incluso de forma remota olores como un archivo o una carpeta que intento usar (o ampliar desde) nt:file, nt:folder y nt:resource.

En mi experiencia, muchas aplicaciones genéricas permiten la interacción con nt:folder y nt:files implícitamente y saben cómo manejar y mostrar esos eventos si están enriquecidos con metainformación adicional. Por ejemplo, una interacción directa con implementaciones de servidor de archivos como CIFS o WebDAV ubicadas encima de JCR quedan implícitas.

Creo que como buena regla general se podría utilizar lo siguiente: Si necesita almacenar el nombre de archivo y el tipo MIME, entonces nt:file/ nt:resource es un muy buen partido. Si puede tener varios "archivos", nt:folder es un buen lugar para almacenarlos.

Si necesita añadir información meta para el recurso, por ejemplo, una propiedad "author" o "description", amplíe nt:resource no el nt:file. Rara vez extiendo nt:file y con frecuencia extiendo nt:resource.

Ejemplo

Supongamos que alguien desea cargar una imagen en una entrada de blog en:

/content/myblog/posts/iphone_shipping

y tal vez la reacción intestinal inicial sería agregar una propiedad binaria que contenga la imagen.

Aunque ciertamente hay buenos casos de uso para utilizar solo una propiedad binaria (digamos que el nombre es irrelevante y el tipo MIME está implícito) en este caso recomendaría la siguiente estructura para mi ejemplo de blog.

/content/myblog/posts/iphone_shipping/attachments [nt:folder]
/content/myblog/posts/iphone_shipping/attachments/front.jpg [nt:file]
/content/myblog/posts/iphone_shipping/attachments/front.jpg/jcr:content [nt:resource]

Regla #7: Los identificadores son malvados.

Explicación

En las bases de datos relacionales, los ID son un medio necesario para expresar relaciones, por lo que las personas también tienden a utilizarlos en modelos de contenido. Principalmente por las razones equivocadas a través de.

Si el modelo de contenido está lleno de propiedades que terminan en "Id", probablemente no esté aprovechando la jerarquía correctamente.

Es cierto que algunos nodos necesitan una identificación estable a lo largo de su ciclo de vida. Mucho menos de lo que se podría pensar. mix: referenciable proporciona un mecanismo de este tipo integrado en el repositorio, por lo que no es necesario idear un medio adicional para identificar un nodo de forma estable.

Tenga también en cuenta que los elementos se pueden identificar por ruta, y tanto como los "enlaces simbólicos" tienen más sentido para la mayoría de los usuarios que los enlaces duros en un sistema de archivos unix, una ruta tiene sentido para la mayoría de las aplicaciones para hacer referencia a un nodo de destino.

Más importante aún, lo es mezclar: referenciable, lo que significa que se puede aplicar a un nodo en el momento en que realmente necesita hacer referencia a él.

Por lo tanto, supongamos que simplemente porque desee poder hacer referencia a un nodo de tipo "Documento" no significa que el tipo de nodo "Documento" tenga que extenderse desde mix:referenceable de forma estática, ya que se puede agregar dinámicamente a cualquier instancia del "Documento".

Ejemplo

Uso:

/content/myblog/posts/iphone_shipping/attachments/front.jpg

en lugar de:

[Blog]
-- blogId
-- author
[Post]
-- postId
-- blogId
-- title
-- text
-- date
[Attachment]
-- attachmentId
-- postId
-- filename
+ resource (nt:resource)

En esta página