Patrones de diseño de XML Schema
Indice
- Patrones de diseño de XML Schema
Introducción
En este tutorial vamos a analizar y mostrar con ejemplos los cuatro principales patrones de diseño de XML Schema: Russian Doll, Salami Slice, Venetian Blind y Garden of Eden.
Existen muchas maneras de diseñar XML Schemas válidos según la definición del consorcio W3C, pero si los queremos utilizar junto a los descriptores de contratos de servicios web (WSDL, Web Service Description Languaje), tendrán que cumplir además con las especificaciones W3C WSDL v1.1 para la descripción de contratos de web services, y WS-I Basic Profile (BP V1.1) con el propósito de cumplir unos mínimos de interoperabilidad y asegurar la compatibilidad en las invocaciones entre los mismos.
Las buenas prácticas que enseñamos a continuación giran en torno a la existencia de:
- Declaración de elementos (element) globales (global se entiende como hijos directos del nodo raíz <schema>) o locales (anidados o hijos de otros nodos que no sean el raíz)
- Ídem para con la declaración de tipos definidos (complexType ó simpleType)
La combinación de los binomios elementos/tipos-locales/globales potenciarán la facilidad de desarrollo en unos casos y la reutilización en otros.
Ejemplo: definición de empresa, razón social y domicilio
El ejemplo práctico de este tutorial consiste en definir con XML Schema y los cuatro patrones, los siguientes tipos de datos:
- Tipo de dato empresa: constará de los subtipos:
- razonSocial:
- nombre: tipo cadena
- CIF: tipo cadena
- domicilio:
- calle: tipo cadena
- numero: tipo entero
- piso: tipo entero
- razonSocial:
Para ello nos vamos a ayudar del IDE NetBeans Enterprise, que se distribuye con OpenESB. Para más información sobre descarga e instalación se puede consultar el tutorial: OpenESB 2.1. Instalación e introducción al entorno.
Creamos en Netbeans un nuevo proyecto web con nombre AplicacionWeb:
Nuevo proyecto web
Así pues creamos dentro del proyecto un nuevo documento XML Schema con nombre empresaSchema y espacio de nombres: http://tutorial.adictosaltrabajo.com/schema/empresaSchema
Patrón de diseño Russian Doll
El patrón de diseño Russian Doll consiste en la definición de un único elemento global, y el resto de elementos y los tipos están definidos en su interior, como nodos hijos (de ahí el nombre del patrón Matrioska, Muñeca Rusa). En este caso, el nodo padre será empresa, y como nodos hijos y hermanos: razonSocial y domicilio:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" xmlns:tns="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" elementFormDefault="qualified"> <xsd:element name="empresa"> <xsd:complexType> <xsd:sequence> <xsd:element name="razonSocial"> <xsd:complexType> <xsd:sequence> <xsd:element name="nombre" type="xsd:string"></xsd:element> <xsd:element name="CIF" type="xsd:string"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="domicilio"> <xsd:complexType> <xsd:sequence> <xsd:element name="calle" type="xsd:string"></xsd:element> <xsd:element name="numero" type="xsd:int"></xsd:element> <xsd:element name="piso" type="xsd:int"></xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> |
El código anterior deberá ser el que contenga nuestra primera versión de empresaSchema.xsd. Podemos copiar el código y pegarlo en el editor, o bien diseñarlo gráficamente:
Patrón Russian Doll de XML Schema en NetBeans
Disponer de esta estructura declarativa, ¿qué implica?:
- Visibilidad: sólo existe un elemento global visible a otros esquemas (y al mismo) y el resto son locales, es decir, ocultos y no reutilizables. Sólo el elemento empresa se puede reutilizar
- De todos los patrones, esta estructura de XML Schema es la que menos se puede extender
- Alta cohesión: el diseño y los datos relacionados está autocontenidos bajo el elemento global. Tiene la ventaja de no existir riesgo de efectos laterales si los subtipos complejos fuesen visibles
- El XML Schema no es válido para formar un documento WSDL de estilo RPC-literal, ya que a nivel global no hay definido ningún tipo, según requiere WS-I Basic Profile (WS-I BP 1.1, sección 4.4. Messages, subsección 4.4.1. Bindign and parts, regla R2203): An rpc-literal binding in a DESCRIPTION MUST refer, in its soapbind:body element(s), only to wsdl:part element(s) that have been defined using the type attribute.
Patrón de diseño Salami Slice
El patrón de diseño Salami Slice consiste en dividir la estructura del patrón anterior en partes más pequeñas y exponerlas a nivel global. Las definiciones locales de elementos se extraen de su localización y se convierten en globales, es decir, se sitúan a nivel raíz del documento; y en su lugar original se establecen referencias a éstos.
Para crear este patrón automáticamente partiendo del empresaSchema.xml definido en el patrón Russian Doll, pulsamos con el botón derecho sobre el nombre del fichero empresaSchema.xml | Apply Design Pattern…:
Aplicar patrón de diseño XML Schema con NetBeans
y en el asistente seleccionamos la creación de múltiples elementos globales, pero sin la creación de tipos. De paso el asistente nos indica cuál es el patrón del documento actual y el patrón que estamos aplicando:
Conversión al patrón Salami Slice
Pulsamos en Finish y vemos cómo todos los tipos están definidos a nivel raíz del documento; y allí donde son utilizados, se les referencia a través de su namespace y nombre:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" xmlns:tns="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" elementFormDefault="qualified"> <xsd:element name="empresa"> <xsd:complexType> <xsd:sequence> <xsd:element ref="tns:razonSocial"/> <xsd:element ref="tns:domicilio"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="razonSocial"> <xsd:complexType> <xsd:sequence> <xsd:element ref="tns:nombre"/> <xsd:element ref="tns:CIF"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="nombre" type="xsd:string"/> <xsd:element name="CIF" type="xsd:string"/> <xsd:element name="domicilio"> <xsd:complexType> <xsd:sequence> <xsd:element ref="tns:calle"/> <xsd:element ref="tns:numero"/> <xsd:element ref="tns:piso"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:element name="calle" type="xsd:string"/> <xsd:element name="numero" type="xsd:int"/> <xsd:element name="piso" type="xsd:int"/> </xsd:schema> |
Gráficamente:
Patrón Salami Slice de XML Schema
Algunas implicaciones de un XML Schema bajo esta estructura son:
- Toda definición de elementos es global, y de tipos local
- Los elementos, al ser globales, pueden reutilizarse dentro y fuera del documento. Los tipos serán ocultos y no reutilizables
- Este patrón añade más complejidad al documento, ya que existe más de un elemento raíz.
- Existe riesgo de efectos laterales, al modificar un elemento global que es dependencia de otra partes del documento
- Con relación al patrón Russian Doll, el patrón Salami Slice facilita la reutilización de componentes, pero añade complejidad al espacio de nombres expuesto al haber más elementos
- Con respecto a su uso en documentos WSDL con binding RPC-literal, tenemos el mismo problema que con el patrón Russian Doll
Como nota al margen, comentar que en lenguaje anglosajón, el sustantivo salami puede usarse para aportar el significado de descomposición, separación, divide y vencerás: salami slicing, salami attack, salami tactics aka salami-slice strategy, salami technique…
Patrón de diseño Venetian Blind
El patrón de diseño Venetian Blind consiste en la existencia de un único elemento global en el XSD, el resto de elementos son locales. Sin embargo ahora todos los tipos se declaran a nivel raíz y son referenciados desde otros tipos o elementos que los utilicen.
La combinación que hemos de aplicar al asistente de patrones de diseño de Netbeans es la creación de un único elemento global y la creación de tipos:
Parámetros para aplicar el patrón Venetian Blind
El código será en este caso:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" xmlns:tns="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" elementFormDefault="qualified"> <xsd:element name="empresa"> <xsd:complexType> <xsd:sequence> <xsd:element name="razonSocial" type="tns:razonSocialType"/> <xsd:element name="domicilio" type="tns:domicilioType"/> </xsd:sequence> </xsd:complexType> </xsd:element> <xsd:complexType name="razonSocialType"> <xsd:sequence> <xsd:element name="nombre" type="xsd:string"/> <xsd:element name="CIF" type="xsd:string"/> </xsd:sequence> </xsd:complexType> <xsd:complexType name="domicilioType"> <xsd:sequence> <xsd:element name="calle" type="xsd:string"/> <xsd:element name="numero" type="xsd:int"/> <xsd:element name="piso" type="xsd:int"/> </xsd:sequence> </xsd:complexType> </xsd:schema> |
Gráficamente podemos comprobar que se han creado tipos globales, referenciados por los elementos:
Patrón Venetian Blind de XML Schema
Por tanto las características de este patrón incluyen:
- Un único elemento global, cualquier otro deberá ser local. Todos los tipos son globales
- Orientado a reutilizar tipos definidos en XML Schema
- Si queremos utilizar un documento WSDL con binding Document-literal, debemos tener en cuenta que en la definición de partes de un mensaje sólo pueden utilizarse elementos, no tipos: (WS-I BP 1.1, sección 4.4. Messages, subsección 4.4.1. Bindign and parts, regla R2204): A document-literal binding in a DESCRIPTION MUST refer, in each of its soapbind:body element(s), only to wsdl:part element(s) that have been defined using the element attribute.
- Alto acoplamiento entre elementos y tipos
Patrón de diseño Garden of Eden
El patrón Garden of Eden es una combinación de los patrones Salami Slice y Venetian Blind, puesto que tanto los elementos como los tipos se definen a nivel global en el namespace. Este patrón es el más reutilizable de todos al exponer todos los tipos y elementos a los clientes del Schema.
La combinación que hemos de aplicar al asistente de patrones de diseño de Netbeans es la creación de múltiples elementos globales y la creación de tipos:
Parámetros para aplicar el patrón Garden of Eden
El código se refactoriza y queda de la manera mostrada a continuación:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" xmlns:tns="http://tutorial.adictosaltrabajo.com/schema/empresaSchema" elementFormDefault="qualified"> <xsd:element name="empresa" type="tns:empresaType"/> <xsd:complexType name="empresaType"> <xsd:sequence> <xsd:element ref="tns:razonSocial"/> <xsd:element ref="tns:domicilio"/> </xsd:sequence> </xsd:complexType> <xsd:element name="razonSocial" type="tns:razonSocialType"/> <xsd:complexType name="razonSocialType"> <xsd:sequence> <xsd:element ref="tns:nombre"/> <xsd:element ref="tns:CIF"/> </xsd:sequence> </xsd:complexType> <xsd:element name="nombre" type="xsd:string"/> <xsd:element name="CIF" type="xsd:string"/> <xsd:element name="domicilio" type="tns:domicilioType"/> <xsd:complexType name="domicilioType"> <xsd:sequence> <xsd:element ref="tns:calle"/> <xsd:element ref="tns:numero"/> <xsd:element ref="tns:piso"/> </xsd:sequence> </xsd:complexType> <xsd:element name="calle" type="xsd:string"/> <xsd:element name="numero" type="xsd:int"/> <xsd:element name="piso" type="xsd:int"/> </xsd:schema> |
El aspecto visual del diseñador representará el XML Schema con los siguientes nodos:
Patrón Garden of Eden de XML Schema
Sus características generales son :
- Todos los elementos y tipos son declarados globales
- Es el patrón que maximiza la reutilización
- El namespace es más completo pero también más complejo
- Es el más adecuado para su utilización indistinta en documentos WSDL de estilo RPC y Document-literal
Conclusión
En el momento de diseñar XML Schemas y tener el ‘folio en blanco’ delante, hay dos preguntas que nos vienen a la mente:
- Una determinada entidad, ¿la declaro como elemento o la defino como un tipo?
- Este elemento o tipo, ¿lo declaro global o local en el documento?
Para formar un criterio al respecto de esas preguntas, preguntémonos:
- ¿Qué grado de reutilización de entidades definidas voy a necesitar?
- ¿Voy a necesitar extender el XML Schema?
- ¿Qué grado de acoplamiento u ocultación de entidades considero adecuado para mi diseño?
- En caso de utilizarlo con documentos WSDL en servicios web, ¿mi diseño del XML Schema introduce limitaciones a los estilos RPC o Document del WSDL, o de referencia a entidades en los wsdl:part?
Esperamos finalmente que este documento sirva como punto de partida para fomentar el uso de patrones de diseño en nuestros proyectos.