tesis-persistencia-maestria

159
UNIVERSIDAD FRANCISCO GAVIDIA UNIDAD DE POSTGRADOS “Desarrollo de un Motor de Persistencia para la Plataforma Microsoft .Net” TRABAJO DE GRADUACION PREPARADO PARA LA UNIDAD DE POSTGRADOS PARA OPTAR AL GRADO DE: MASTER EN INFORMATICA APLICADA A REDES PRESENTADO POR: Francisco José Fernández Escobar Ernesto Armando Zavaleta William Alexie Rebolone DICIEMBRE – 2006 SAN SALVADOR – EL SALVADOR – CENTROAMERICA

Upload: michael-lewis

Post on 10-Aug-2015

75 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Tesis-persistencia-maestria

UNIVERSIDAD FRANCISCO GAVIDIA UNIDAD DE POSTGRADOS

“Desarrollo de un Motor de Persistencia para

la Plataforma Microsoft .Net”

TRABAJO DE GRADUACION PREPARADO PARA LA

UNIDAD DE POSTGRADOS

PARA OPTAR AL GRADO DE:

MASTER EN INFORMATICA APLICADA A REDES

PRESENTADO POR:

Francisco José Fernández Escobar Ernesto Armando Zavaleta William Alexie Rebolone

DICIEMBRE – 2006

SAN SALVADOR – EL SALVADOR – CENTROAMERICA

Page 2: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 2 de 159

Tabla de Contenidos

I. INTRODUCCIÓN .................................................................................................................................. 4

1.1. OBJETIVOS. ...................................................................................................................................... 5 1.2. ALCANCES ....................................................................................................................................... 6 1.3. LIMITACIONES.................................................................................................................................. 6 1.4. SUPOSICIONES Y DEPENDENCIAS ..................................................................................................... 7 1.5. A QUIEN ESTA DIRIGIDO ESTE DOCUMENTO...................................................................................... 7 1.6. ORGANIZACIÓN DEL DOCUMENTO. .................................................................................................. 8

II. JUSTIFICACIÓN DEL TEMA............................................................................................................. 9

2.1 ANTECEDENTES ............................................................................................................................... 9 2.2 MOTORES DE PERSISTENCIA Y EL FRAMEWORK .NET.................................................................... 11 2.3 EL PORQUE DE LA CREACIÓN DE UN MOTOR DE PERSISTENCIA PARA .NET. .................................... 12

III. FUNDAMENTOS TEORICOS ...................................................................................................... 13

3.1 PROGRAMACIÓN ORIENTADA A OBJETOS....................................................................................... 13 3.1.1 Historia y Evolución................................................................................................................. 13 3.1.2 Ventajas de la OO..................................................................................................................... 14 3.1.3 Características de los Objetos.................................................................................................. 15

3.2 PATRONES DE DISEÑO .................................................................................................................... 21 3.2.1 Historia..................................................................................................................................... 22 3.2.2 Conceptos Clave ....................................................................................................................... 23 3.2.3 Tipos de Patrones ..................................................................................................................... 23 3.2.4 Patrones de Acceso a Datos ..................................................................................................... 25 3.2.5 El patrón Singleton................................................................................................................... 27 3.2.6 El Patrón Factory..................................................................................................................... 28 3.2.7 El Patrón Abstract Factory ...................................................................................................... 32 3.2.8 El Patron Data Accessors......................................................................................................... 34 3.2.9 Patron DAO (Data Access Object)........................................................................................... 34

3.3 BASES DE DATOS ORIENTADAS A OBJETOS.................................................................................... 38 3.3.1 El Concepto de Orientación a Objetos ..................................................................................... 40 3.3.2 El Modelo de Datos Orientado a Objetos ................................................................................ 41 3.3.3 El modelo Estándar ODMG ..................................................................................................... 46

3.4 SISTEMAS OBJETOS-RELACIONALES .............................................................................................. 49 3.4.1 Diferencia entre los tres sistemas (RDBMS, ODBMS, ORDBMS)........................................... 50

3.5 MOTORES DE PERSISTENCIA........................................................................................................... 53 3.5.1 Opciones para motores de persistencia.................................................................................... 55

3.6 PROCESO DE DISEÑO Y DESARROLLO DE UN PROYECTO DE SOFTWARE ........................................ 56 3.6.1 CMM......................................................................................................................................... 56 3.6.2 El RUP y el Proceso Unificado ................................................................................................ 65 3.6.3 Microsoft Solution Framework................................................................................................. 67

3.7 MICROSOFT .NET FRAMEWORK ..................................................................................................... 69 3.7.1 Características ......................................................................................................................... 71 3.7.2 Arquitectura.............................................................................................................................. 75 3.7.3 ADO .Net 2.0 ............................................................................................................................ 83

IV. SOLUCIÓN PROPUESTA ............................................................................................................. 90

4.1 MODELADO DE LA SOLUCIÓN ........................................................................................................ 90 4.1.1 Consideraciones Iniciales......................................................................................................... 90 4.1.2 Namespaces y Assemblies......................................................................................................... 92

4.2 SINCRONIZACIÓN ESTRUCTURA ER Y MODELO DE DOMINIO ........................................................ 93 4.2.1 Planteamiento del Requerimiento............................................................................................. 93 4.2.2 Diseño de la Solución ............................................................................................................... 93

Page 3: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 3 de 159

4.2.3 Construcción de la Solución..................................................................................................... 98 4.3 GENERACIÓN DE OPERACIONES TRANSACCIONALES ...................................................................... 99

4.3.1 Planteamiento del Requerimiento............................................................................................. 99 4.3.2 Diseño de la Solución ............................................................................................................... 99 4.3.3 Construcción de la Solución................................................................................................... 103

4.4 CONSTRUCCIÓN Y CARGAS DE LOS OBJETOS ............................................................................... 108 4.4.1 Planteamiento del Requerimiento........................................................................................... 108 4.4.2 Diseño de la Solución ............................................................................................................. 108 4.4.3 Construcción de la Solución................................................................................................... 109

4.5 ACCESO INDEPENDIENTE DEL SISTEMA RDBMS ......................................................................... 112 4.5.1 Planteamiento del Requerimiento........................................................................................... 112 4.5.2 Diseño de la Solución ............................................................................................................. 113 4.5.3 Construcción de la Solución................................................................................................... 115

4.6 CONFIGURACIÓN Y PARAMETRIZACIÓN ....................................................................................... 117 4.6.1 Planteamiento del Requerimiento........................................................................................... 117 4.6.2 Diseño de la Solución ............................................................................................................. 118 4.6.3 Construcción de la Solución................................................................................................... 118

V. RESULTADOS Y VERIFICACION EXPERIMENTAL ............................................................... 120

5.1 OBJETIVO DE LAS PRUEBAS.......................................................................................................... 120 5.2 DEFINICIÓN DEL REQUERIMIENTO................................................................................................ 120 5.3 MODELADO Y DISEÑO DE LA SOLUCIÓN ...................................................................................... 121

5.3.1 Modelo de Dominio. ............................................................................................................... 121 5.3.2 Modelo de Acceso a Datos ..................................................................................................... 125 5.3.3 Modelo de Reglas del Negocio. .............................................................................................. 126

5.4 CONSTRUCCIÓN DE LA APLICACIÓN ............................................................................................. 128 5.4.1 Creación de la Estructura de Datos. ...................................................................................... 128 5.4.2 Creación del Proyecto Visual C# Win32................................................................................ 129

5.5 EJECUCIÓN Y RESULTADOS .......................................................................................................... 138 5.5.1 Operación de Adición............................................................................................................. 139 5.5.2 Operación de Actualización: .................................................................................................. 140 5.5.3 Operación de Eliminación...................................................................................................... 141

5.6 CONCLUSIONES SOBRE LAS PRUEBAS........................................................................................... 141

VI. CONCLUSIONES Y FUTURAS LINEAS DE INVESTIGACION .......................................... 142

6.1 CONCLUSIONES GENERALES ........................................................................................................ 142 6.2 FUTURAS LÍNEAS DE INVESTIGACIÓN........................................................................................... 143

6.2.1 Manejo de Herencia y Composición....................................................................................... 143 6.2.2 Eficiencia y Rendimiento. ....................................................................................................... 144 6.2.3 Ejecución sobre plataformas no Windows.............................................................................. 144

VII. BIBLIOGRAFÍA Y REFERENCIAS ESTUDIADAS................................................................ 145

VIII. ANEXO A: CÓDIGO FUENTE DEL MOTOR DE PERSISTENCIA .................................... 147

Page 4: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 4 de 159

I. Introducción

A medida que evoluciona la tecnología y los procesos de negocios de las empresas privadas

y gubernamentales se vuelven mas dependientes de las ciencias de la información, se

demanda a su vez, una mayor calidad en los procesos de desarrollo de software con el fin

de obtener productos de una mayor calidad, es decir con una mejor estabilidad, eficiencia

robustez y reusabilidad de los dichos elementos. Esto significa que lo productos de software

no deben ser diseñados y creados únicamente para solucionar un requerimiento especifico

de usuario como un caso de uso, un user story o un escenario, sino deben de ser diseñados

de tal forma que estén totalmente documentados, que su arquitectura sea robusta y permita

la reutilización de sus componentes, que sea sencillo el cambio o extensión de una

funcionalidad o comportamiento, que su ejecución sea estable, etc. Estos requerimientos

son totalmente soportados por la orientación a objetos la cual con la ayuda de algunos

metodologías de desarrollo y herramientas de software logran cumplir los requerimientos

antes mencionados.

En el ciclo de desarrollo de los proyectos de software, las etapas de conceptualización y

diseño de sistemas requieren abstraer los comportamientos de los elementos que se desean

mecanizar, de tal forma que sean imitados tanto en sus propiedades como en su

comportamiento, esto nos lleva a la definición de tipos de datos o clases los cuales serán la

implementación de los elementos surgidos de la etapa de conceptualización, estos tipos de

datos con estado y comportamiento, darán vida a lo que denominaremos ya en la ejecución

de sistema “objetos”.

Dado que la tecnologías favoritas actuales de persistencia de datos aun son las bases de

relacionales, existe un divorcio entre los modelos de clases que forman la

conceptualización del sistema con sus propias características OO (Object Oriented) como la

herencia, la encapsulación y el polimorfismo y los modelos relacionales los cuales siguen

otro conjunto de reglas como las reglas de normalización. Este problema es solventado por

los motores de persistencia, quienes se encargan de convertir objetos a registros en un

sistema relacional y viceversa.

Page 5: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 5 de 159

Los motores de persistencia vienen entonces a ser el enlace entre ambas tecnologías

permitiendo al diseñador llegar a abstraer completamente un sistema en un modelo de

clases con sus características innatas OO, sin tener que preocuparse por como serán

persistidos los datos en la base relacional.

Este documento muestra como utilizando recursos sin costo alguno puede ser construido un

motor de persistencia para la plataforma .Net de Microsoft que implemente las

características principales de esta tecnología de persistencia de un modelo conceptual

completamente Object Oriented o modelo de dominio en una base de datos relacional

1.1. Objetivos.

• Fomentar el diseño orientado a objetos utilizando la plataforma .Net, al facilitar una

herramienta que implemente la funcionalidad necesaria para persistir objetos que a

su ves sean capaces de conceptualizar los distintos elementos que componen un

sistema de información como objetos que modelen la realidad del sistema y posean

responsabilidades únicas.

• Diseñar y desarrollar una librería que implemente la funcionalidad para realizar un

mapeo automático entre un modelo de clases o modelo de Dominio y un modelo

ER.

• Diseñar una librería que implemente la funcionalidad necesaria para crear de forma

automática las operaciones transaccionales contra un sistemas RDBMS.

• Aplicar conceptos avanzados de Ingeniería de Software, como el uso de patrones de

diseño, para garantizar la reusabilidad del código desarrollado, así como su

confiabilidad y robustez.

• Fomentar el uso de técnicas de ingeniería de software avanzadas en los programas

educativos de las universidades, al utilizar este documento como una referencia de

trabajo y ejemplo de la aplicación de patrones de diseño y otras temas relacionados.

Page 6: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 6 de 159

1.2. Alcances

• Se desarrollará un prototipo que implementará la funcionalidad principal del motor

de persistencia, es decir maneje automáticamente las operaciones de Object /

Relational Mapping O/R M.

• La arquitectura del producto es un diseño 100% creado por el grupo de trabajo y no

se ha copiado, basado o inspirado en la arquitectura de productos existentes por lo

que no existe un elemento de investigación de las arquitecturas de los motores

actuales, sino solamente sobre su funcionalidad.

• El proyecto esta orientado a la plataforma .Net de Microsoft, específicamente al

Framework 2.0.

• Todas las herramientas a emplear en el desarrollo del proyecto a excepción de la

herramienta CASE 1de diseño y modelado son de libre distribución, por lo que no se

estiman costos para la adquisición de software.

• El producto será desarrollado utilizando el lenguaje C# de Microsoft y la

herramienta de desarrollo Visual C# 2005 Express edition.

• Para realizar las operaciones de mapeo O/RM, ya que esto se hará de forma

automática y transparente para el desarrollador, el producto se basará en un modelo

de clases el cual debe de coincidir perfectamente con un modelo relacional por lo

que será altamente recomendable la utilización de una Herramienta Case que

mantenga la sincronía entre el modelo de clases y el ER.

1.3. Limitaciones.

La limitación principal que afecta el proyecto en si, es el tiempo asignado y ya que de

las 10 semanas totales se utilizaron más de dos en la formulación del proyecto, algunas

limitaciones especificas son las siguientes:

• Para el prototipo a implementar, no se contempla el soporte para la Composición y

la herencia.

1 Se deja a criterio del lector el uso de la herramienta CASE de su preferencia. Para este proyecto se utiliza PowerDesigner 12

Page 7: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 7 de 159

• Se construirá el prototipo con librerías de acceso a datos o dialectos que permitan

conectarse a los sistemas Oracle, Mysql y Microsoft SQL Server 2000/2005. Estas

podrán ser extendidos posteriormente gracias a la utilización de los patrones de

diseño como el Abstract Factory.

• Se han utilizado patrones de diseño fundamentales como el Singleton y el Abstract

Factory y otros específicos de acceso a datos como DAO, Data Accesors, etc. Sin

embargo es posible que alguna de la funcionalidad creada en este prototipo pudiera

haber sido implementada también utilizando otros patrones que por el corto tiempo

no pudieron ser considerados.

• Se enfoco el esfuerzo del grupo de trabajo en la eficacia de la funcionalidad a

implementar, esto debido a la limitante de tiempo. Se propone entonces un estudio

aparte a este proyecto donde se plantee la implemente la funcionalidad propuesta de

una forma mas eficiente.

1.4. Suposiciones y Dependencias

• Se supone que el lector tiene conocimientos medios en la utilización del lenguaje

C# y de las técnicas de orientación a objetos.

• Se supone que el lector tiene claro las ventajas de la utilización de un enfoque

orientado a objetos sobre uno tradicional.

• Se supone que el lector tiene conocimientos básicos de los patrones de diseño y de

las ventajas que estos representan en la construcción de software.

• Se supone que el diseñador modelador posee conocimientos sobre modelado UML

y uso de la herramienta CASE.

1.5. A quien esta dirigido este documento. Este documento en general esta dirigido a todo aquel desarrollador que desee ampliar sus

conocimientos en el uso de la tecnología de motores de persistencia u O/R Mapping,

aplicadas a la plataforma Microsoft .Net.

El documento sin embargo ha sido elaborado para que pueda ser utilizado como una guía a

educadores del área de desarrollo de nivel intermedio que puedan al implementar la

Page 8: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 8 de 159

propuesta aquí planteada, repasar una serie de conocimientos, técnicas y principios

relacionados a la Ingeniería del Software. Sin embargo debe de recordarse que no esta

orientada a desarrolladores principiantes, sino con un conocimiento intermedio de

programación orientada a objetos y desarrollo bajo e framework .Net.

1.6. Organización del Documento.

El documento ha sido organizado de la siguiente manera:

En el primer capitulo “Introducción” encontrará todo lo referente a la definición del

proyecto, sus objetivos, alcances y limitantes, así como las suposiciones sobre las que se

trabajo dicho proyecto y la descripción de a quien esta dirigido este documento.

El segundo capitulo “Justificación del Tema”, describe la importancia del tema de motores

de persistencia en el contexto de un mejor ciclo de vida de proyectos de desarrollo de

software y del beneficio académico que supone este proyecto

El tercer capitulo “Fundamentos Teóricos” contiene una referencia documental rapida de

distintas, tecnologías, disciplinas y estándares relacionados con el tema principal, con el fin

de que sirvan de guía o refuerzo si desconoce algún tema en particular.

El cuarto capitulo “Solución Propuesta”, se describe el ciclo completo de construcción de la

solución, desde la definición de sus requerimientos, el diseño de cada funcionalidad

requerida y su implementación con el lenguaje C

El quinto capitulo “Resultados y Verificación Experimental”, documenta los resultados de

las pruebas realizadas luego de construida la solución, demostrando que el producto es

operable de acuerdo a los alcances definidos.

El capitulo sexto “Conclusiones y Futuras Lineas de Investigación” presenta las

conclusiones generales después de construir el producto, así como se propone una serie de

temas que por motivos de tiempo no se han incluido en este documento, pero que se

estiman pueden ser desarrollados extendiendo la funcionalidad del prototipo planteado.

El capitulo séptimo “Bibliografía y Referencias Estudiadas”, lista la bibliografía utilizada

como fuente para este proyecto.

Page 9: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 9 de 159

II. Justificación del Tema

2.1 Antecedentes Los procesos de desarrollo de software, han evolucionado en los últimos años. Esto debido

en gran medida a la cantidad alarmante de proyectos de este tipo que no se desarrollan de

acuerdo a lo planeado, o, finalizan en fracasos. Una muestra de esto se puede apreciar en la

siguiente gráfica la cual es resultado de una investigación del Standish Group en los estados

unidos, donde se recolecto información de mas de 30,000 proyectos de pequeña, mediana y

grandes empresas.

Se puede observar en la gráfica que se presentan para los años 1994, 1995, 1998 y 2000 los

porcentajes de proyectos los cuales han sido clasificados de la siguiente manera:

• Failed: Estos son proyectos que fueron abortados, suspendidos o finalizaron en un

fracaso de acuerdo a los objetivos planteados.

• Challenged: Estos son proyectos que si bien finalizaron , consumieron mas de los

recursos planeados originalmente , excediendose principalmente en tiempo o

presupuesto.

• Succeeded: Estos son los proyectos que finalizaron existomente utilizando los

recursos planeados originalmente.

2000

1998

1995

1994

28% 23% 49%

26% 28% 46%

27% 40% 33%

16% 31% 53%

Succeeded Challenged Failed

Page 10: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 10 de 159

Esta situación origino el estudio, documentación, estandarización y difusión de las

conocidas buenas practicas para el desarrollo de software. Tomando como base las

investigaciones realizadas por el Instituto de Ingeniería del Software SIE solicitado por el

Departamento de Defensa de los Estados Unidos que dieron origen al modelo de capacidad

de madures CMM2 y sus sucesores SW-CMM y el actual CMMI que sirve como base a

metodologías de desarrollo como el Rational Unified Process y el Microsoft Solution

Framework.

Estas nuevas metodologías al igual que el CMMI sugieren llevar en el proceso de desarrollo

de software una administración de requerimientos, control de cambios y otras

características que garantizan un estricto control del proyecto para llevarlo a ser exitoso. El

RUP y el MSF son las metodologías disponibles en nuestro medio y que lentamente son

adoptadas por las instituciones y empresas, ambas sugieren la creación de una serie de

roles con responsabilidades bien definidas, en estos se aprecia que el rol del desarrollador

sin bien y obviamente es necesario no tiene tanta importancia como los roles de Arquitectos

de la solución, ingenieros de requerimientos o Diseñadores, ya que son ellos los que

conciben la solución la conceptualizan y modelan, dejando al final prácticamente un

completo manual de que es lo que se debe de construir, donde se han evaluado ya los

aspectos de arquitectura, seguridad etc. Entonces el desarrollador viene solo a seguir las

indicaciones de que lo que se construirá y como se hará .(Debe de tenerse en cuenta que en

proyectos pequeños o con pocos recursos, ambos roles diseñador y desarrollador los podría

ejecutar la misma persona). Dadas las necesidades de robustez, reusabilidad, etc. al

momento de diseñar y construir la solución se utiliza un enfoque orientado a objetos

aunque este posteriormente pueda evolucionar a una orientación a Aspectos o Servicios.

El diseñador o arquitecto de la solución, podría entonces concebir un modelo de la solución

completamente orientado a objetos, utilizando herencias, polimorfismos, encapsulamiento,

etc. Sin embargo al intentar persistir dichos objetos para hacerlo de forma transparente se

requeriría la utilización de una Base de Datos Orientada a Objetos, lo cual es poco usual ya

2 Para mayor información sobre CMM remitirse a la sección 3.5.1

Page 11: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 11 de 159

que la tecnología de almacenamiento mas utilizada son las bases relacionales como Oracle,

SQL Server, Sybase, MySQl, etc. Así que con un diseño orientada a objetos al momento

realizar la persistencia el Desarrollador deberá ver como se las arregla para realizar el

mapeo entre clases y tablas y generar las operaciones transaccionales necesarias.

Naturalmente esta operación le consumirá una considerable cantidad de tiempo.

Los motores de persistencia o también denominados O/R Mapping implementan una capa

que realiza las transformaciones entre clases y tablas de forma tal que los desarrolladores ya

no deben de invertir tanto tiempo en estas actividades, siendo al final una valiosa

herramienta a utilizar cuando se tiene un diseño orientado a objeto y se desea persistir en

una base de datos relacional.

2.2 Motores de Persistencia y el Framework .Net

Los motores de persistencia han sido utilizados ampliamente en la plataforma Java, donde

productos como Hibernate, TopLink, CocoBase, JRelay son algunos representantes de estos

productos, de hecho Java tiene el estándar JDO que pretende normalizar las operaciones de

persistencia bajo esta plataforma.

En el caso de la plataforma Microsoft, es mas reciente la utilización de este tipo de

tecnologías, sin embargo existen en el mercado opciones comerciales como ORM, Gentle

.Net, etc. Además existe ahora una versión del motor de persistencia de código abierto mas

difundido en el mundo Java “Hibérnate”, que en su versión para el framework .Net es

denominado NHibernate.

Antes de la aparición del Framework 2.0 se hablaba también del producto ObjectSpaces el

cual es un motor de persistencia desarrollado por Microsoft para trabajar únicamente sobre

SQL Server, sin embargo se planeaba que fuera liberado junto con la nueva versión del

framework. A la fecha el framework ya fue liberado pero no se tiene información sobre

ObjectSpaces.

Page 12: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 12 de 159

2.3 El porque de la creación de un motor de persistencia para .Net.

Cuando las necesidades de un motor de persistencia son inminentes, las dos opciones son o

construirlo o comprar u adquirir un producto existente. El uso de un producto existente

naturalmente conlleva adaptarse a la forma de trabajo planteada por dicho producto. Por

otro lado la construcción de un motor de este tipo, requiere la inversión de tiempo, el

conocimiento avanzado de técnicas de orientación a objetos, aplicación de patrones de

diseño, etc.

Dado que bajo la plataforma .Net el uso de este tipo de aplicativos no es muy difundida,

siendo sus beneficios muy amplios. La creación y puesta a disposición de una herramienta

de este tipo se espera potencie su uso y promueva el diseño de sistemas completamente

orientados a objetos, además el hecho de dejar documentado el proceso de diseño y

construcción en este documento, se espera pueda servir como un ejercicio académico que

pueda ser utilizado por educadores y desarrolladores para profundizar en el tema y elevar su

nivel.

Finalmente la sola utilización de la herramienta construida por la comunidad de

desarrolladores .Net, se espera tengo un impacto positivo permitiendo la reducción de los

tiempos de desarrollo, la abstracción de modelos de dominio y de acceso a datos

independientes del tipo de base de datos utilizado y en si todas las características que

conlleva el uso de este tipo de herramientas.

Page 13: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 13 de 159

III. FUNDAMENTOS TEORICOS

Los fundamentos teóricos plasmados en esta sección describen aquellas técnicas y

disciplinas que están estrechamente relacionadas al tema de los Motores de Persistencia,

iniciando desde la programación orientada a objetos y los patrones de diseño, pasando al

tema de Bases de Datos Orientadas a Objetos, generalidades sobre los motores de

persistencia e introduciendo al tema de Metodologías Iterativas de Desarrollo de Software

donde se habla del CMMI, el RUP y el MSF. Finalmente se termina el capitulo

describiendo algunas características de la plataforma sobre la cuales se implementan los

conceptos antes descritos, es decir la plataforma del Microsoft .Net Framework.

Esta información esta documentada en este capitulo de tal forma que pueda servir como

base al lector para ampliar sobre algunos fundamentos sobre los cuales se ha desarrollado el

presente proyecto.

3.1 Programación Orientada a Objetos

3.1.1 Historia y Evolución.

El modelo orientado a objetos es el modelo teórico que usan la mayoría de los programas

actuales. La programación orientada a objetos comienza en los años sesenta (en los que

aparecieron los primeros lenguajes de este tipo, llamados “Simula I” y “Simula 67”,

desarrollados en el Centro Noruego de Computación, en Oslo). En los primeros 70, aparece

“Smalltalk”, un lenguaje fundamental en la historia de la orientación a objetos.

Sin embargo, es hasta la segunda mitad de los años 80 que la orientación de objetos se

generaliza, convirtiéndose en el estándar predominante en los años 90, con lenguajes tales

como C++ y Java. Su éxito ha sido impulsado por la difusión de otras tecnologías (como la

interfaz gráfica o las arquitecturas distribuidas) que son más fáciles de implementar

mediante este tipo de desarrollo que mediante una programación tradicional.

En la actualidad, la práctica totalidad de los lenguajes de programación que surgen son

orientados a objetos y esta tecnología se ha convertido en el estándar actual de

Page 14: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 14 de 159

programación que, a su vez, está generando nuevos desarrollos muy prometedores para el

futuro como, por ejemplo, la programación orientada a aspectos.

La idea de la orientación a objetos es modelar los programas de una forma parecida a cómo

percibimos la realidad. Para la mente humana, el universo está compuesto por una serie de

“objetos” (en el sentido más amplio de la palabra, incluyendo seres vivos, ideas, etc.). Cada

objeto tiene unas características que lo diferencian de los demás y, con cada objeto, se

pueden realizar unas acciones que son propias y específicas del mismo. Así, por ejemplo,

un determinado auto tiene unas características (color rojo, caja de cambios automática,

diesel, etc.) y puede realizar unas determinadas acciones (acelerar, frenar, etc.).

La programación orientada a objetos intenta modelar estos objetos reales con estructuras de

programa, llamadas “objetos de software” o, simplemente, “objetos”. Cada uno de estos

objetos de software, está compuesto por una serie de características (llamadas “atributos”) y

una serie de acciones (llamadas “métodos”), al igual que un objeto de la vida real.

La OO aporta un enfoque nuevo, convirtiendo la estructura de datos en el centro sobre el

que pivotan las operaciones. De esta forma, cualquier modificación de la estructura de

datos tiene efecto inmediato sobre las acciones a realizar sobre ella, siendo esta una de las

diferencias radicales respecto a la programación estructurada.

En esta forma de diseño se descomponen los requerimientos del programa paso a paso,

hasta llegar a un nivel que permite expresarlos mediante procedimientos y funciones. La

OO estructura los datos en objetos que pueden almacenar, manipular y combinar

información.

3.1.2 Ventajas de la OO

La OO proporciona las siguientes ventajas sobre otros lenguajes de programación

• Uniformidad. Ya que la representación de los objetos lleva implica tanto el análisis

como el diseño y la codificación de los mismos.

Page 15: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 15 de 159

• Comprensión. Tanto los datos que componen los objetos, como los procedimientos

que los manipulan, están agrupados en clases, que se corresponden con las

estructuras de información que el programa trata.

• Flexibilidad. Al tener relacionados los procedimientos que manipulan los datos con

los datos a tratar, cualquier cambio que se realice sobre ellos quedará reflejado

automáticamente en cualquier lugar donde estos datos aparezcan.

• Estabilidad. Dado que permite un tratamiento diferenciado de aquellos objetos que

permanecen constantes en el tiempo sobre aquellos que cambian con frecuencia

permite aislar las partes del programa que permanecen inalterables en el tiempo.

• Reusabilidad. La noción de objeto permite que programas que traten las mismas

estructuras de información reutilicen las definiciones de objetos empleadas en otros

programas e incluso los procedimientos que los manipulan. De esta forma, el

desarrollo de un programa puede llegar a ser una simple combinación de objetos ya

definidos donde estos están relacionados de una manera particular.

Uno de los puntos clave a remarcar es que la programación orientada a objetos no sustituye

a ninguna metodología ni lenguaje de programación anterior. Todos los programas que se

realizan según OOD se pueden realizar igualmente mediante programación estructurada. Su

uso en la actualidad se justifica porque el desarrollo de todas las nuevas herramientas

basadas en un interfase de usuario gráfico como Windows, OS/2, x-Windows, etc. Es

mucho más sencillo

3.1.3 Características de los Objetos

3.1.3.1 Identidad del Objeto La identidad expresa que aunque dos objetos sean exactamente iguales en sus atributos, son

distintos entre sí. De esta forma incluso una serie de Objetos vehiculo, recién fabricados

son distintos los unos de los otros.

La afirmación anterior, aunque parece obvia, tiene importancia cuando descendemos al

nivel de programación. En este ámbito cada uno de los objetos tiene un controlador pro el

Page 16: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 16 de 159

cual se identifica. Este puede ser una variable, una estructura de datos, una cadena de

caracteres, etc. El controlador será distinto para cada uno de los objetos, aunque las

referencias a éstos sean uniformes e independientes del contenido, permitiendo crear

agrupaciones de objetos con el mismo tratamiento.

3.1.3.2 Abstracción Cada objeto en el sistema sirve como modelo de un "agente" abstracto que puede realizar

trabajo, informar y cambiar su estado, y "comunicarse" con otros objetos en el sistema sin

revelar cómo se implementan estas características. Los procesos, las funciones o los

métodos pueden también ser abstraídos y cuando lo están, una variedad de técnicas son

requeridas para ampliar una abstracción

3.1.3.3 Clasificación Con la clasificación comienza la verdadera programación orientada a objetos. Ellos nos

obliga a una abstracción del concepto de objeto denominada clase.

Las clases permiten la agrupación de objetos que comparten las mismas propiedades y

comportamiento.

El esfuerzo del programador ante una aplicación orientada a objetos se centra en la

identificación de las clases, sus atributos y operaciones asociadas y que son estas realmente

las que modelan la realidad de la aplicación a construir.

Las propiedades de cada clase deben cumplir una serie de premisas

• Las propiedades deber ser significativas dentro del entorno de la aplicación es decir,

deben servir para identificar claramente y de una manera única (y univoca) a cada

uno de los objetos

• El número de propiedades de un objeto debe ser el mínimo para realizar todas las

operaciones que requiera la aplicación.

Page 17: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 17 de 159

3.1.3.4 Encapsulación y ocultación de datos

La capacidad de presentación de información dentro de un objeto se divide en dos partes

bien diferenciadas:

• Interna: La información que necesita el objeto para operar y que es innecesaria para

los demás objetos de la aplicación. Estos atributos se denominada privados y tienen

como marco de aplicación únicamente a las operaciones asociadas al objeto.

• Externa La que necesitan el resto de los objetos para interactuar con el objeto que

definimos . Estas propiedades se denominan públicas y corresponde a la

información que necesitan conocer los restantes objetos de la aplicación respecto

del objeto definido para poder operar.

Podemos imaginarla encapsulación como introducir el objeto dentro de una caja negra

donde existen dos ranuras denominadas entrada y salida. Si introducimos datos por la

entrada automáticamente obtendrá un resultado en la salida. No necesita conocer ningún

detalle del funcionamiento interno de la caja.

El término encapsulación indica la capacidad que tienen los objetos de construir una

cápsula a su alrededor, ocultando la información que contienen (aquélla que es necesaria

para su funcionamiento interno, pero innecesaria para los demás objetos) a las otras clases

que componen la aplicación.

Aunque a primera vista la encapsulación puede parecer superflua, tengamos en cuenta que

existen muchas variables utilizadas de forma temporal: contadores y variables que

contienen resultados intermedios, etc. De no ser por la encapsulación estas variables

ocuparían memoria y podrían interferir en el funcionamiento del resto de los objetos.

La encapsulación no es exclusiva de los lenguajes de programación orientados a objetos.

Aparece en los lenguajes basados en procedimientos (PASCAL, C, COBOL, ETC) como

una forma de proteger los datos que se manipulan dentro de las funciones.

Page 18: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 18 de 159

Los lenguajes OOP incorporan la posibilidad de encapsular también las estructuras de datos

que sirven como base a las funciones. Aportan por tanto un nivel superior en cuanto a

protección de información.

La encapsulación nos permite el uso de librerías de objetos para el desarrollo de nuestros

programas. Recordemos que las librerías son definiciones de objetos de propósito general

que se incorporan a los programas. Al ser el objeto parcialmente independiente en su

funcionamiento del programa en donde está definido, ya que contiene y define todo lo que

necesita para poder funcionar, es fácil utilizarlo en los mas variados tipos de aplicaciones.

Si aseguramos , depurando las propiedades y las operaciones dentro de la clase que el

objeto función bien dentro de una aplicación, con una correcta encapsulación el objeto

podrá funcionar en cualquier otra.

Otra de las ventajas de la encapsulación, es que al definir el objeto como una caja negra

con entradas y salida asociadas, en cualquier momento podemos cambiar el contenido de

las operaciones del objeto, de manera que no afecte al funcionamiento general del

programa.

La encapsulación está en el núcleo de dos grandes pilares de la construcción de sistemas;

mantenibilidad y reusabilidad

3.1.3.5 Mantenibilidad

Cualidad que indica que un programa o sistema debe ser fácilmente modificable. Es decir

que los cambios en las condiciones externas (como la definición de una nueva variable)

implicarán modificaciones pequeñas en el programa / sistema. El concepto de

mantenibilidad implica que un programa, al igual que un ser vivo debe ser capaz de

adaptarse a un medio ambiente siempre cambiante.

Page 19: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 19 de 159

3.1.3.6 Reusabilidad

Cualidad que nos indica que partes del programa ( en este caso objetos) pueden ser

reutilizados en la confección de otros programas. Ello implica que los objetos definidos en

un programa pueden ser extraídos del mismo e implantados en otro sin tener que realizar

modificaciones importantes en el código del objeto.

3.1.3.7 Poliformismo

El polimorfismo es una nueva característica aportada por la OOP. Esta propiedad indica la

posibilidad de definir varias operaciones con el mismo nombre, diferenciándolas

únicamente en los parámetros de entrada. Dependiendo del objeto que se introduzca como

parámetro de entrada, se elegirá automáticamente cual de las operaciones se va a realizar.

Ya está habituado al operador <<suma>> que está presente en todos los lenguajes de

programación. Sin embargo, los operadores <<suma de fracciones>> y <<suma de números

complejos>> no existen en casi ningún lenguaje de programación.

Los lenguajes OOP permiten definir un operador <<suma>> tal que reconozca que tipo de

objeto se le está aplicando, a través de operaciones de objetos. Previamente deberá definir

la fracción y el número complejo como una clase y la operación suma como una operación

de una clase.

Definiendo adecuadamente las operaciones suma de fracciones y suma de números

imaginarios, el operador suma devolverá, en el caso que los operandos sean fracciones, una

fracción y , en el caso de los números imaginarios, otros número imaginario.

Es posible extender el concepto e incluso definir operaciones como suma de bases de datos

3.1.3.8 Herencia

Page 20: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 20 de 159

La herencia es la última de las propiedades relativas a la OOP, Consiste en la propagación

de los atributos y las operaciones a través de distintas sub-clases definidas a partir de una

clase común.

Introduce, por tanto, una posibilidad de refinamiento sucesivo del concepto de clase. Nos

permite definir una clase principal y , a través de sucesivas aproximaciones, cualquier

característica de los objetos. A partir de ahora definiremos como sub-clases todas aquellas

clases obtenidas mediante refinamiento de una (o varias) clases principales.

La herencia nos permite crear estructuras jerárquicas de clases donde es posible la creación

de sub-clases que incluyan nuevas propiedades y atributos. Estas sub-clases admiten la

definición de nuevos atributos, así como crear, modificar o inhabilitar propiedades.

Posibles modelos.

Además, es posible que una sub-clase herede atributos y propiedades de más de una clase.

Este proceso se denomina herencia múltiple

La herencia es, sin duda alguna, una de las propiedades más importantes de la OOP, ya que

permite, a través de la definición de una clase básica, ir añadiendo propiedades a medida

que sean necesarias y, además, en el sub-conjunto de objetos que sea preciso.

La herencia permite que los objetos puedan compartir datos y comportamientos a través de

las diferentes sub-clases, sin incurrir en redundancia. Más importante que el ahorro de

código, es la claridad que aporta al identificar que las distintas operaciones sobre los

objetos son en realidad una misma cosa.

3.1.3.9 Conclusión. Identidad, clasificación, polimorfismo y herencia caracterizan a los lenguajes orientados a

objetos. Cada uno de estos conceptos puede utilizarse aisladamente, incluso aparecen en

otras metodologías de programación, pero juntos se complementan en una relación

sinérgica. Los beneficios de la programación orientada a objetos son más que los que

pueden verse a simple vista. El énfasis en las propiedades esenciales de un objeto, fuerza al

Page 21: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 21 de 159

desarrollador a pensar cuidadosamente que es un objeto y que es lo que hace con el

resultado de que el sistema es normalmente más preciso, general y robusto que si

pusiéramos el énfasis en los procedimientos y los datos por separado.

3.2 Patrones de Diseño

Un patrón de diseño es una solución a un problema de diseño no trivial que es efectiva (ya

se resolvió el problema satisfactoriamente en ocasiones anteriores) y reusable (se puede

aplicar a diferentes problemas de diseño en distintas circunstancias).

Los patrones son soluciones de sentido común que deberían formar parte del conocimiento

de un diseñador experto. Además facilitan la comunicación entre diseñadores, pues

establecen un marco de referencia (terminología, justificación). Los patrones son una

manera de resolver problemas del desarrollo del software, fruto de la experiencia

acumulada de muchos desarrolladores. Esto garantiza que el patrón no es simplemente una

abstracción teórica, sino que realmente soluciona el problema planteado y ha sido probado

miles y miles de veces por lo que es altamente fiable y estable para la solución del

problema especifico.

En la programación orientada a objetos resulta complicado descomponer el sistema en

objetos (encapsulación, granularidad, dependencias, flexibilidad, reusabilidad, etc.), los

patrones de diseño nos permitirán identificar a los objetos apropiados de una manera mucho

más sencilla. También nos permitirán determinar la granularidad de los objetos.

Los patrones permiten

• Ante un problema reiterado ofrece una solución contrastada que lo resuelve.

• Describe el problema en forma sencilla.

• Describe el contexto en que ocurre.

• Describe los pasos a seguir.

Page 22: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 22 de 159

• Describe los puntos fuertes y débiles de la solución.

• Describe otros patrones asociados

En general un patrón tiene cuatro elementos fundamentales:

• El Nombre del Patrón, describe la forma en que podemos manejar un problema sus

soluciones y consecuencias descritas en una o dos palabras

• El problema describe cuando aplicar dicho patrón. Explica el problema y su

contexto. Puede exponer problemas específicos de diseño tales como representar

algoritmos como objetos. En algunas ocasiones se incluyen también listas de

condiciones que deben de ser conocidas antes de decidir aplicar este diseño

• La solución, describe los elementos que componen el diseño, sus relaciones,

responsabilidades y colaboración. La solución no describe un diseño concreto

particular o su implementación, esto es debido a que un patrón es mas como una

plantilla que puede ser aplicada en muchas situaciones. En ves de eso, el patrón

provee una descripción abstracta del diseño de un problema

• Las consecuencias, estas son el resultado de la aplicación del patrón. Las

consecuencias, son elementos críticos al momento de evaluar las alternativas de

diseño

3.2.1 Historia

El reciente interés del mundo del software por los patrones tiene su origen, a partir de 1995,

tras la aparición y el éxito del libro "Design Patterns: Elements of Reusable Object-

Oriented Software" de la banda de los cuatro. Ellos, Erich Gamma, Richar Helm, Ralph

Johnson y John Vlissides, se dedicaron a recopilar una serie de patrones (23) aplicados

habitualmente por expertos diseñadores de software orientado a objetos, y al hacerlos

públicos.

Podemos mencionar otros autores que han contribuido a este tema como Craig Larman,

quien ha definido de los patrones GRASP (patrones generales de software para asignar

responsabilidades

Page 23: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 23 de 159

3.2.2 Conceptos Clave

Resulta difícil hablar de patrones de diseño, sin retomar dos términos que son un objetivo

permanente del diseño orientado a objetos, como son la cohesión y el acoplamiento.

Podríamos definir la cohesión de una clase (o de un paquete, etc.) como la relación entre

los distintos elementos de la clase, normalmente sus métodos. Es decir, que todos los

elementos de una clase tienen que trabajar en la misma dirección, es decir, hacia un mismo

fin. Por ejemplo, una clase "Coche" debería ocuparse de cosas relacionadas con el coche en

si, como acelerar y frenar, pero no de cosas ajenas a él como manipular información

referente a su seguro. La cohesión es una medida relativa, en el sentido de que depende de

lo que cada uno piense que es la función de la clase, pero lo importante es mantener una

cohesión lo mas alta posible. Existen diferentes tipos de cohesión (funcional, secuencial,

etc.),

Respecto al acoplamiento, podemos decir que es la interdependencia existente entre dos

clases, paquetes, etc. Esto ocurre normalmente cuando una clase (o paquete) necesita saber

demasiados detalles internos de otra para su funcionamiento, es decir, rompe el

encapsulamiento del que tanto se habla en la programación orientada a objetos. También

existen diversos tipos de acoplamiento (funcional, de datos, etc.), lo que nos lleva a la

conclusión que para tener un diseño correcto, fácil de mantener y modular, cuanto más

bajo acoplamiento haya entre las clases (o paquetes), pues mejor.

3.2.3 Tipos de Patrones

La banda de los cuatro (GoF) definió tres tipos distintos de patrones fundamentales:

• patrones de creación.

• patrones estructurales.

• patrones de comportamiento

Page 24: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 24 de 159

3.2.3.1 Patrones Creacionales

Los patrones de creación son las soluciones aceptadas como "buenas" a los problemas de

creación de instancias de objetos. Los programas orientados a objetos crean decenas,

cientos o incluso miles de instancias de objetos, es por ello, que esta no es una tarea que se

puede realizar a la ligera.

Nuestros programas no deben depender de la forma en que se crean y organizan los objetos.

Por supuesto que podemos utilizar el operador new cada vez que necesitemos, pero en

ocasiones eso puede hacer nuestro software realmente difícil de mantener.

Además, en muchos casos, puede ocurrir que el objeto concreto que necesitemos en un

momento concreto dependa del estado de nuestra aplicación en tiempo de ejecución. Por

ejemplo, puede ocurrir que en un momento tengamos que dibujar un círculo o un cuadrado,

pero no por ello tenemos que llenar nuestro software de sentencias if. El crear clases

especiales que abstraen el proceso de creación de instancias hace que nuestro software sea

más flexible y general.

Ejemplos de estos patrones son:

• Patrón Factoría

• Patrón Factoría Abstracta

• Patrón Singleton (Instancia Única)

• Patrón Prototipo

3.2.3.2 Patrones Estructurales

Los patrones estructurales se ocupan de la combinación de objetos para crear estructuras

complejas. Esto no es del todo exacto, ya que hay patrones estructurales que se encargan de

las relaciones entre clases (mayoritariamente el uso de la herencia), mientras que otros se

encargan de los objetos, las instancias de las clases (normalmente composición).

Destacan entre este tipo de patrones, el patrón adaptador (adapter pattern, GoF), el patrón

fachada (facade pattern, GoF), el patrón proxy (proxy pattern, GoF) y el patrón puente

(bridge pattern, GoF).

Page 25: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 25 de 159

3.2.3.3 Patrones de Comportamiento

Los patrones de comportamiento estudian las relaciones entre llamadas entre los diferentes

objetos, normalmente ligados con la dimensión temporal

Entre este tipo de patrones, tenemos:

• Patrón Cadena de Responsabilidad

• Patrón Comando

• Patrón Intérprete

• Patrón Iterador

• Patrón Mediador

• Patrón Recuerdo (Memento)

• Patrón Observador

• Patrón Estado

• Patrón Estrategia

• Patrón Plantilla

• Patrón Visitante

3.2.4 Patrones de Acceso a Datos Asi como los patrones de diseño, implementan soluciones a problemas comunes, los

patrones de acceso a datos tienen un rol similar en el campo del acceso a datos. Estos

patrones, describen una abstracción común a problemas a soluciones que pueden ser

aplicadas directamente a problemas relacionados con la obtención y persistencia de la

información. Algunos de estos patrones son aplicados o utilizados ampliamente en una

variedad de productos comerciales como en los casos de los patrones Resource pool y

Object/Relational Map. Otros de estos patrones, son menos utilizados o conocidos, de igual

forma ofrecen una amplia gama de soluciones a problemas relacionados con los datos.

Muchos de estos patrones, son adaptaciones de los patrones fundamentales a problemas

específicos del área de acceso a datos. De este tipo de patrones también existe una

categorización la cual se muestra a continuación:

Page 26: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 26 de 159

• Decoupling Patterns: describen estrategias para separar el acceso a datos de otras

responsabilidades de la aplicación. Esta acción de separación brinda flexibilidad

cuando se selecciona un modelo subyacente de datos o cuando se realizan cambios a

la estrategia completa de acceso a datos. Algunos de estos patrones son:

o Data Accesor

o Active Domain Object

o Object/Relational Map

o Layer

• Resource Patterns: describen estrategias para administrar los objetos envueltos en

relaciones de acceso a datos. Entre estos patrones tenemos:

o Resource Decorador

o Resource Pool

o Resource Timer

o Resource Descriptor

o Retraer

• Input/output patterns: Describen patrones que simplifican las operaciones de

entrada y salida, usando una tranlación consistente en información relacional y la

representación de los Domain objects. Entre estos patrones tenemos:

o Selection Factory

o Domain Object Factory

o Update Factory

o Domain Object Assembler

o Paging Iterator

• Cache Patterns: brindan soluciones que reducen la frecuencia de las operaciones

de acceso a datos, almacenado informacion comun en cache. Estos patrones

generalmente almacenan Domain object mas que información relacional. Entre

estos patrones tenemos:

o Cache Accessor

o Demand Cache

o Primed Cache

Page 27: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 27 de 159

o Cache Search Sequence

o Cache Collector

o Cache Replicator

o Cache Statistics

• Concurrency Patterns: ofrecen soluciones para el acceso multiple o concurrente a

información comun en una base datos. La mayoria de base de datos ofrecen

operaciones de locking para permitir y ayudar con este problema, sin embargo la

utilización de código que maneje este problema desde la aplicación, puede ser

tuneado para necesidades especificas. Algunos patrones representantivos de este

grupo son:

o Transaction

o Optimistic Lock

o Pessimistic Lock

o Compensating

3.2.5 El patrón Singleton Este patrón asegura que sólo una instancia de la clase es creada. Todos los objetos que usan

una instancia de esa clase, usan la misma instancia.

Algunas clases deben tener exactamente una instancia. Estas clases usualmente involucran

la administración centralizada de algún recurso. Por ejemplo, si se necesita escribir una

clase que un applet pueda usar para asegurar que no más de un clip de audio sea ejecutado

al mismo tiempo. Para evitar que dos clips de audio sean ejecutados al mismo tiempo, la

clase que usted escribe debe dejar de ejecutar un clip de audio antes de empezar a ejecutar

el siguiente. Una forma de lograr esto, es asegurar que solamente exista una instancia de la

clase, compartida por todos los objetos que usan la clase. La siguiente figura muestra el

diagrama de clases.

Page 28: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 28 de 159

Se debe de recordar que "+" significa que la característica es pública, y "-" significa que la

característica es privada. Una característica subrayada indica que es estática.

El constructor de la clase es privado. Esto previene que otras clases creen directamente una

instancia de la clase. En lugar de eso, para acceder a una instancia de la clase deben usar el

método getInstance. Este método es estático, y siempre regresa la misma instancia de la

clase. La siguiente figura muestra el diagrama de clases general de este patrón.

3.2.6 El Patrón Factory

Si consideramos el problema de crear un framework para el desarrollo de aplicaciones para

PC (tipo MSOffice). Estas aplicaciones están generalmente organizadas de una forma

"centradas en documentos" (o "centradas en archivos"). Las operaciones usualmente

empiezan con un comando para crear o editar un documento (del procesador de texto, la

planilla electrónica, etc.). En el caso de un editor de texto, además el editor puede

reconocer diferentes tipos de archivos. Un framework que apoye este tipo de aplicaciones

Page 29: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 29 de 159

debe incluir operaciones comunes de alto nivel, como crear, abrir o guardar documentos.

Supongamos que queremos crear los métodos de la clase Application. La mayoría de los

métodos de esta clase varían según el tipo de documento. Debido a esto, la clase

Application usualmente delega la mayoría de los comandos a algún tipo de objeto

documento. Además, la lógica de las operaciones del objeto documento puede variar según

el tipo de documento. Sin embargo, hay operaciones, como por ejemplo desplegar el string

con el título del documento o desplegar una imagen .gif, que son comunes para todos los

objetos documento. Esto sugiere una organización que incluya una clase abstracta

Document independiente de la aplicación, para especificar los tipos de documentos.

Esta organización es mostrada en la siguiente figura.

Lo que no queda claro aun, es cómo un objeto Application puede crear instancias de clases

de documentos específicos para esa aplicación, sin ser ella misma una aplicación específica.

Para lograr esto, se puede encapsular la lógica e instanciar subclases de la clase Document

específicas a la aplicación en una interfaz. La siguiente figura muestra esta nueva

organización.

Page 30: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 30 de 159

Usando la organización de la figura anterior, un objeto Application llama al método

createDocument de un objeto que implementa la interfaz DocumentFactoryIF. Éste le pasa

un string al método createDocument que le dice al método cuál subclase de la clase

Document debe instanciar.

El patrón Fáctory provee un objeto independiente de la aplicación con un objeto específico

a la aplicación, al cual delega la creación de otros objetos específicos a la aplicación. La

siguiente figura muestra el diagrama general de este patrón.

Page 31: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 31 de 159

Los roles que las clases e interfaz de la figura anterior juegan son los siguientes:

Product. Una clase en este rol es la superclase abstracta de objetos producidos por

el patrón Factory.

Concrete Product. Cualquier clase concreta instanciada por los objetos que

participan en este patrón.

Creation Requestor. El objeto que requiere la creación, es una clase independiente

de la aplicación que necesita crear clases específicas a la aplicación. Esto lo hace

indirectamente a través de una instancia de la clase Factory.

Factory IF. Es una interfaz independiente de la aplicación. Los objetos que crean

productos usando CreationRequestor deben implementar esta interfaz. Las

interfaces de este tipo declaran un método que es llamado por un objeto

CreationRequestor para crear productos concretos.

Factory Class. Es una clase específica a la aplicación que implementa la interfaz de

fábrica adecuada, y tiene un método para crear productos concretos.

Page 32: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 32 de 159

3.2.7 El Patrón Abstract Factory

Este patrón es también conocido como Kit o Toolkit. Dado un conjunto de clases

relacionadas, el patrón Fábrica Abstracta provee una forma de crear instancias de estas

clases desde un conjunto acoplado de subclases concretas.

Supongamos que tenemos que construir un framework para crear interfaces de usuario, que

trabajen sobre múltiples plataformas gráficas (MS-Windows, Motif, MacOS, etc.). Cada

plataforma tiene una forma nativa de desplegar cada componente (look and feel). Para

construir el framework, se puede crear una clase abstracta para cada tipo de objeto (texto,

botones, listas, etc.) y luego reescribir una subclase concreta de cada clase de objeto para

cada plataforma. Para hacerlo robusto, hay que asegurarse además que todos los objetos

creados son de la plataforma deseada. En esta situación, una clase fábrica abstracta define

métodos para crear una instancia de cada clase abstracta que representa un objeto de la

interfaz de usuario. Fábricas concretas son subclases concretas de una fábrica abstracta que

implementa sus métodos para crear instancias de clases de objetos concretos para una

misma plataforma.

En un contexto más general, una clase de fábrica abstracta y sus subclases concretas,

organizan conjuntos de clases concretas que trabajan con productos diferentes, pero

relacionados entre sí. La siguiente figura muestra el diagrama general de este patrón.

Page 33: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 33 de 159

Los roles del la imagen anterior son los siguientes:

Client. Las clases en el rol del cliente (Client) usan varias clases de objetos (widgets) para

solicitar servicios del producto con el que el cliente está trabajando. Las clases cliente

solamente conocen las clases de objetos (widgets) abstractos, y no necesitan conocer las

clases concretas.

AbstractFactory. Las clases AbstractFactory definen métodos abstractos para crear

instancias de clases de objetos concretas. Tienen un método estático getFactory el cual es

llamado por los objetos Client para tener una instancia de una fábrica concreta, apropiada

para crear widgets que trabajan con un producto particular.

ConcreteFactory1, ConcreteFactory2. Estas clases implementan los métodos definidos

por la superclase de la fábrica abstracta, para crear instancias de widgets concretos. Las

clases cliente que llaman estos métodos no necesitan tener conocimiento directo de estas

clases de fábrica concretas. En lugar de esto, accesan instancias de estas clases como

instancias de la superclase fábrica abstracta.

Page 34: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 34 de 159

WidgetA, WidgetB. Son clases abstractas que corresponden a características de un

producto con el que trabaja la subclase concreta. Se conocen como widgets abstractos.

Product1WidgetA, Product2WidgetA. Son clases concretas que corresponden a

características de un producto con el que trabajan. Se conocen como widgets concretos

3.2.8 El Patron Data Accessors

El patrón Data Accessor encapsula los detalles del acceso físico a datos en una componente

simple, exponiendo únicamente las operaciones lógicas vitales. El código de la aplicación

debe mantener el conocimiento del modelo de datos pero, es separado a traves del uso de

este patron, de cualquier responsabilidad de acceso a datos. La estructura estática de este

patrón, es mostrada en la siguiente figura:

3.2.9 Patron DAO (Data Access Object)

3.2.9.1 Origenes de DAO Este patrón ha sido tomado de las especificaciones J2EE de la plataforma Java, su utilidad

y beneficios son altos por lo que será aplicado en la construcción de nuestro prototipo.

Page 35: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 35 de 159

3.2.9.2 Contexto y Aplicación.

Muchas aplicaciones en el mundo real necesitan utilizar datos persistentes en algún

momento. Para muchas de ellas, este almacenamiento persistente se implementa utilizando

diferentes mecanismos, y hay marcadas diferencias en los APIS utilizados para acceder a

esos mecanismos de almacenamiento diferentes. Otras aplicaciones podrían necesitar

acceder a datos que residen en sistemas diferentes. Por ejemplo, los datos podrían residir en

sitemas mainframe, repositorios LDAP, etc. Otro ejemplo es donde los datos los

proporcionan servicios a través de sistemas externos como los sistemas de integración

negocio-a-negocio (B2B), servicios de tarjetas de crédito, etc.

Normalmente, las aplicaciones utilizan componentes distribuidos y compartidos como los

beans de entidad para representar los datos persistentes en la plataforma Java. Se considera

que una aplicación emplea consistencia manejada por el bean (BMP) cuando sus beans de

entidad acceden explícitamente al almacenamiento persistente -- el bean de entidad incluye

código para hacer esto. Una aplicación con requerimientos sencillos podría por lo tanto

utilizar beans de entidad en lugar de beans de sesión o servlets para acceder al

almacenamiento persistente y recuperar o modificar los datos. O, la aplicación podría usar

beans de entidad con persistencia manejada por el contenedor, y así dejar que el contenedor

maneje los detalles de las transacciones y de la persistencia.

Utilizar un Data Access Object (DAO) para abstraer y encapsular todos los accesos a la

fuente de datos. El DAO maneja la conexión con la fuente de datos para obtener y

almacenar datos.

El DAO implementa el mecanismo de acceso requerido para trabajar con la fuente de datos.

Esta fuente de datos puede ser un almacenamiento persistente como una RDMBS, un

servicio externo como un intercambio B2B, un repositorio LDAP, o un servicio de

negocios al que se accede mediante CORBA Internet Inter-ORB Protocol (IIOP) o sockets

de bajo nivel. Los componentes de negocio que tratan con el DAO utilizan un interface

simple expuesto por el DAO para sus clientes. El DAO oculta completamente los detalles

de implementación de la fuente de datos a sus clientes.

Page 36: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 36 de 159

Como el interface expuesto por el DAO no cambia cuando cambia la implementación de la

fuente de datos subyacente, este patrón permite al DAO adaptarse a diferentes esquemas de

almacenamiento sin que esto afecte a sus clientes o componentes de engocio.

Esencialmente, el DAO actúa como un adaptador entre el componente y la fuente de datos.

La siguiente figura muestra el diagrama de clases que representa las relaciones para el

patrón DAO:

La siguiente figura muestra el diagrama de secuencia de la interacción entre los distintos

participantes en este patrón:

Page 37: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 37 de 159

• BusinessObject :Representa los datos del cliente. Es el objeto que requiere el acceso a

la fuente de datos para obtener y almacenar datos. Podríamos implementar un

businessObject como un bean de sesión, un bean de entidad o cualquier otro objeto

Java, además de como un Servlet o como un bean de apoyo.

• DataAccessObject: es el objeto principal de este patrón. DataAccessObject abstrae la

implementación del acceso a datos subyacente al BusinessObject para permitirle un

acceso transparente a la fuente de datos. El BusinessObject también delega las

operaciones de carga y almacenamiento en el DataAccessObject.

• DataSource: Representa la implementación de la fuente de datos. Una fuente de datos

podría ser una base de datos como un RDBMS, un OODBMS, un repositorio XML, un

fichero plano, etc. También lo pueden ser otros sitemas (mainframes/legales), servicios

(servicio B2B u oficina de tarjetas de crédito), o algún tipo de repositorio (LDAP).

3.2.9.3 Generación Automática de DAO Como cada BusinessObject corresponde a un DAO específico, es posible establecer

relaciones entre el BusinessObject, el DAO, y las implementaciones subyacentes (como en

las tablas de una RDBMS). Una vez que se han establecido las relaciones, es posible

escribir una utilidad de generación-de-código-específica-de-aplicación que genere el código

para todos los DAOs que necesita la aplicación. Los meta datos para generar el DAO

pueden venir de un fichero descriptor definido por el desarrollador. Como alternativa, el

generador de código puede inspeccionar la base de datos y proporcionar los DAOs

necesarios para acceder a ella.

Si los requerimientos de los DAOs son lo suficientemente complejos, debemos considerar

la utilización de herramientas de terceras partes que proporcionan un mapeo de objeto-a-

relacional para bases de datos RDBMS. Estas herramientas normalmente incluyen

utilidades GUI para mapear los objetos de negocio a objetos de almacenamiento persistente

y además definir los DAOs intermedios. Estas herramientas generan el código

automáticamente una vez que se termina el mapeo, y podrían proporcionar otras

características valiosas como el caché de resultados y de consultas, integración con

servidores de aplicaciones, integración con otros productos de terceras partes, etc.

Page 38: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 38 de 159

3.2.9.4 Ventajas de DAO Algunas ventajas en la utilización de DAO son las siguientes:

• Permite la Transpariencia Los objetos de negocio puede utilizar la fuente de datos

sin conocer los detalles específicos de su implementación. El acceso es transparente

porque los detalles de la implementación se ocultan dentro del DAO.

• Permite una Migración más Fácil :Una capa de DAOs hace más fácil que una

aplicación pueda migrar a una implementación de base de datos diferente. Los

objetos de negocio no conocen la implementación de datos subyacente, la migración

implica cambios sólo en la capa DAO. Además, si se emplea la estrategia de

factorías, es posible proporcionar una implementación de factorías concretas por

cada implementación del almacenamiento subyacente. En este caso, la migración a

un almacenamiento diferente significa proporcionar a la aplicación una nueva

implementación de la factoría.

• Reduce la Complejidad del Código de los Objetos de Negocio : Como los DAOs

manejan todas las complejidades del acceso a los datos, se simplifica el código de

los objetos de negocio y de otros clientes que utilizan los DAOs. Todo el código

relacionado con la implementación (como las sentencias SQL) están dentro del

DAO y no en el objeto de negocio. Esto mejora la lectura del código y la

productividad del desarrollo.

• Centraliza Todos los Accesos a Datos en un Capa Independiente :Como todas las

operaciones de acceso a los datos se ha delegado en los DAOs, esto se puede ver

como una capa que aísla el resto de la aplicación de la implementación de acceso a

los datos. Esta centralización hace que la aplicación sea más sencilla de mantener y

de manejar.

3.3 Bases de Datos Orientadas a Objetos

Los modelos de bases de datos tradicionales (relacional, red y jerárquico) han sido capaces

de satisfacer con éxito las necesidades, en cuanto a bases de datos, de las aplicaciones de

gestión tradicionales. Sin embargo, presentan algunas deficiencias cuando se trata de

aplicaciones más complejas o sofisticadas como, por ejemplo, el diseño y fabricación en

ingeniería (CAD/CAM, CIM), los experimentos científicos, los sistemas de información

Page 39: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 39 de 159

geográfica o los sistemas multimedia. Los requerimientos y las características de estas

nuevas aplicaciones difieren en gran medida de las típicas aplicaciones de gestión la

estructura de los objetos es más compleja, las transacciones son de larga duración, se

necesitan nuevos tipos de datos para almacenar imágenes y textos, y hace falta definir

operaciones no estándar, específicas para cada aplicación.

Las bases de datos orientadas a objetos se crearon para tratar de satisfacer las necesidades

de estas nuevas aplicaciones. La orientación a objetos ofrece flexibilidad para manejar

algunos de estos requisitos y no está limitada por los tipos de datos y los lenguajes de

consulta de los sistemas de bases de datos tradicionales. Una característica clave de las

bases de datos orientadas a objetos es la potencia que proporcionan al diseñador al

permitirle especificar tanto la estructura de objetos complejos, como las operaciones que se

pueden aplicar sobre dichos objetos.

Otro motivo para la creación de las bases de datos orientadas a objetos es el creciente uso

de los lenguajes orientados a objetos para desarrollar aplicaciones. Las bases de datos se

han convertido en piezas fundamentales de muchos sistemas de información y las bases de

datos tradicionales son difíciles de utilizar cuando las aplicaciones que acceden a ellas está

escritas en un lenguaje de programación orientado a objetos como C++, Smalltalk o Java.

Las bases de datos orientadas a objetos se han diseñado para que se puedan integrar

directamente con aplicaciones desarrolladas con lenguajes orientados a objetos, habiendo

adoptado muchos de los conceptos de estos lenguajes.

Los fabricantes de los Sistemas gestores de Base de Datos (SGBD) relacionales también se

han dado cuenta de las nuevas necesidades en el modelado de datos, por lo que las nuevas

versiones de sus sistemas incorporan muchos de los rasgos propuestos para las bases de

datos orientadas a objetos, como ha ocurrido con Informix y Oracle. Esto ha dado lugar al

modelo relacional extendido y a los sistemas que lo implementan se les denomina sistemas

objeto–relacionales. La nueva versión de SQL, SQL:19993, incluye algunas de las

características de la orientación a objetos.

3 Este es el nombre que recibe el estándar. En ocasiones se cita como SQL3 porque así se llamaba el proyecto que lo desarrolló. También se cita como SQL99, por ser un nombre similar al de la versión anterior,

Page 40: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 40 de 159

Durante los últimos años se han creado muchos prototipos experimentales de sistemas de

bases de datos orientadas a objetos y también muchos sistemas comerciales. Conforme

éstos fueron apareciendo, surgió la necesidad de establecer un modelo estándar y un

lenguaje.

Para ello, los fabricantes de los SGBD orientadas a objetos formaron un grupo denominado

ODMG (Object Database Management Group), que propuso el estándar ODMG–93 y que

ha ido evolucionando hasta el ODMG 3.0, su última versión. El uso de estándares

proporciona portabilidad, permitiendo que una aplicación se pueda ejecutar sobre sistemas

distintos con mínimas modificaciones. Los estándares también proporcionan

interoperabilidad, permitiendo que una aplicación pueda acceder a varios sistemas

diferentes. Y una tercera ventaja de los estándares es que permiten que los usuarios puedan

comparar entre distintos sistemas comerciales, dependiendo de qué partes del estándar

proporcionan.

3.3.1 El Concepto de Orientación a Objetos

El desarrollo del paradigma orientado a objetos aporta un gran cambio en el modo en que se

ven los datos y los procedimientos que actúan sobre ellos. Tradicionalmente, los datos y los

procedimientos se han almacenado separadamente: los datos y sus relaciones en la base de

datos y los procedimientos en los programas de aplicación. La orientación a objetos, sin

embargo, combina los procedimientos de una entidad con sus datos.

Esta combinación se considera como un paso adelante en la gestión de datos. Las entidades

son unidades auto contenidas que se pueden reutilizar con relativa facilidad. En lugar de

ligar el comportamiento de una entidad a un programa de aplicación, el comportamiento es

parte de la entidad en sí, por lo en cualquier lugar en el que se utilice la entidad, se

comporta de un modo predecible y conocido.

SQL92; sin embargo, este último nombre no se ha utilizado en esta ocasión porque se quiere evitar el efecto 2000 en el nombre de futuras versiones.

Page 41: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 41 de 159

El modelo orientado a objetos también soporta relaciones de muchos a muchos, siendo el

primer modelo que lo permite. Aún así se debe ser muy cuidadoso cuando se diseñan estas

relaciones para evitar pérdidas de información.

Por otra parte, las bases de datos orientadas a objetos son navegacionales: el acceso a los

datos es a través de las relaciones, que se almacenan con los mismos datos. Esto se

considera un paso atrás. Las bases de datos orientadas a objetos no son apropiadas para

realizar consultas ad hoc, al contrario que las bases de datos relacionales, aunque

normalmente las soportan. La naturaleza navegacional de las bases de datos orientadas a

objetos implica que las consultas deben seguir relaciones predefinidas y que no pueden

insertarse nuevas relaciones “al vuelo”.

No parece que las bases de datos orientadas a objetos vayan a reemplazar a las bases de

datos relacionales en todas las aplicaciones del mismo modo en que éstas reemplazaron a

sus predecesoras.

Los objetos han entrado en el mundo de las bases de datos de formas:

• SGBD orientados a objetos puros: son SGBD basados completamente en el modelo

orientado a objetos.

• SGBD híbridos u objeto–relacionales: son SGBD relacionales que permiten

almacenar objetos en sus relaciones (tablas).

3.3.2 El Modelo de Datos Orientado a Objetos

El modelo de datos orientado a objetos es una extensión del paradigma de programación

orientado a objetos. Los objetos entidad que se utilizan en los programas orientados a

objetos son análogos a las entidades que se utilizan en las bases de datos orientadas a

objetos puros, pero con una gran diferencia: los objetos del programa desaparecen cuando

el programa termina su ejecución, mientras que los objetos de la base de datos permanecen.

A esto se le denomina persistencia.

Page 42: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 42 de 159

En una base de datos orientada a objetos, cualquier cosa es un objeto y se manipula como

tal. Un objeto es una instancia que responde a mensajes activando un método. Los objetos

soportan una serie de características de los mismos :

• Se agrupan en tipos denominados clases

• Contienen datos internos que definen su estado actual

• Soportan ocultación de datos

• Pueden heredar propiedades de otros objetos

• Pueden comunicarse con otros objetos enviando o pasando mensajes

• Tienen métodos que definen su comportamiento

3.3.2.1 Relaciones Las bases de datos relacionales representan las relaciones mediante las claves ajenas.

No tienen estructuras de datos que formen parte de la base de datos y que representen estos

enlaces entre tablas. Las relaciones se utilizan para hacer concatenaciones (join) de tablas.

Por el contrario, las bases de datos orientadas a objetos implementan sus relaciones

incluyendo en cada objeto los identificadores de los objetos con los que se relaciona.

Un identificador de objeto es un atributo interno que posee cada objeto. Ni los

programadores, ni los usuarios que realizan consultas de forma interactiva, ven o manipulan

estos identificadores directamente. Los identificadores de los objetos los asigna el SGBD y

es él el único que los utiliza.

El identificador puede ser un valor arbitrario o puede incluir la información necesaria para

localizar el objeto en el fichero donde se almacena la base de datos. Por ejemplo, el

identificador puede contener el número de la página del fichero donde se encuentra

almacenado el objeto, junto con el desplazamiento desde el principio de la página.

Hay dos aspectos importantes a destacar sobre este método de representar las relaciones

entre datos:

Page 43: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 43 de 159

• Para que el mecanismo funcione, el identificador del objeto no debe cambiar

mientras este forme parte de la base de datos.

• Las únicas relaciones que se pueden utilizar para consultar la base de datos son

aquellas que se han predefinido almacenando en atributos los identificadores de los

objetos relacionados. Por lo tanto, una base de datos orientada a objetos pura es

navegacional, como los modelos prerrelaciónales (el modelo jerárquico y el modelo

de red). De este modo se limita la flexibilidad del programador/usuario a aquellas

relaciones predefinidas, pero los accesos que siguen estas relaciones presentan

mejores prestaciones que en las bases de datos relacionales porque es más rápido

seguir los identificadores de los objetos que hacer operaciones de concatenación

(join).

El modelo orientado a objetos permite los atributos multivaluados, agregaciones a las que

se denomina conjuntos (sets) o bolsas (bags). Para crear una relación de uno a muchos, se

define un atributo en la parte del uno que será de la clase del objeto con el que se relaciona.

Este atributo contendrá el identificador de objeto del padre. La clase del objeto padre

contendrá un atributo que almacenará un conjunto de valores: los identificadores de los

objetos hijo con los que se relaciona. Cuando el SGBD ve que un atributo tiene como tipo

de datos una clase, ya sabe que el atributo contendrá un identificador de objeto.

Las relaciones de muchos a muchos se pueden representar directamente en las bases de

datos orientadas a objetos, sin necesidad de crear entidades intermedias. Para representar la

relación, cada clase que participa en ella define un atributo que contendrá un conjunto de

valores de la otra clase con la que se relacionará. Aunque el hecho de poder representar

relaciones de muchos a muchos parece aportar muchas ventajas, hay que tener mucho

cuidado cuando se utilizan. En primer lugar, si la relación tiene datos, será necesario crear

una entidad intermedia que contenga estos datos. Por ejemplo, en la relación de los

artículos con los proveedores, en donde cada proveedor puede tener un precio distinto para

un mismo artículo. En este caso, la relación de muchos a muchos se sustituye por dos

relaciones de uno a muchos, como se haría en una base de datos relacional. En segundo

lugar, se puede diseñar una base de datos que contiene relaciones de muchos a muchos en

Page 44: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 44 de 159

donde o bien se pierde información, o bien se hace imposible determinar las relaciones con

precisión. También en estos casos la solución es incluir una entidad intermedia que

represente la relación.

Ya que el paradigma orientado a objetos soporta la herencia, una base de datos orientada

a objetos también puede utilizar la relación “es un” entre objetos. Por ejemplo, en una base

de datos para un departamento de recursos humanos habrá una clase genérica Empleado

con diversos atributos: nombre, dirección, número de la seguridad social, fecha de contrato

y departamento en el que trabaja. Sin embargo, para registrar el modo de pago de cada

empleado hay un dilema. No a todos los empleados se les paga del mismo modo: a algunos

se les paga por horas, mientras que otros tienen un salario mensual. La clase de los

empleados que trabajan por horas necesita unos atributos distintos que la clase de los otros

empleados.

En una base de datos orientada a objetos se deben crear las dos subclases de empleados.

Aunque el SGBD nunca creará objetos de la clase Empleado, su presencia en el diseño

clarifica el diseño lógico de la base de datos y ayuda a los programadores de aplicaciones

permitiéndoles escribir sólo una vez los métodos que tienen en común las dos subclases

(serán los métodos que se sitúan en la clase Empleado).

En teoría, una base de datos orientada a objetos debe soportar dos tipos de herencia: la

relación “es un” y la relación “extiende”. La relación “es un”, que también se conoce como

generalización–especialización, crea una jerarquía donde las subclases son tipos

específicos de las súperclases. Con la relación “extiende”, sin embargo, una clase expande

su súperclase en lugar de estrecharla en un tipo más específico. Por ejemplo, en la jerarquía

de la clase Empleado, al igual que son necesarias clases para los empleados que realizan

cada trabajo específico, hace falta guardar información adicional sobre los directores, que

son empleados pero que también tienen unas características específicas. La base de datos

incluirá una clase Director con un atributo para los empleados a los que dirige. En este

sentido un director no es un empleado más específico sino un empleado con información

adicional.

Page 45: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 45 de 159

Una de las cosas que es difícil de manejar en las bases de datos relacionales es la idea de las

partes de un todo, como en una base de datos de fabricación, en la que hace falta saber qué

piezas y qué componentes se utilizan para fabricar un determinado producto. Sin embargo,

una base de datos orientada a objetos puede aprovechar la relación denominada “todo–

parte” en la que los objetos de una clase se relacionan con objetos de otras clases que

forman parte de él. En el caso de la base de datos de fabricación, la clase Producto se

relacionará con las clases Pieza y Componente utilizando una relación “todo–parte”. Este

tipo de relación es una relación de muchos a muchos con un significado especial. Un

producto puede estar hecho de muchas piezas y muchos componentes. Además, una misma

pieza o un mismo componente se puede utilizar para fabricar distintos productos. El

identificar esta relación como “todo–parte” permite que el diseño sea más fácil de entender.

3.3.2.2 Integridad de las Relaciones Para que las relaciones funcionen en una base de datos orientada a objetos pura, los

identificadores de los objetos deben corresponderse en ambos extremos de la relación. Por

ejemplo, si los aparejadores de una empresa de control de calidad se deben relacionar con

las obras de construcción que supervisan, debe haber algún modo de garantizar que, cuando

un identificador de un objeto Obra se incluye en un objeto Aparejador, el identificador de

este mismo objeto Aparejador se debe incluir en el objeto Obra anterior. Este tipo de

integridad de relaciones, que es de algún modo análogo a la integridad referencial en las

bases de datos relacionales, se gestiona especificando relaciones inversas.

La clase Aparejador tiene un atributo de tipo conjunto llamado supervisa. Del mismo

modo, la clase Obra tiene un atributo llamado es_supervisada. Para garantizar la

integridad de esta relación, un SGBD orientado a objetos puro deberá permitir que el

diseñador de la base de datos pueda especificar dónde debe aparecer el identificador del

objeto inverso, como por ejemplo:

relationship set<Obra> supervisa

inverse Obra::es supervisada

Page 46: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 46 de 159

en la clase Aparejador y:

relationship Aparejador es supervisada

inverse Aparejador::supervisa

en la clase Obra.

Siempre que un usuario o un programa de aplicación inserta o elimina un identificador de

objeto de la relación supervisa en un objeto Aparejador, el SGBD actualizará

automáticamente la relación es_supervisada en el objeto Obra relacionado. Cuando se

hace una modificación en el objeto Obra, el SGBD lo propagará automáticamente al objeto

Aparejador.

Del mismo modo que en las bases de datos relacionales es el diseñador de la base de datos

el que debe especificar las reglas de integridad referencial, en las bases de datos orientadas

a objetos es también el diseñador el que debe especificar las relaciones inversas cuando

crea el esquema de la base de datos.

3.3.3 El modelo Estándar ODMG

Un grupo de representantes de la industria de las bases de datos formaron el ODMG

(Object Database Management Group) con el propósito de definir estándares para los

SGBD orientados a objetos. Este grupo propuso un modelo estándar para la semántica de

los objetos de una base de datos. Los principales componentes de la arquitectura ODMG

para un SGBD orientado a objetos son los siguientes:

• Modelo de objetos.

• Lenguaje de definición de objetos (ODL).

• Lenguaje de consulta de objetos (OQL).

• Conexión con los lenguajes C++, Smalltalk y Java.

Page 47: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 47 de 159

3.3.3.1 Modelo de Objetos El modelo de objetos ODMG permite que tanto los diseños, como las implementaciones,

sean portables entre los sistemas que lo soportan. Dispone de las siguientes primitivas de

modelado:

• Los componentes básicos de una base de datos orientada a objetos son los objetos y

los literales. Un objeto es una instancia auto contenida de una entidad de interés del

mundo real. Los objetos tienen algún tipo de identificador único. Un literal es un

valor específico, como “Amparo” o 36. Los literales no tienen identificadores. Un

literal no tiene que ser necesariamente un solo valor, puede ser una estructura o un

conjunto de valores relacionados que se guardan bajo un solo nombre.

• Los objetos y los literales se categorizan en tipos. Cada tipo tiene un dominio

específico compartido por todos los objetos y literales de ese tipo. Los tipos también

pueden tener comportamientos. Cuando un tipo tiene comportamientos, todos los

objetos de ese tipo comparten los mismos comportamientos. En el sentido práctico,

un tipo puede ser una clase de la que se crea un objeto, una interfase o un tipo de

datos para un literal (por ejemplo, integer). Un objeto se puede pensar como una

instancia de un tipo.

• Lo que un objeto sabe hacer son sus operaciones. Cada operación puede requerir

datos de entrada (parámetros de entrada) y puede devolver algún valor de un tipo

conocido.

• Los objetos tienen propiedades, que incluyen sus atributos y las relaciones que

tienen con otros objetos. El estado actual de un objeto viene dado por los valores

actuales de sus propiedades.

• Una base de datos es un conjunto de objetos almacenados que se gestionan de modo

que puedan ser accedidos por múltiples usuarios y aplicaciones.

Page 48: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 48 de 159

• La definición de una base de datos está contenida en un esquema que se ha creado

mediante el lenguaje de definición de objetos ODL (Object Definition Language)

que es el lenguaje de manejo de datos que se ha definido como parte del estándar

propuesto para las bases de datos orientadas a objetos

Lenguaje de Definición de Objetos ODL es un lenguaje de especificación para definir tipos de objetos para sistemas

compatibles con ODMG. ODL es el equivalente del DDL (lenguaje de definición de datos)

de los SGBD tradicionales. Define los atributos y las relaciones entre tipos, y especifica la

signatura de las operaciones. La sintaxis de ODL extiende el lenguaje de definición de

interfaces (IDL) de la arquitectura CORBA (Common Object Request Broker Architecture).

Lenguaje de Consulta de Objetos.

OQL es un lenguaje declarativo del tipo de SQL que permite realizar consultas de modo

eficiente sobre bases de datos orientadas a objetos, incluyendo primitivas de alto nivel para

conjuntos de objetos y estructuras. Está basado en SQL-92, proporcionando un súper

conjunto de la sintaxis de la sentencia SELECT.

OQL no posee primitivas para modificar el estado de los objetos ya que las modificaciones

se pueden realizar mediante los métodos que estos poseen.

La sintaxis básica de OQL es una estructura SELECT...FROM...WHERE..., como en SQL.

Por ejemplo, la siguiente expresión obtiene los nombres de los departamentos de la escuela

de ‘Ingeniería’:

SELECT d.nombre

FROM d in departamentos

WHERE d.escuela = `Ingeniería';

En las consultas se necesita un punto de entrada, que suele ser el nombre de un objeto

persistente. Para muchas consultas, el punto de entrada es la extensión de una clase. En el

ejemplo anterior, el punto de entrada es la extensión departamentos, que es un objeto

Page 49: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 49 de 159

colección de tipo set<Departamento>. Cuando se utiliza una extensión como punto de

entrada es necesario utilizar una variable iteradora que vaya tomando valores en los objetos

de la colección. Para cada objeto de la colección (sólo la forman objetos persistentes) que

cumple la condición (que es de la escuela de ‘Ingeniería’), se muestra el valor del atributo

nombre.

El resultado es de tipo bag<string>. Cuando se utiliza SELECT DISTINCT … el

resultado es de tipo set ya que se eliminan los duplicados.

OQL tiene además otras características que no se van a presentar aquí:

• Especificación de vistas dando nombres a consultas.

• Obtención como resultado de un solo elemento (hasta ahora hemos visto que se

devuelven colecciones: set, bag, list).

• Uso de operadores de colecciones: funciones de agregados (max, min, count, sum,

avg) y cuantificadores (for all, exists).

• Uso de group by.

3.4 Sistemas Objetos-Relacionales

El modo en que los objetos han entrado en el mundo de las bases de datos relacionales es en

forma de dominios, actuando como el tipo de datos de una columna. Hay dos implicaciones

muy importantes por el hecho de utilizar una clase como un dominio:

• Es posible almacenar múltiples valores en una columna de una misma fila ya que un

objeto suele contener múltiples valores. Sin embargo, si se utiliza una clase como

dominio de una columna, en cada fila esa columna sólo puede contener un objeto de

la clase (se sigue manteniendo la restricción del modelo relacional de contener

valores atómicos en la intersección de cada fila con cada columna).

• Es posible almacenar procedimientos en las relaciones porque un objeto está

enlazado con el código de los procesos que sabe realizar (los métodos de su clase).

Page 50: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 50 de 159

Otro modo de incorporar objetos en las bases de datos relacionales es construyendo tablas

de objetos, donde cada fila es un objeto.

Ya que un sistema objeto–relacional es un sistema relacional que permite almacenar objetos

en sus tablas, la base de datos sigue sujeta a las restricciones que se aplican a todas las

bases de datos relacionales y conserva la capacidad de utilizar operaciones de

concatenación (join) para implementar las relaciones “al vuelo”.

Toda la información de la base de datos esta guardado en los tablas pero algunas

operaciones tabulares pueden tener una estructura de datos abstract data types(ADTs). Las

extensiones son necesarias porque los ORBDMSs debe de soportar ADT's. El ORDBMS

tiene un modelo relacionado porque los datos están guardados en forma de tablas con

renglones y columnas. SQL es usado como el lenguaje de búsqueda de información. Pero el

modelo relacionado tiene que ser modificado para soportar las características clásicas de

programación orientada a objeto. Las características de ORDBMSs son:

• extensión, de base de datos

• Soporte de objetos complejos,

• Herencia, y

• Reglas del Sistema.

Los ORDBMSs permiten que los usuarios puedan definir los tipos de datos, funciones y

operadores. Como resultado, los ORDBMSs tiene más funcionalidad y un mejor

desempeño

3.4.1 Diferencia entre los tres sistemas (RDBMS, ODBMS, ORDBMS)

Tabla 1: Una comparación de sistemas de Administración de Base de Datos

Criterio RDBMS ODBMS ORDBMS

Standard para definir SQL2 ODMG-2.0 SQL3 (in proceso)

Apoyo de

características

No lo apoya; Es

difícil mapear un

apoyo extensivo apoyo limitado;

mayormente con

Page 51: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 51 de 159

orientadas-objetos programa entre el

objeto y la base de

datos

datatypes

Uso Fácil de usar Bueno para

programadores;

Algún acceso de

SQL para usuarios

finales

Fácil de usar excepto

por algunas

extensiones

Apoyo para relaciones

complejas

No apoya datatypes

abstractos

Apoya una gran

variedad de

datatypes e inter-

relaciones de datos

complejos

Apoya datatypes

abstractos y

relaciones complejas

Desempeño Buen desempeño Relativamente menor

desempeño

Se espera que el

desempeño sea

mejor

Madurez del producto Relativamente viejo

y muy maduro

Este concepto tiene

un par de años y es

relativamente

maduro

Todavía está en el

proceso de

desarrollo

El uso de SQL Apoyo extensivo de

SQL

OQL es similar a

SQL, pero con

características

adicionales como

Objetos complejos y

características

orientadas a objetos

SQL3 está siendo

desarrollado con

características OO

incorporadas

Ventajas Su dependencia de

SQL, y su

optimización de

consultas es

Puede manejar todo

tipo de aplicaciones

complejas, puede

reutilizar el código

Habilidad de

consultas para

aplicaciones

complejas y la

Page 52: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 52 de 159

relativamente

sencilla

habilidad a manejar

aplicaciones grandes

y complejas

Desventajas Inhabilidad de

manejar aplicaciones

complejas

Desempeño pobre

por la optimización

de consultas

complejas, la

inhabilidad de

soportar sistemas de

gran escala

Desempeño pobre en

aplicaciones web.

Tiene apoyo de los

vendedores

Tiene un extenso

mercado y muchos

vendedores

En el presente, falta

apoyo de los

vendedores por el

tamaño del mercado

de RDBMS

Tiene un buen

futuro. Parece que

todo los vendedores

de RDBMS quieren

este producto

En el artículo "Object-Relational DBMS: The Next Wave," del Dr. Michael Stonebraker,

gerente de Tecnología de la Informix Software, ha clasificado cuatro tipos de aplicaciones

de DBMS:

Tabla 2: Categorías de DBMSs

File Systems RDBMSs OODBMSs ORDBMSs

Datos simples sin

queries

Datos simples con

queries

Datos complejos sin

queries

Datos complejos con

queries

Esos cuatro tipos describen sistemas de archivos, DBMS relacionales, DBMS orientados a

objetos, y DBMS objeto-relacional. Universal Server, creado por Informix pertenece a la

cuarta categoría. Los otros ORDBMS incluyen Oracle8 y superiores, de Oracle Corporation

y Universal DB (UDB) de IBM. También, Stonebraker predice que muy pronto todas las

aplicaciones de DBMSs (datos sencillos con queries) relacionales van a imitar los DBMS

objeto-relacional (datos complejos con query).

Page 53: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 53 de 159

Las cinco opciones de arquitectura por Dr. Stonebraker, están enlistadas en orden de

practicidad y desempeño:

• Proveen plug-in code para hacer llamadas funcionales a otras aplicaciones.

• Proveen API's esperando subsistemas del servidor para apoyar la funcionalidad de

objeto

• Simulan funcionalidad relacional-objeto en una capa de middleware

• Un motor de base de datos completamente rediseñado.

• Provee una nueva capa orientada a objetos para soportar tipos de datos

enriquecidos.

La ventaja principal del ORDBMSs es la gran escalabilidad que tienen, están diseñados

para manejar una gran cantidad de información. Pero aunque tengan muchas ventajas,

los ORDBMSs también tienen desventajas. La arquitectura de un modelo objeto

relacionado no es el mejor modelo para aplicaciones de alta velocidad en el web. Sin

embargo, los ORDBMS hacen la promesa de conquistar el mercado del mundo porque

tienen ventajas como la capacidad de guardar cantidades grandes de información y

acceso de alta velocidad. También tienen el apoyo de los vendedores principales.

3.5 Motores de Persistencia

Las opciones que se basan en imponer un único modelo teórico (un único formato de datos)

a toda la aplicación padecen de graves inconvenientes. En el caso de que toda la aplicación

siga el modelo relacional, se pierden las ventajas de la orientación a objetos. En el caso de

que toda la aplicación siga el modelo orientado a objetos, las bases de datos están

inmaduras y tienen un bajo nivel de estandarización.

Otra opción es aquella en la que el programa sea orientado a objetos y la base de datos sea

relacional, lo que, en principio, constituye la opción más natural. Sin embargo, plantea el

problema de hacer que dos componentes con formatos de datos muy diferentes puedan

comunicarse y trabajar conjuntamente.

Page 54: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 54 de 159

Se debe encontrar un traductor que sepa traducir de cada idioma al otro. Este traductor no

es más que un componente de software (concretamente, una capa de programación), al que

se le dan los nombres de “capa de persistencia”, “capa de datos”, “correspondencia O/R”

(“OR mapping”) o “motor de persistencia”.

El motor de persistencia traduce entre los dos formatos de datos: de registros a objetos y de

objetos a registros. La situación se ejemplifica en la figura 9. Cuando el programa quiere

grabar un objeto llama al motor de persistencia, que traduce el objeto a registros y llama a

la base de datos para que guarde estos registros. De la misma manera, cuando el programa

quiere recuperar un objeto, la base de datos recupera los registros correspondientes, los

cuales son traducidos en formato de objeto por el motor de persistencia.

El programa sabe que puede guardar y recuperar objetos, como si estuviera programado

para una base de datos orientada a objetos. La base de datos sabe que guarda y recupera

registros, como si el programa estuviera dirigiéndose a ella de forma relacional. Es decir,

cada uno de los dos componentes trabaja con el formato de datos (el “idioma”) que le

resulta más natural y es el motor de persistencia el que actúa de traductor entre los dos

modelos, permitiendo que los dos componentes se comuniquen y trabajen conjuntamente.

Esta solución goza de las mejores ventajas de los dos modelos.

• Por una parte, es posible programar con orientación a objetos, aprovechando las

ventajas de flexibilidad, mantenimiento y reusabilidad.

Page 55: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 55 de 159

• Por otra parte, se puede usar una base de datos relacional, aprovechando su

madurez y su estandarización así como las herramientas relacionales que existen

para ella.

Un motor de persistencia puede reducir el código de una aplicación en un cuarenta por

ciento, haciéndola menos costosa de desarrollar. Además, el código es más limpio y

sencillo y, por lo tanto, más fácil de mantener y más robusto, de tal manera que el motor de

persistencia no sólo simplifica la programación, sino que permite hacer ciertas

optimizaciones de rendimiento que serían difíciles de programar de otra manera.

En conclusión, ésta es la mejor opción en la actualidad para implementar una aplicación de

software.

3.5.1 Opciones para motores de persistencia

El motor de persistencia tiene la ventaja de que es el mismo para todas las aplicaciones. De

esta forma sólo debe programarse una vez y puede usarse para todas las demás aplicaciones

que se desarrollen en una empresa. Sin embargo, un motor de persistencia es difícil de

programar y de mantener, por lo que necesita un gran esfuerzo en costo y tiempo de

desarrollo.

Es por ello que hay dos opciones a la hora de usar un motor de persistencia:

• Programarlo, lo cual no es lo más recomendable, por la complejidad y costo que

introduce esta opción.

• Utilizar un motor que ya esté programado, comprándolo a un vendedor o bien

usando un motor gratuito de código abierto.

La segunda opción es la más recomendada, debido a que es la menos costosa y la menos

propensa a fallos. Se debe escoger un motor de persistencia de los que están programados,

estudiarlo y aplicarlo a todas las aplicaciones de una misma empresa.

En cuanto a la plataforma Java, los servidores de aplicaciones basados en la especificación

EJB (“Enterprise JavaBeans”), incorporan un motor de persistencia a través del mecanismo

conocido como “entity beans”. Sin embargo, los “entity beans” no son un mecanismo de

Page 56: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 56 de 159

persistencia totalmente recomendable, pues no permiten implementar algunas

características de la programación orientada a objetos (por ejemplo, herencia) y además,

obligan a una forma de programar diferente a los objetos normales de Java (o POJOs, por

“Plain Old Java Objects”).

Hay motores de persistencia más completos que no tienen este tipo de inconvenientes, entre

los de código abierto podemos destacar: Hibernate, Castor, Torque, OJB y Cayenne. Entre

los comerciales, podemos destacar TopLink, Cocobase y FastObjects. En los últimos años

se ha creado una especificación llamada JDO, para estandarizar la forma de programar en

Java con esos motores de persistencia. Ejemplos de motores de persistencia que cumplen el

estándar JDO son Kodo, JDO Genie, LiDo, Exadel JDO, IntelliBO, JRelay JDO (todos

ellos comerciales), TJDO y XORM (de código abierto).

La plataforma .NET, por su relativa novedad, está más inmadura que la plataforma Java.

Además, al ser una plataforma propietaria, cuesta más encontrar proyectos de código

abierto para ella. Por esto no existe tanta variedad de motores de persistencia en esta

plataforma. Microsoft anunció un motor de persistencia llamado Objectspaces para .NET

2004, sin embargo a la fecha y con el lanzamiento de .NET 2005, el producto no ha sido

liberado. Mientras tanto, se puede usar ORM.NET, que es un motor de persistencia

comercial para .NET.

3.6 Proceso de Diseño y Desarrollo de un Proyecto de Software

3.6.1 CMM El Modelo de Capacidad y Madurez o CMM (Capability Maturity Model), es un modelo de

evaluación de los procesos de una organización. Fue desarrollado inicialmente para los

procesos relativos al software por la Universidad Carnegie-Mellon para el SEI (Software

Engineering Institute).

El SEI es un centro de investigación y desarrollo patrocinado por el Departamento de

Defensa de los Estados Unidos de América y gestionado por la Universidad Carnegie-

Mellon. "CMM" es una marca registrada del SEI

Page 57: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 57 de 159

A partir de noviembre de 1986 el SEI, a requerimiento del Gobierno Federal de los Estados

Unidos de América, desarrolló una primera definición de un modelo de madurez de

procesos en el desarrollo de software, que se publicó en septiembre de 1987. Este trabajo

evolucionó al modelo CMM o SW-CMM (CMM for Software), cuya última versión (v1.1)

se publicó en febrero de 1993.

Este modelo establece un conjunto de prácticas o procesos clave agrupados en Áreas Clave

de Proceso (KPA - Key Process Area). Para cada área de proceso define un conjunto de

buenas prácticas que habrán de ser:

• Definidas en un procedimiento documentado

• Provistas (la organización) de los medios y formación necesarios

• Ejecutadas de un modo sistemático, universal y uniforme (institucionalizadas)

• Medidas

• Verificadas

• A su vez estas Áreas de Proceso se agrupan en cinco "niveles de madurez", de modo

que una organización que tenga institucionalizadas todas las prácticas incluidas en

un nivel y sus inferiores, se considera que ha alcanzado ese nivel de madurez.

Los niveles son:

1. Inicial. Las organizaciones en este nivel no disponen de un ambiente estable para el

desarrollo y mantenimiento de software. Aunque se utilicen técnicas correctas de

ingeniería, los esfuerzos se ven minados por falta de planificación. El éxito de los

proyectos se basa la mayoría de las veces en el esfuerzo personal, aunque a menudo se

producen fracasos y casi siempre retrasos y altos costos. El resultado de los proyectos

es impredecible.

2. Repetible. En este nivel las organizaciones disponen de unas prácticas

institucionalizadas de gestión de proyectos, existen unas métricas básicas y un

razonable seguimiento de la calidad. La relación con subcontratistas y clientes está

gestionada sistemáticamente.

Page 58: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 58 de 159

3 Definido. Además de una buena gestión de proyectos, a este nivel las organizaciones

disponen de correctos procedimientos de coordinación entre grupos, formación del

personal, técnicas de ingeniería más detalladas y un nivel más avanzado de métricas en

los procesos. Se implementan técnicas de revisión por pares (peer reviews).

4 Gestionado. Se caracteriza porque las organizaciones disponen de un conjunto de

métricas significativas de calidad y productividad, que se usan de modo sistemático

para la toma de decisiones y la gestión de riesgos. El software resultante es de alta

calidad.

5 Optimizado. La organización completa está volcada en la mejora continua de los

procesos. Se hace uso intensivo de las métricas y se gestiona el proceso de innovación.

Así es como el modelo CMM establece una medida del progreso conforme avanza, en

niveles de madurez. Cada nivel a su vez cuenta con un número de áreas de proceso que

deben lograrse. El alcanzar estas áreas o estadios se detecta mediante la satisfacción o

insatisfacción de varias metas claras y cuantificables. Con la excepción del primer Nivel,

cada uno de los restantes Niveles de Madurez está compuesto por un cierto número de

Áreas Claves de Proceso, conocidas a través de la documentación del CMM por su sigla

inglesa: KPA.

Cada KPA identifica un conjunto de actividades y prácticas interrelacionadas, las cuales

cuando son realizadas en forma colectiva permiten alcanzar las metas fundamentales del

proceso. Las KPAs pueden clasificarse en 3 tipos de proceso: Gestión, Organizacional e

Ingeniería.

Las prácticas que deben ser realizadas por cada Area Clave de Proceso están organizadas en

5 Características Comunes, las cuales constituyen propiedades que indican si la

implementatción y la institucionalización de un proceso clave es efectivo, repetible y

duradero.

Estas 5 características son: i)Compromiso de la realización, ii) La capacidad de realización,

iii) Las actividades realizadas, iv) Las mediciones y el análisis, v) La verificación de la

implementación.

Page 59: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 59 de 159

Las organizaciones que utilizan CMM para mejorar sus procesos disponen de una guía útil

para orientar sus esfuerzos. Además, el SEI proporciona formación a evaluadores

certificados (Lead Assesors) capacitados para evaluar y certificar el nivel CMM en el que

se encuentra una organización. Esta certificación es requerida por el Departamento de

Defensa de los Estados Unidos, pero también es utilizada por multitud de organizaciones de

todo el mundo para valorar a sus subcontratistas de software.

Se considera típico que una organización dedique unos 18 meses para progresar un nivel,

aunque algunas consiguen mejorarlo. En cualquier caso requiere un amplio esfuerzo y un

compromiso intenso de la dirección.

Como consecuencia, muchas organizaciones que realizan funciones de factoría de software

o, en general, outsourcing de procesos de software, adoptan el modelo CMM y se certifican

en alguno de sus niveles. Esto explica que uno de los países en el que más organizaciones

certificadas exista sea India, donde han florecido las factorías de software que trabajan para

clientes estadounidenses y europeos.

A partir de 2001, en que se presentó el modelo CMMI, el SEI ha dejado de desarrollar el

SW-CMM, cesando la formación de los evaluadores en diciembre de 2003, quienes

dispondrán hasta fin de 2005 para reciclarse al CMMI. Las organizaciones que sigan el

modelo SW-CMM podrán continuar haciéndolo, pero ya no podrán ser certificadas a partir

de fin de 2005.

3.6.1.1 SW-CMM Vs CMMI El objetivo de esta sección es presentar un panorama general y un comparativo sobre los

dos modelos de madurez del SEI (Software Engineering Institute) que han tenido más

aceptación para las organizaciones y áreas que se dedican al desarrollo del software y que

últimamente han generado gran controversia en la comunidad mundial: SW-CMM y

Page 60: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 60 de 159

CMMI. Esto con la finalidad de que el lector se forme una idea de la razón de ser de los

mismos, la audiencia hacia la cual están enfocados y los aspectos que cubren.

Antes de iniciar con nuestra revisión es importante mencionar que la aplicabilidad de los

modelos para la mejora de procesos depende de la situación y del tipo de cada

organización, ya que los programas de mejora deben estar basados en la misión y los

objetivos del negocio que tenga cada organización.

SW-CMM (Software Capability Maturity Model)

Es el modelo más utilizado en la industria de software, no sólo en los Estados Unidos

(EE.UU.), sino en el mundo entero, por lo que representa el estándar de facto de la

industria de software.

Mide la capacidad de proceso para desarrollar software con calidad, incrementando la

predectibilidad para terminar los proyectos en costo, tiempo y con la calidad que el cliente

espera. El modelo fue creado a solicitud de la DoD (Department of Defense) de EE.UU. y

rápidamente fue adoptado por la industria para evaluar a los proveedores de software de

manera estándar y objetiva.

Actualmente el SW-CMM, en su versión 1.1, está organizado en 5 niveles de madurez, con

18 áreas clave (KPAs), con 52 metas que requieren de 316 prácticas comunes (tales como

habilidades a desarrollar, compromisos de la gerencia, métricas y revisiones para verificar

la implantación de las actividades requeridas). Su enfoque está orientado en generar,

implantar y mejorar las prácticas de ingeniería de software, considerando al desarrollo de

software como producto principal.

El SW-CMM ha demostrado ser un diferenciador importante de nivel comercial, pues

además de permitir mejorar internamente los procesos de las organizaciones, representa una

manera estándar e internacional de comparar (hacer benchmarking) objetivamente a

diferentes proveedores. De hecho, el Departamento de Defensa de EE.UU. requiere que

todos sus proveedores de software sean nivel 3 o superior. Este requerimiento se ha

extendido en la mayoría de las grandes empresas de EE.UU. que subcontratan empresas

para el desarrollo de sus sistemas de software y por lo mismo la industria de desarrollo de

Page 61: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 61 de 159

software en la India ha tenido un gran auge. Si bien es un modelo general, debido a que nos

presenta un marco de referencia para generar nuevas capacidades de desarrollar software,

su fortaleza radica en la flexibilidad que proporciona para que las organizaciones adapten el

modelo a su forma de trabajo, sin forzarlos a utilizar determinadas herramientas o

metodologías. Es un modelo totalmente orientado a la industria de software, lo cual implica

que puede ser aplicado tanto a empresas que se dediquen exclusivamente al desarrollo de

sistemas de software, o a aquellas que necesitan hacer integración de hardware y software.

Las industrias que son usuarias del modelo SW-CMM, numéricamente, tienen el siguiente

perfil: 689 de 1018 empresas evaluadas formalmente por el SEI son industrias comerciales

(67.7%), mientras que sólo 329 (32.3%) pertenecen a la industria militar, o son contratistas

de los mismos. De las primeras, el 40% de las empresas tienen 100 o menos empleados y

el 60% tienen 200 empleados o menos, lo cual indica que la mayoría de las empresas

usuarias del modelo son empresas medianas o pequeñas.

En una entrevista al Dr. Pankaj Jalote, Ex-Vicepresidente de Calidad de Infosys, una de las

pocas empresas que han obtenido el nivel 5 de SW-CMM, comentó textualmente, que la

razón por la cual en la India se había adoptado el SW-CMM, era muy sencilla y lógica ya

que la industria de software de la India ha estado y está orientada a la exportación de

software a diversos países, principalmente a EE.UU. y Europa, países que han determinado

el desarrollo de software bajo estándares internacionales. Debido a que sus principales

compradores están esparcidos por todo el mundo, la industria de desarrollo de software de

la India necesitaba seguir un marco de referencia globalmente aceptado y alineado a los

estándares internacionalmente reconocidos. Esto generó la necesidad de adoptar (C)

modelos como ISO 9000 y SW-CMM. El Dr. Jalote se remontó a la historia de la industria

de la India y nos comentó que al inicio, sus principales clientes eran empresas europeas y

por lo tanto el primer estándar que adoptaron fue ISO 9000, ya que era el requerimiento del

mercado para poder adquirir el software desarrollado por la India. De esta manera, las

empresas exportadoras de software de la India, entre 1993 y 1996, se certificaron en ISO

9000. Más adelante tuvieron que evolucionar a un nuevo estándar ya que el mercado y sus

principales compradores, en este caso EE.UU., cambiaron el requerimiento hacia SW-

CMM, y por lo tanto las empresas de la India para seguir en el negocio de desarrollo y

exportación de software, dejaron atrás la certificación ISO 9000 y cambiaron al modelo de

SW-CMM. Actualmente existen 64 empresas que están en nivel 5 y 51 de éstas son

Page 62: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 62 de 159

empresas de la India. Resumiendo lo anterior y citando las palabras Dr. Jalote la razón

principal es " market-driven", o como dice un conocido refrán mexicano “Dale al cliente lo

que pida”.

CMMI (Capability Maturity Model Integrated) Es un nuevo modelo del SEI que fue creado a solicitud del DoD para las organizaciones

con iniciativas de ingeniería de software, ingeniería de sistemas o industrias que requieran

integración (software + hardware). La intención de este nuevo modelo es consolidar y

agrupar una familia de modelos que ya estaban siendo utilizados y reconciliar estos

modelos con los estándares y metodologías (como ISO/IEC/TR 15504).

La base del CMMI está constituida por los modelos SW-CMM, SA-CMM (Software

Acquisition Capability Maturity Model), IPD-CMM (Integrated Product Development

Capability Maturity Model) y SE-CMM(Systems Engineering Capability Maturity Model).

El CMMI es un modelo nuevo y aunque se han liberado varias versiones, todavía no son

estables debido a las modificaciones y sugerencias de cambio que se están realizando sobre

la versión aprobada. La última versión liberada es la 1.02, y está en vías de liberación la

1.1.

Existen dos versiones de este modelo, la escalonada (staged) y la continua (continuos).

Aunque los expertos y algunos opositores a este modelo opinan que no existe una clara

diferencia entre el modelo escalonado y el continuo, ya que el escalonado es más continuo

de lo que aparenta.

La versión escalonada del modelo tiene 5 niveles, como el SW-CMM versión 1.1, que

contienen 24 áreas de proceso (PAs), con 78 metas que se alcanzan al implantar las 618

prácticas comunes. Para la versión continua del modelo existen 6 niveles de madurez, que

contienen 24 áreas de proceso (PAs), con 174 metas que se deben alcanzar y 455 prácticas

comunes.

El modelo del CMMI tiene el propósito de proporcionar una guía unificada para la mejora

de múltiples disciplinas tales como ingeniería de sistemas, ingeniería de software, etc. Sin

embargo, mucho se ha escrito y discutido sobre el tema de que las empresas que en realidad

Page 63: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 63 de 159

necesitan una guía de este tipo, son las grandes organizaciones (proveedores del

Departamento de Defensa, principalmente) cuyos proyectos involucran múltiples

disciplinas; mientras que la gran mayoría de los usuarios actuales del modelo SW-CMM

son pequeñas organizaciones y/o áreas de desarrollo de software, que no utilizan o no

necesitan otras disciplinas mas que la de ingeniería de software y ésta es el foco principal

del SW-CMM.

La situación actual del CMMI en el mercado norteamericano, es incierta ya que a pesar de

tener la presión del Departamento de Defensa por adaptar este nuevo modelo, muchas

empresas han comentado que el CMMI no se adapta a sus necesidades, debido a que hay

muchos elementos que resultan sobrados para empresas pequeñas-medianas cuyo negocio

principal es el desarrollo de software, y no la integración de tecnología o hardware, que es

el enfoque principal del nuevo modelo. Adicionalmente al esfuerzo requerido para la

implantación de las nuevas prácticas del CMMI, es necesario considerar el esfuerzo

necesario para la capacitación y para la evaluación formal. El método de evaluación para el

nuevo modelo se denomina SCAMPI (Standard CMMI Assessment Method for Process

Improvement) y para realizar una evaluación se requieren considerar varios meses debido a

la visión global que refleja el modelo.

La percepción en la industria internacional, es que este modelo se adapta más a empresas

grandes, que requieren de diversas disciplinas. La transición del SW-CMM al CMMI

requiere una inversión fuerte, incluso para las organizaciones que son maduras en el

modelo SW-CMM (niveles 3, 4), ya que se requiere realizar un esfuerzo extra para cubrir

las nuevas áreas de proceso (en niveles inferiores y superiores), lograr un nuevo cambio de

cultura y capacitar a la organización en el nuevo modelo de referencia.

En la conferencia del SEPG que se realizó el pasado febrero en Phoenix, se presentaron

diversas conferencias y paneles de discusión sobre este tema y principalmente nos interesó

una conferencia que presentó el tema "CMMI not for the little guy?", impartida por

Margaret Kulpa de Agile Dim Inc. El tema de la conferencia se enfocó al cuestionamiento

de si el modelo CMMI se adapta a las organizaciones pequeñas, dónde el término

“pequeñas” se utilizaba en el contexto de 20 o menos empleados, con 2 o 3 empleados por

Page 64: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 64 de 159

proyecto, donde el personal asignado al proyecto desempeña varios roles y los proyectos

tienen una duración de 3 a 6 semanas. A continuación se resumen algunos puntos de esta

presentación con la finalidad de formar al lector con ideas más concretas de las

implicaciones de este modelo en empresas pequeñas, como es el caso de muchas empresas

mexicanas.

El modelo del CMMI no provee guías de ajuste para adaptar el modelo a las organizaciones

pequeñas. Esta guía es necesaria, debido a que la estructura del modelo (diseñada para

muchos recursos asignados a proyectos, con muchos roles, proyectos muy largos que

pueden durar años y cuestan millones de dólares). CMMI se basa en prácticas de

organizaciones grandes, y está enfocado para organizaciones del departamento de defensa o

aeronáutica.

CMMI es demasiado grande para que pueda ser manejado en organizaciones pequeñas. El

CMM ha sido criticado por tener muchas áreas clave, pero CMMI tiene muchas mas. Esto

implica que la documentación de procesos que cubra las prácticas del modelo puede ser

agobiante para las organizaciones pequeñas, y por lo tanto, el tiempo, costo y recursos para

la documentación pueden crecer exponencialmente.

El retorno de inversión (ROI) del CMMI no ha sido validado (especialmente en

organizaciones pequeñas). El retorno de inversión, suele ser uno de los principales

justificaciones para invertir en programas de mejora. Este punto es especialmente

importante para las organizaciones pequeñas donde, la mayoría de las veces no se cuenta

con un gran presupuesto e indudablemente el pago de la nómina cada dos semanas es una

preocupación mayor. Actualmente no se tienen estudios que ayuden a calcular el ROI para

el CMMI.

Las organizaciones pequeñas se administran de manera diferente a las grandes y enfrentan

retos diferentes. El principal móvil de negocio para las empresas pequeñas es el tiempo de

salida al mercado (time-to-market) de sus productos, por lo que la entrega rápida de

productos es muy importante para éstas, y para el CMMI ese "time-to-market" no parece

ser una fuerza impulsora.

CMMI fue escrito para organizaciones maduras. El material introductorio de las primeras

versiones del modelo escalonado (CMMI staged), decía que las organizaciones evaluadas

Page 65: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 65 de 159

en niveles superiores del SW-CMM deberían utilizar el CMMI. La mayoría de este tipo de

organizaciones son grandes, y por lo general ya han trabajado en programas de mejora o

han alcanzado un buen entendimiento de lo que significa la mejora de procesos. El

requerimiento de CMMI para el programa de métricas es complicado y sofisticado desde el

nivel 2, y aunque la definición de métricas es importante para cualquier programa de

mejora esto puede ser difícil de implantar en una organización principiante.

Podríamos seguir listando una serie de elementos que han sido criticados en el nuevo

modelo de CMMI y las inquietudes que existen, incluso en la industria estadounidense y en

el propio SEI, en cuanto a la aceptación por el modelo. Esto nos hace reflexionar sobre la

dificultad que representa para las empresas mexicanas la adopción de este nuevo modelo.

Sobre todo para aquellas que no tienen experiencia anterior con un programa de mejora

basado en el SW-CMM.

Actualmente no hay muchas organizaciones que hayan adoptado o estén haciendo la

transición hacia el nuevo modelo. Incluso los grandes corporativos norteamericanos tienen

que realizar una fuerte inversión para hacer la transición.

Lo que la comunidad internacional está pidiendo es que se mantengan los dos modelos, se

libere la versión 2 del SW-CMM que actualmente está en versión borrador y permitir que el

mercado decida cual de los dos modelos debe utilizar con base en sus necesidades y

objetivos de negocio (SW-CMM vs. CMMI).

Finalmente, nos gustaría comentar que el éxito del proyecto no está en la selección de un

modelo en particular, sino en establecer un programa de mejora que establezca nuevas

prácticas y disciplinas de trabajo para el desarrollo de software utilizando un modelo como

un marco de referencia que ayude a las organizaciones a lograr sus objetivos de negocio. Lo

recomendable es que éste sea reconocido mundialmente con el objetivo de ser comparable

con otros proveedores en mercados internacionales.

3.6.2 El RUP y el Proceso Unificado Los orígenes de RUP se remontan al modelo espiral original de Barry Boehm. Ken

Hartman, uno de los contribuidores claves de RUP colaboró con Boehm en la

investigación. En 1995 Rational Software es comprada por una compañia sueca llamada

Page 66: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 66 de 159

Objectory AB. El Rational Unified Process fue el resultado de una convergencia de

Rational Approach y Objectory, proceso desarrollado por el fundador de Objectory Ivan

Jacobson. El primer resultado de esta fusión fue el Rational Objectory Process, la primera

versión de RUP, fue puesta en el mercado en 1998, siendo el arquitecto en jefe Philippe

Kruchten.

El Proceso Racional Unificado o RUP (Rational Unified Process), es un proceso de

desarrollo de software y junto con el Lenguaje Unificado de Modelado UML, constituye la

metodología estándar más utilizada para el análisis, implementación y documentación de

sistemas orientados a objetos. RUP es en realidad un refinamiento realizado por Rational

Software del más genérico Proceso Unificado.

Sus principales características son:

• Forma disciplinada de asignar tareas y responsabilidades (quién hace qué, cuándo y

cómo)

• Pretende implementar las mejores prácticas en Ingeniería de Software

• Desarrollo interactivo

• Administración de requisitos

• Uso de arquitectura basada en componentes

• Control de cambios

• Modelado visual del software

• Verificación de la calidad del software

El RUP es un producto de Rational (IBM). Se caracteriza por ser interactivo e incremental,

estar centrado en la arquitectura y guiado por los casos de uso. Incluye artefactos (que son

los productos tangibles del proceso como por ejemplo, el modelo de casos de uso, el código

fuente, etc.) y roles (papel que desempeña una persona en un determinado momento, una

persona puede desempeñar distintos roles a lo largo del proceso).

Page 67: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 67 de 159

3.6.2.1 Fases del RUP

El RUP divide el proceso de desarrollo en ciclos, teniendo un producto final al final de cada

ciclo, cada ciclo se divide en fases que finalizan con un hito donde se debe tomar una

decisión importante:

1. Inicio (Inception): se hace un plan de fases, se identifican los principales casos de uso

y se identifican los riesgos

2. Elaboración (Elaboration): se hace un plan de proyecto, se completan los casos de uso

y se eliminan los riesgos

3. Construcción (Construction): se concentra en la elaboración de un producto

totalmente operativo y eficiente y el manual de usuario

4. Transición (Transition): se implementa el producto en el cliente y se entrena a los

usuarios. Como consecuencia de esto suelen surgir nuevos requisitos a ser analizados.

3.6.2.2 El RUP y la orientación a Objetos.

Aunque RUP es un proceso de desarrollo de software genérico, se concibió en gran medida

para el desarrollo de sistemas basados en P.O.O. Por ejemplo se suele emplear RUP en

proyectos de programación en Lenguajes como Java o .NET, etc. Al ser genérico, tiene

muchas aplicaciones y se pueden realizar las adecuaciones necesarias al proceso, según la

naturaleza del proyecto que se desea afrontar.

3.6.3 Microsoft Solution Framework Microsoft Solutions Framework (MSF) es un proceso de desarrollo de software altamente

customizable, escalable e integrado. Actualmente junto al producto Visual Studio 2005

Team system ofrece una serie de herramientas con las cuales puede ser aplicado a proyectos

pequeños denominados MSF for Agile Software Development y a proyectos de gran

envergadura denominado MSF for CMMI® Process Improvement

Page 68: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 68 de 159

Microsoft Solutions Framework (MSF) es una flexible e interrelacionada serie de

conceptos, modelos y prácticas de uso que controlan la planificación, el desarrollo y la

gestión de proyectos tecnológicos. MSF se centra en los modelos de proceso y de equipo

dejando en un segundo plano las elecciones tecnológicas. Originalmente creado en 1994

para conseguir resolver los problemas a los que se enfrentaban las empresas en sus

respectivos proyectos, se ha convertido posteriormente en un modelo práctico que facilita el

éxito de los proyectos tecnológico

MSF se compone de varios modelos encargados de planificar las diferentes partes

implicadas en el desarrollo de un proyecto: Modelo de Arquitectura del Proyecto, Modelo

de Equipo, Modelo de Proceso, Modelo de Gestión del Riesgo, Modelo de Diseño de

Proceso y finalmente el modelo de Aplicación.

• Modelo de Equipo: Este modelo ha sido diseñado para mejorar el rendimiento del

equipo de desarrollo. Proporciona una estructura flexible para organizar los equipos

de un proyecto. Puede ser escalado dependiendo del tamaño del proyecto y del

equipo de personas disponibles. Para obtener más información puedes consultar el

Documento del Modelo de Equipo

• Modelo de Proceso: Diseñado para mejorar el control del proyecto, minimizando el

riesgo, y aumentar la calidad acortando el tiempo de entrega. Proporciona una

estructura de pautas a seguir en el ciclo de vida del proyecto, describiendo las fases,

las actividades, la liberación de versiones y explicando su relación con el Modelo de

equipo. Puedes encontrar su descripción en el Documento del Modelo de Proceso

• Disciplina de Gestión de Riesgos: Diseñada para ayudar al equipo a identificar las

prioridades, tomar las decisiones estratégicas correctas y controlar las emergencias

que puedan surgir. Este modelo proporciona un entorno estructurado para la toma

de decisiones y acciones valorando los riesgos que puedan provocar. Consulta la

base del modelo en el Documento de la Disciplina de Gestión de Riesgos

Page 69: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 69 de 159

• Disciplina de Gestión de Proyectos: Es una disciplina que describe el rol de la

gestión del proyecto dentro del modelo de equipo de MSF, y como permite mayor

escalabilidad, desde proyectos pequeños a proyectos largos y complejos. Puedes

encontrar la descripción de esta disciplina el el Documento de la Disciplina de

Gestión de Proyectos

• Disciplina de Gestión de la Preparación (Readiness): Esta disciplina describe

aquellos conocimientos, aptitudes y habilidades que son necesarias para planificar,

desarrollar y gestionar soluciones satisfactorias. Se puede consultar en el

Documento de la Disciplina de Gestión de la Preparación

Para una mayor información sobre el MSF puede visitar la página http://www.microsoft.com/msf

3.7 Microsoft .Net Framework

Microsoft .NET es una plataforma de desarrollo y ejecución de aplicaciones. que brinda las

herramientas y servicios que se necesitan para desarrollar modernas aplicaciones

empresariales y de misión crítica, y que también provee mecanismos robustos, seguros y

eficientes para asegurar que la ejecución de las mismas sea óptima. Los componentes

principales de la plataforma .NET son:

• Un entorno de ejecución de aplicaciones, también llamado “Runtime”, que es un

componente de software cuya función es la de ejecutar las aplicaciones .NET e

interactuar con el sistema operativo ofreciendo sus servicios y recursos.

• Un conjunto de bibliotecas de funcionalidades y controles reutilizables, con una

enorme cantidad de componentes ya programados listos para ser consumidos por

otras aplicaciones.

Page 70: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 70 de 159

• Un conjunto de lenguajes de programación de alto nivel, junto con sus compiladores

y linkers, que permitirán el desarrollo de aplicaciones sobre la plataforma .NET.

• Un conjunto de utilitarios y herramientas de desarrollo para simplificar las tareas

más comunes del proceso de desarrollo de aplicaciones.

• Documentación y guías de arquitectura, que describen las mejores prácticas de

diseño, organización, desarrollo, prueba e instalación de aplicaciones .NET

Por otra parte, .NET representa la evolución COM (Component Object Model), la

plataforma de desarrollo de Microsoft anterior a .NET y sobre la cual se basaba el

desarrollo de aplicaciones Visual Basic 6.

Entre los factores que motivaron el desarrollo e introducción al mercado de la plataforma

Microsoft .NET. se pueden mencionar:

- La amplia disponibilidad de conexiones a Internet de alta velocidad, e incluso

inalámbricas

- La proliferación de nuevos tipos de dispositivos de hardware que son usados en la

vida diaria (teléfonos inteligentes, Pocket PC’s, HandHelds, Media Centers, etc.)

- El creciente poder de cómputo de las computadoras personales y servidores basados

en arquitecturas x86.

- El surgimiento de estándares de Internet para permitir la comunicación e integración

entre diversas plataformas de software

.NET no es un sistema operativo, como lo es Microsoft Windows en sus distintas

versiones.

.NET no es un Lenguaje de Programación: si bien la plataforma Microsoft .NET

incluye lenguajes de programación de aplicaciones, su concepto es más amplio y va

más allá de éstos.

Page 71: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 71 de 159

.NET no es un Entorno de Desarrollo: si bien la plataforma Microsoft .NET incluye

entornos de desarrollo integrados (IDEs), su concepto es más amplio y va más allá de

éstos.

.NET no es un servidor de aplicaciones (Application Server)

.NET no es un producto empaquetado que se pueda comprar como tal, sino que es una

plataforma que engloba distintas aplicaciones, servicios y conceptos y que en conjunto

permiten el desarrollo y la ejecución de aplicaciones.

3.7.1 Características Algunas de las características principales de la plataforma Microsoft .NET son:

• Se dice que es una plataforma de ejecución intermedia, ya que las aplicaciones

.NET no son ejecutadas directamente por el sistema operativo, como ocurre en el

modelo tradicional de desarrollo. En su lugar, las aplicaciones .NET están diseñadas

para ser ejecutadas contra un componente de software llamado Entorno de

Ejecución (muchas veces también conocido como “Runtime”, o , “Máquina

Virtual”). Este componente es el encargado de manejar el ciclo de vida de cualquier

aplicación .NET, iniciándola, deteniéndola, interactuando con el Sistema Operativo

y proveyéndole servicios y recursos en tiempo de ejecución.

• La plataforma Microsoft .NET está completamente basada en el paradigma de

Orientación a Objetos.

• .NET es multi-lenguaje: esto quiere decir que para poder codificar aplicaciones

sobre esta plataforma no es necesario aprender un único lenguaje específico de

programación de alto nivel, sino que se puede elegir de varias opciones.

• .NET es una plataforma que permite el desarrollo de aplicaciones empresariales de

misión crítica, entendiéndose por esto que permite la creación y ejecución de

aplicaciones de porte corporativo que sean críticas para la operación de tipos

variados de organizaciones. Puede soportar aplicaciones grandes y complejas.

• .Net fue diseñado de manera tal de poder proveer un único modelo de

programación, uniforme y consistente, para todo tipo de aplicaciones (ya sean de

formularios Windows, de consola, aplicaciones Web, aplicaciones móviles, etc.) y

Page 72: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 72 de 159

para cualquier dispositivo de hardware (PC’s, Pocket PC’s, Teléfonos Celulares

Inteligentes, también llamados “SmartPhones”, Tablet PC’s, etc.). Esto representa

un gran cambio con respecto a las plataformas anteriores a .NET, las cuales tenían

modelos de programación, bibliotecas, lenguajes y herramientas distintas según el

tipo de aplicación y el dispositivo de hardware.

• Uno de los objetivos de diseño de .NET fue que tenga la posibilidad de interactuar e

integrarse fácilmente con aplicaciones desarrolladas en plataformas anteriores,

particularmente en COM, ya que aún hoy existen una gran cantidad de aplicaciones

desarrolladas sobre esa base.

• .NET no sólo se integra fácilmente con aplicaciones desarrolladas en otras

plataformas Microsoft, sino también con aquellas desarrolladas en otras plataformas

de software, sistemas operativos o lenguajes de programación. Para esto hace un uso

extensivo de numerosos estándares globales que son de uso extensivo en la

industria, algunos ejemplos de estos estándares son XML, HTTP, SOAP, WSDL y

UDDI.

El .NET Framework es el componente fundamental de la plataforma Microsoft .NET,

necesario tanto para poder desarrollar aplicaciones como para poder ejecutarlas luego en

entornos de prueba o producción.

El .NET framework tiene tres variantes principales, todas descargables gratuitamente desde

Internet

• .NET Framework Redistributable Package: mínimo componente de la plataforma

.NET que se necesita para poder ejecutar aplicaciones. Normalmente ésta es la

variante que se instala en los entornos productivos, una vez que el desarrollo y las

pruebas de la aplicación han finalizado.

Está compuesto por:

• El entorno de ejecución de la plataforma .NET

• Las bibliotecas de funcionalidad reutilizable

• .NET Framework SDK: esta versión contiene herramientas de desarrollo de línea de

comandos (compiladores, depuradores, etc.), documentación de referencia, ejemplos

Page 73: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 73 de 159

y manuales para desarrolladores de aplicaciones. Normalmente ésta variante se

instala en los entornos de desarrollo de aplicaciones, y es más útil a los

programadores que a los usuarios finales. Para poder instalar la versión SDK

(Software Development Kit) es necesario instalar previamente el Redistributable

Package.

• NET Compact Framework: esta es una versión reducida del .NET Framework

Redistributable, especialmente pensada para ser instalada en dispositivos móviles

como Pocket PC’s y SmartPhones.

El .NET Framework puede ser instalado en cualquier sistema operativo de la familia

Windows superior a Windows 98, actualmente, Windows 2003 Server y Windows XP SP2

traen el .NET Framework preinstalado.

El .NET Framework debe estar instalado en cualquier dispositivo de hardware para que la

ejecución de una aplicación .NET sea posible. En el caso de las aplicaciones de escritorio

(también llamadas “De Formularios Windows”) y las aplicaciones de consola (aplicaciones

cuya interfaz de usuario es una consola de comandos), el Framework debe estar presente

del lado del cliente (computadora donde se ejecuta la parte de la aplicación que interactúa

con el usuario), y en el servidor sólo en caso de que la aplicación sea distribuida y tenga

parte de su funcionalidad centralizada en una única computadora.

En el caso de las aplicaciones Web, el único requisito del lado del cliente es tener un

navegador y una conexión de red al servidor, el cual debe tener instalado el .NET

Framework.

Para las aplicaciones móviles, que se ejecutan sobre Windows Mobile en algún dispositivo

tipo Pocket PC o SmartPhone, es necesario tener instalado el .NET Compact Framework en

el dispositivo.

Page 74: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 74 de 159

Actualmente hay 3 versiones de la plataforma Microsoft .NET:

• La versión 1.0: fue liberada a principios del año 2002, e incluía la versión 1.0 del

.NET Framework, la versión 2002 de Visual Studio y varios lenguajes de

programación nuevos compatibles con la plataforma (como C#.NET y Visual

Basic.NET)

• La versión 1.1: fue liberada en 2003, aproximadamente un año después que su

predecesora. Esta versión introdujo el .NET Framework 1.1 junto con Visual Studio

.NET 2003, la primer versión del .NET Compact Framework y un nuevo lenguaje

de programación llamado J#.NET.

• La versión 2.0: fue liberada a finales del año 2005, esta versión trajo consigo las

versiones 2.0 del .NET Framework y el .NET Compact Framework, así como

también una nueva versión de Visual Studio.

La próxima generación de la plataforma .NET, tendrá por nombre código “Orcas”.

.NET Compact Framework

����* ����

����

����* ����

Aplicación

Móvil

Aplicación de

Consola

Aplicación Web

Aplicación de

Escritorio

¿¿DDóónnddee iinnssttaallaarr eell ..NNEETT FFrraammeewwoorrkk??

ServidorServidorServidorServidor ClienteClienteClienteCliente

** SSóólloo ssii llaa aapplliiccaacciióónn eess ddiissttrriibbuuiiddaa

Page 75: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 75 de 159

3.7.2 Arquitectura

Windows COM+ Services

Common Language Runtime

Base Class Library

ADO.NET y XML

ASP.NET Windows Forms

Common Language Specification

VB C++ C# J# …

AArrqquuiitteeccttuurraa ddeell ..NNEETT FFrraammeewwoorrkk

.NE

T F

ram

ew

ork

R

edis

trib

uta

ble

.NE

T F

ram

ew

ork

SD

K

.NE

T F

ram

ew

ork

C

lass L

ibra

ry

CCrroonnoollooggííaa ddee ..NNEETT

Visual Studio 6.0 Visual Basic VBA Visual FoxPro VBScript C++ J++ JScript ASP

Visual Studio .NET 2003 .NET Framework 1.1 .NET Compact Framework J#

Visual Studio “Orcas” .NET Framework “Orcas” .NET Compact Framework “Orcas”

2000 2001 2002 2003 2004 2005 2006 y más

Visual Studio 2005 (“Whidbey”) .NET Framework 2.0 (“Whidbey”) .NET Compact Framework 2.0 (“Whidbey”)

Visual Studio .NET 2002 .NET Framework 1.0 Visual Basic .NET C#

Page 76: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 76 de 159

En la figura se pueden apreciar las distintas partes que componen al .NET Framework,

incluidas el entorno de ejecución de aplicaciones (CLR, en verde), el conjunto de

bibliotecas de funcionalidad reutilizable (.NET Framework Class Library, en azul) y los

compiladores y herramientas de desarrollo para los lenguajes .NET (en rojo). Todos estos

componentes se motan por encima de la familia de sistemas operativos Windows.

Dentro del conjunto de la .NET Framework Class Library se distinguen 4 sub-componentes

principales:

• La Base Class Library (BCL - Biblioteca de Clases Base), que contiene la

funcionalidad más comúnmente utilizada para el desarrollo de todo tipo de

aplicaciones. Algunos ejemplos de la funcionalidad provista por la BCL son el

manejo de colecciones, cadenas de texto, entrada/salida, threading, operaciones

matemáticas y dibujos 2D.

• ADO.NET, que contiene un conjunto de clases que permiten interactuar con bases

de datos relacionales y documentos XML como repositorios de información

persistente.

• ASP.NET, que constituye la tecnología dentro del .NET Framework para construir

aplicaciones con interfaz de usuario Web (es decir, aplicaciones cuya lógica se

encuentra centralizada en uno o varios servidores y que los clientes pueden acceder

usando un browser o navegador mediante una serie de protocolos y estándares como

HTTP y HTML).

• Windows Forms (o simplemente WinForms), que constituye la tecnología dentro

del .NET Framewok que permite crear aplicaciones con interfaz de usuario basada

en formularios y ventanas Windows que se ejecutan directamente en los clientes.

El modelo de ejecución que propone la plataforma .NET se suele definir como “virtual”, o

“de máquina virtual”, ya que las aplicaciones no son desarrolladas directamente contra las

APIs de programación expuestas por el sistema operativo, ni es éste el que se encarga de su

ejecución y ciclo de vida, sino que .NET provee un entorno de ejecución (el CLR) que

corre por sobre el sistema operativo y que es el encargado de ejecutar las aplicaciones y

proveerles servicios en tiempo de ejecución. A los componentes de software que se

Page 77: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 77 de 159

ejecutan de esta manera se los conoce comúnmente como “componentes manejados”, ya

que su ejecución es controlada por un entorno intermedio.

Una de las principales ventajas de contar con una plataforma virtual es que no están

“atadas” de ninguna forma con el sistema operativo y la plataforma de hardware

subyacente. Es sabido que una aplicación compilada para que utilice directamente las APIs

y servicios expuestos por un sistema operativo “x” muy difícilmente pueda ser ejecutada

en otro sistema operativo distinto sin ser recompilada. Las aplicaciones manejadas, en

cambio, descansan la tarea de su compilación a un código de máquina específico en el

entorno de ejecución. De esta manera, si existen distintos entornos de ejecución intermedia

para diferentes Sistemas Operativos, la misma aplicación puede ejecutarse en todos ellos si

necesidad de recompilarse.

El desarrollo de una aplicación .NET comienza con la escritura de su código fuente en

alguno de los lenguajes de alto nivel soportados por la plataforma. El mismo luego es

compilado obteniéndose un ejecutable (que en Windows normalmente llevan la extensión

.exe) o una biblioteca (que en Windows normalmente llevan la extensión .dll). A estos

componentes .NET resultantes del proceso de compilación se los denomina genéricamente

Assemblies, o Ensamblados.

Ahora bien, en lugar de contener código de máquina específico para el sistema operativo y

el hardware en el cual fueron compilados (nativo), los assemblies contienen un código

denominado MSIL (Microsoft Intermediate Language). EL MSIL es un set de instrucciones

independientes de cualquier CPU existente y que puede ser convertido a código nativo muy

eficientemente. MSIL incluye instrucciones para cargar, almacenar, inicializar e interactuar

con objetos y sus atributos y métodos, así como también instrucciones aritméticas y lógicas,

control de flujo, acceso directo a memoria, manejador de errores y otras operaciones. Antes

de que el código MSIL pueda ser ejecutado debe convertirse a código nativo específico

para un CPU y Sistema Operativo, tarea a cargo de los compiladores JIT incluidos en el

CLR.

Un Assembly es la menor unidad de ejecución y distribución de una aplicación .NET.

Page 78: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 78 de 159

Los assemblies son reutilizables, versionables y autodescriptivos, ya que no sólo contienen

el código MSIL que representa la lógica de la aplicación, sino que también incluyen

información sobre si mismos y sobre todos los recursos externos de los que dependen para

funcionar correctamente. A esta información se la denomina “Meta data” y forma una

parte integral de un assembly junto con el código MSIL ya que ambos no pueden estar

separados. La Meta data se ubica en una sección especial del Assembly denominada

“Manifest”, o “Manifiesto”, y es utilizada por el CLR a la hora de cargar y ejecutar el

Assembly.

La herramienta ildasm.exe (Intermediate Languaje Dissasembler, incluida en el .NET

Framework SDK) puede utilizarse para inspeccionar la meta data de un assembly.

Una aplicación .NET se compone, entonces, de uno o más assemblies. Otra de las

características de los Assemblies es que no necesitan estar registrados en la Registry de

Windows, como sus predecesores COM. De esta forma, instalar una aplicación .NET puede

ser tan simple como copiar todos los assemblies necesarios a la computadora de destino, y

basta con borrarlos a todos para tener una desinstalación limpia y completa.

Dado que .NET no depende de la Registry, y que cada assembly contiene información

acerca de su versión y las versiones de los componentes de que depende, múltiples

versiones de assemblies pueden coexistir sin ningún problema en la misma computadora.

Existen dos formas de que una aplicación pueda encontrar en tiempo de ejecución los

assemblies de los que depende:

1) Ubicarlos en el mismo directorio. Esta es la opción preferida si esos assemblies

sólo serán utilizados por esa única aplicación.

2) Ubicarlos en un repositorio centralizado de assemblies denominado Global

Assembly Cache, en el cual se instalan todos los assemblies que serán utilizados por

múltiples aplicaciones en la misma computadora. Para registrar un assembly en el

GAC es necesario utilizar otra herramienta incluida en el SDK llamada gacutil.exe.

Page 79: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 79 de 159

Uno de los objetivos de diseño de la plataforma .NET fue el ser independiente del lenguaje

de programación elegido para el desarrollo de aplicaciones. Para lograr esto es que se creó

la Especificación de Lenguaje Común (o CLS, por sus siglas en inglés), que define y

estandariza un subconjunto de todas las características soportadas por el CLR y que son

necesarias en la mayoría de las aplicaciones. Todos los componentes desarrollados y

compilados de acuerdo con la especificación CLS pueden interactuar entre si,

independientemente del lenguaje de programación de alto nivel en el que fueron escritos.

Junto con el .NET Framework, Microsoft provee implementaciones de 4 lenguajes

compatibles con CLS, junto con sus compiladores:

• Microsoft Visual Basic .NET

• Microsoft Visual C# .NET

• Microsoft Visual J#.NET

• Microsoft Visual C++.NET

Esto quiere decir que una aplicación escrita, por ejemplo, en Visual Basic.NET, puede

incorporar sin problemas nuevas partes escritas en C# o C++ .NET.

La infraestructura de lenguaje común (Common Language Infrastructure, CLI) es una

especificación estandarizada que describe un entorno virtual para la ejecución de

aplicaciones, cuya principal característica es la de permitir que aplicaciones escritas en

distintos lenguajes de alto nivel puedan luego ejecutarse en múltiples plataformas tanto de

hardware como de software sin necesidad de reescribir o recompilar su código fuente.

Si bien el CLI tuvo sus orígenes en Microsoft (en principio se pensaba desarrollar un

entorno de ejecución compartido para COM con el nombre de Common Object Runtime,

que luego de extendió y generalizó para dar lugar a CLI), sus especificaciones fueron

llevadas ante ECMA (European Computer Manufacturers Association), una organización

europea de estándares, para su estandarización en el año 2000.

Luego de un año de trabajo conjunto entre ECMA, Microsoft y otras empresas que co-

patrocinaron el proceso (Intel, HP, IBM y Fujitsu entre otras), el estándar ECMA-335 que

Page 80: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 80 de 159

define el entorno CLI finalmente vio la luz en diciembre de 2001. En abril del año 2003

ISO ratificó este estándar con el denominación ISO/IEC 23271:2003 .

Para comprender mejor la inclusión de cada una de las partes principales de la arquitectura

de CLI es interesante analizar los objetivos de diseño que se plantearon desde su

concepción. Según su especificación, la arquitectura de CLI debe:

• Permitir escribir componentes ínter operables independientemente de la plataforma

subyacente y del lenguaje de programación utilizado.

• Exponer todas las entidades programáticas a través de un único sistema unificado de

tipos (en la especificación, este sistema es conocido como CTS, o Common Type

System).

• Empaquetar todos los tipos en unidades completamente auto descriptivas y

portables.

• Cargar los tipos de forma tal que se encuentren aislados unos de otros en tiempo de

ejecución, pero que puedan a su vez compartir recursos.

• Resolver dependencias entre tipos en tiempo de ejecución usando una política

flexible que pueda tener en cuenta la versión, atributos de localización y políticas

administrativas.

• Ejecutar aplicaciones bajo la supervisión de un entorno privilegiado que permita

controlar y hacer cumplir políticas en tiempo de ejecución.

• Diseñar toda la infraestructura y servicios basándose en meta datos extensibles, de

manera tal que toda la arquitectura pueda acomodarse con poco impacto a nuevas

incorporaciones y cambios.

• Poder realizar tareas de bajo nivel, como carga de tipos en memoria, linkeo con

librerías y compilación a código nativo sólo cuando sea necesario (este enfoque se

conoce típicamente como “on demand”, o “just in time”).

• Proveer una serie de funcionalidades comunes mediante un grupo de librerías de

programación que los desarrolladores puedan utilizar para construir sus

aplicaciones.

Page 81: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 81 de 159

Microsoft .NET de hecho es un súper conjunto de esta especificación, es decir, provee todo

lo necesario para cumplir con la misma y además agrega una serie de herramientas,

librerías y funcionalidades no contempladas por ella originalmente y que proveen una

enorme utilidad y flexibilidad a los desarrolladores (por ejemplo, librerías para la creación

de aplicaciones y servicios web, acceso a motores de bases de datos, controles gráficos,

herramientas para desensamblar assemblies, debuggers, etc.). Si bien es gratuito, su código

fuente no es abierto, y es distribuido por Microsoft en versiones para sistemas operativos

Windows 98 y sus sucesores únicamente.

SSuubb--EEssppeecciiffiiccaacciioonneess ddee CCLLII

Lenguajes de Alto NivelLenguajes de Alto NivelLenguajes de Alto NivelLenguajes de Alto Nivel

BCL (Base Class Library)BCL (Base Class Library)BCL (Base Class Library)BCL (Base Class Library)

CLR (Common Language Runtime)CLR (Common Language Runtime)CLR (Common Language Runtime)CLR (Common Language Runtime)

Sistema OperativoSistema OperativoSistema OperativoSistema Operativo

CLS (Common Language Specification)CLS (Common Language Specification)CLS (Common Language Specification)CLS (Common Language Specification)

CTS (Common Type System)CTS (Common Type System)CTS (Common Type System)CTS (Common Type System)

se ajustan a las reglas de la…

y utilizan las clases de la…

cuyos tipos básicos forman el…

y se ejecutan bajo el control de y usan los servicios del…

que está acoplado al y utiliza los servicios del …

Page 82: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 82 de 159

La figura representa el modelo de compilación y ejecución de aplicaciones .NET, al cual

muchas veces se denomina “de compilación diferida”, o “de compilación en dos etapas”.

Esto es asi ya que el primer paso para poder ejecutar una aplicación dentro del CLR es

compilar su código fuente para obtener un assembly con código MSIL. Este paso es

realizado por cada uno de los compiladores de los distintos lenguajes de alto nivel

soportados por .NET.

Luego, el CLR se encarga de compilar el código MSIL a código nativo que hace uso

específico de los servicios del sistema operativo y la plataforma de hardware subyacente.

Todos los compiladores de los nuevos lenguajes .NET de Microsoft siguen este modelo de

ejecución, con excepción de C++ .NET, que es el único lenguaje al que se le ha dejado la

capacidad de emitir también código “no manejado”. Esto se debe a que ciertas aplicaciones,

como los drivers de dispositivos, necesitan tener acceso a los recursos del sistema operativo

a muy bajo nivel para lograr un rendimiento óptimo y mayor performance.

VVBB..NNEETT

CCóóddiiggoo FFuueennttee

CCoommppiillaaddoorr VVBB..NNEETT

CC++++..NNEETT CC##

AAsssseemmbbllyy CCóóddiiggoo MMSSIILL

SSiisstteemmaa OOppeerraattiivvoo ((WWiinnddoowwss))

CCoommmmoonn LLaanngguuaaggee RRuunnttiimmee

CCoommppiillaaddoorr JJIITT

CCóóddiiggoo NNaattiivvoo

CCóóddiiggoo MMaanneejjaaddoo

CCoommppoonneennttee NNoo MMaanneejjaaddoo

MMooddeelloo ddee EEjjeeccuucciióónn ddeell CCLLRR

CCoommppiillaaddoorr CC##

CCoommppiillaaddoorr CC++++ ..NNEETT

AAsssseemmbbllyy CCóóddiiggoo MMSSIILL

AAsssseemmbbllyy CCóóddiiggoo MMSSIILL

Page 83: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 83 de 159

3.7.3 ADO .Net 2.0

ADO.NET es un subconjunto de la .NET Framework Class Library, que contiene todas las

funcionalidades necesarias para conectarse e interactuar con dos tipos de repositorios

permamentes de información:

1) Bases de Datos, como Microsoft SQL Server (clases del namespace System.Data,

que se encuentran compiladas en System.data.dll)

2) Archivos XML (clases del namespace System.XML, que se encuentran compiladas

en System.Xml.dll)

La siguiente figura muestra el subconjunto.

La arquitectura de ADO.NET está basada en el concepto de proveedores de acceso a datos,

siendo un proveedor un conjunto de clases que permiten conectarse a una base de datos,

AAcccceessoo aa DDaattooss:: AADDOO..NNEETT

System.Data

OleDb

SqlClient

OracleClient

Common

Odbc SqlTypes

System.Xml

Serialization

XPath

XSLT

Schema

Page 84: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 84 de 159

ejecutar un comando sobre ella y tener acceso a los resultados de su ejecución, tanto de

forma conectada como desconectada.

Los proveedores de acceso a datos ADO.NET (conocidos como “Managed Data

Providers”) representan conjuntos específicos de clases que permiten conectarse e

interactuar con una base de datos, cada uno utilizando un protocolo particular. El .NET

Framework incluye cuatro proveedores de acceso a datos, que en conjunto le permiten

conectarse e interactuar virtualmente con cualquier base de datos existente en la actualidad:

• Data Provider For SQL Server: es el proveedor de acceso nativo a servidores de

bases de datos Microsoft SQL Server 7.0 o superior, y Microsoft Access. Al

conectarse vía protocolos nativos de bajo nivel, provee la alternativa más

performante para conexiones contra estos motores de bases de datos. Sus clases se

encuentran en el namespace System.Data.SqlClient.

• Data Provider For OLE DB: es el proveedor de acceso a datos que permite

interactuar vía el protocolo estándar OLE DB con cualquier repositorio de datos que

lo soporte. Sus clases se encuentran en el namespace System.Data.OleDb.

• Data Provider For ODBC: es el proveedor de acceso a datos que permite interactuar

vía el protocolo estándar ODBC con cualquier repositorio de datos que lo soporte.

Sus clases se encuentran en el namespace System.Data.Odbc.

• Data Porvider For Oracle: es el proveedor de acceso nativo a bases de datos Oracle,

desarrollado por Microsoft utilizando las herramientas de conectividad de Oracle.

De esta forma puede lograrse un acceso más performante a bases de datos Oracle

desde aplicaciones .NET que utilizando ODBC u OLE DB. Sus clases se encuentran

en el namespace System.Data.OracleClient, y están compiladas en un assembly

diferente al resto: System.Data.OracleClient.dll.

Page 85: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 85 de 159

En la figura se pueden apreciar las clases más comunes que componen a todos los

proveedores de acceso a datos de ADO.NET. Nótese que algunos nombres empiezan con

las letras “Xxx”: esto se debe a que los nombres de esas clases varían según el proveedor

específico que se esté utilizando. Por ejemplo, la clase que representa una conexión con la

base de datos usando el Data Provider For Sql Server es “SqlConnection”, mientras que si

usamos el Data Provider For Oracle podemos obtener la misma funcionalidad de la clase

“OracleConnection”.

● XxxConnection: representa una conexión. Almacena, entre otras cosas, el string de

conexión (connection string), y permite conectarse y desconectarse con una base de

datos.

● XxxCommand: permite almacenar y ejecutar una instrucción SQL contra una base

de datos, enviando parámetros de entrada y recibiendo parámetros de salida.

Estas dos clases se utilizan tanto en escenarios conectados como desconectados.

Base de Datos

XxxConnection

XxxCommand

DataSet XxxDataReader

XxxDataAdapter

Maneja la conección a una base de datos

Ejecuta comandos contra una base de datos

Copia local de datos relacionales

Provee acceso a datos read-only, Forward-only

Intercambia datos entre un dataset y una base de datos

AADDOO..NNEETT-- CCllaasseess mmááss ccoommuunneess

Page 86: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 86 de 159

● XxxDataReader: permite acceder a los resultados de la ejecución de un comando

contra la base de datos de manera read-only (sólo lectura), forward-only (sólo hacia

adelante). Esta clase se utiliza en escenarios conectados, ya que no es posible operar

sobre los registros de un DataReader estando desconectado de la fuente de datos.

● XxxDataAdapter y DataSet: en conjunto, estas clases constituyen el corazón del

soporte a escenarios desconectados de ADO.NET. El DataSet es una representación

en memoria de una base de datos relacional, que permite almacenar un conjunto de

datos obtenidos mediante un DataAdapter. El DataAdapter actúa como

intermediario entre la base de datos y el DataSet local desconectado. Una vez que el

DataSet se encuentra lleno con los datos que se necesitan para trabajar, la conexión

con la base de datos puede cerrarse sin problemas y los datos pueden ser

modificados localmente. Por último, el DataAdapter provee un mecanismo para

sincronizar los cambios locales contra el servidor de base de datos. Nótese que la

clase System.Data.DataSet no tiene el prefijo Xxx, ya que es independiente del

proveedor de acceso a datos utilizado.

ADO.NET provee una arquitectura extensible, posibilitando que terceras partes creen sus

propios proveedores de acceso nativo para aplicaciones .NET. Algunos ejemplos de esto

son:

• Data Provider For DB2, desarrollado por IBM

• Oracle Data Provider For .NET, desarrollado por Oracle

• Providers de acceso nativo a bases de datos OpenSource, como MySQL y

PostgreSQL

Page 87: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 87 de 159

ADO.NET es el sucesor de ADO (ActiveX Data Objects), la biblioteca de acceso a datos de

la plataforma COM. Si bien ADO soporta sólo escenarios conectados, puede resultar útil

hacer una analogía de las clases más comunes utilizadas en ADO con respecto a sus nuevas

versiones en ADO.NET:

• La clase Connection de ADO tiene su paralelo en las clases XxxConnection de los

distintos proveedores de ADO.NET

• La clase Command de ADO tiene su paralelo en las clases XxxCommand de los

distintos proveedores de ADO.NET

• La clase Recordset de ADO dejó de existir como tal en ADO.NET. En su lugar

existen en ADO.NET las clases XxxDataReader (es lo más parecido a un Recordset

read-only forward-only de ADO), y las nuevas clases DataSet y XxxDataAdapter

para escenarios desconectados.

AADDOO..NNEETT vvss.. AADDOO

Page 88: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 88 de 159

La figura ilustra una parte del soporte a XML provisto por el .NET Framework, que va

desde la simple lectura de un documento XML a su navegación, búsqueda y

transformaciones complejas.

• XmlReader – clase abstracta cuyo propósito es proveer un mecanismo de lectura

forward-only de un documento XML. Tiene tres clases derivadas:

• XmlTextReader – utilizada para leer datos de un documento XML o un

stream. Se utiliza normalmente cuando la performance de lectura es un

factor clave y todo el sobreprocesamiento de DOM debe evitarse.

• XmlValidatingReader – similar a XmlTextReader, pero pensada para

validaciones DOM.

• XmlNodeReader – permite leer datos de un nodo XML.

• XmlTextWriter – permite que datos XML puedan ser escritos a un archivo XML o

a un stream, y puede además proveer mecanismos de validación para asegurar que

sólo datos XML válidos y bien formados sean escritos.

XXmmllTTeexxttWWrriitteerr

XXmmllTTeexxttRReeaaddeerr

<<XXMMLL>>

XXmmllDDooccuummeenntt

DDooccuummeennttNNaavviiggaattoorr

XXmmllRReeaaddeerr

XXmmllVVaalliiddaattiinnggRReeaaddeerr XXmmllNNooddeeRReeaaddeerr

AADDOO..NNEETT -- SSooppoorrttee aa XXMMLL

Page 89: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 89 de 159

• XmlDocument – esta es una clase compleja que actúa como un contenedor de datos

XML, representando en un modelo de objetos en memoria toda la estructura de un

documento XML. Esto permite tener facilidades de navegación y edición, pero a un

cierto costo de performance y consumo de recursos.

• DocumentNavigator – permite navegar libremente la estructura de un documento

XML una vez que ha sido cargado dentro de una instancia de la clase

XmlDocument.

Page 90: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 90 de 159

IV. Solución Propuesta

El presente capitulo, describe la conceptualización, elaboración y construcción de la

solución propuesta. De esta forma que se detallan los requerimientos base con los que se

inicio la conceptualización y diseño de la solución, los criterios y estimaciones de diseño y

finalmente se muestra la implementación del diseño utilizando código C#.

La propuesta se plantea, presentando inicialmente el modelado general de la solución

describiendo elementos de arquitectura considerados y las características generales

propuestas. Posteriormente se presenta la funcionalidad básica que debe de implementar

aislando en secciones cada funcionalidad con sus requerimientos, sus criterios de diseño y

su implementación, con el fin de que sea mas sencillo detallar la construcción de cada

sección especifica de la solución propuesta.

4.1 Modelado de la solución

4.1.1 Consideraciones Iniciales

Dado que nuestra solución pretende reforzar y promover el uso de un diseño y construcción

completamente orientado a objetos, esto requiere la utilización de una arquitectura

multicapas como las mostrada en el siguiente diagrama.

<<Usa>>

<<Usa>><<Crea>>

<<Usa>>Presentación Negocio Acceso a Datos

Dominio

Para el diseño del core del sistema se construirá un modelo de dominio basados en el patrón

Domain Value Object, donde en ves de diseñar tablas o un modelo ER, se diseñaran clases

Page 91: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 91 de 159

que encapsulen datos y comportamiento siguiendo las características de la orientación a

objetos.

El motor de persistencia a construir implementará funcionalidad de la capa de Acceso a

Datos, por lo que es en este nivel donde definirá el ambiente, estándares y características

bajo los cuales trabajara la propuesta.

Debido que existen una serie de patrones de diseño disponibles para el Acceso a Datos, se

ha decido tomar el patrón utilizado en la plataforma J2EE denominado DAO (Data Access

Object)4. Este patrón proporcionara los siguientes beneficios a nuestro diseño.

• DAO define una relación uno a uno entre clases de dominio y de acceso a datos

• Cada clase de dominio tendrá asociada una clase de DAO de acceso a datos lo que

permitirá no mezclar operaciones entre clases e identificar rápidamente la clase

responsable de cada entidad.

• El uso de DAO proporciona una alta cohesión ya que todos los métodos

transaccionales de una clase están relacionados a una sola clase de dominio y el

acoplamiento entre clases DAO es bastante bajo.5

• El uso de DAO permitirá una alta reusabilidad de las clases implementadas.

Dado que por cada clase de

dominio tendremos una clase

de acceso a datos, podemos

considerar el diseño de una

clase maestra que contenga la

funcionalidad genérica del

motor de persistencia y sea

heredado a cada una de las

clases DAO de la aplicación.

Esto se muestra en el diagrama

adjunto.

4 Para mas información sobre el patrón DAO consultar la sección 3.2.9 5 Para mas información sobre Acoplamiento y Cohesión remitirse a la sección 3.2.2

<<Crea>> <<Crea>> <<Crea>> <<Crea>>

DAOMaster

DAOCliente DAOFactura DAOProductoDAOItem

Cliente Factura ProductoItem

Page 92: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 92 de 159

4.1.2 Namespaces y Assemblies.

La funcionalidad principal del motor de persistencia será encapsulada en una clase a la que

se denominará DAOMaster la cual deberá ser heredada, por lo que se definirá de tipo

abstracta. Adicionalmente esta clase dependerá de los servicios de otras clases encargadas

de crear conexiones y otros tipos de objetos. Toda esta funcionalidad se definirá y agrupará

dentro de un solo namespace el cual será denominado DAOMasterLibrary con el fin de

que solo sea incorporado en la lógica de las capa de acceso datos de las aplicaciones que

utilicen esta herramienta.

Así a la hora de diseñar la arquitectura de una aplicación la lógica de acceso a datos será

heredada de este namespace, esto como se muestra en el siguiente diagrama:

<<Usa>><<Crea>>

<<Usa>>

DAOMasterLibrary

Negocio Acceso a Datos

Dominio

Finalmente la implementación del motor de persistencia, estará contenida en un solo

Assembly o librería de clases DLL la cual será denominada DAOMasterLibrary.dll . Este

podrá ser incorporado en cualquier proyecto de desarrollo, simplemente al agregar una

referencia a esta librería y seguir el esquema propuesto.

Finalmente el motor de persistencia debe de implementar ciertas características como la

Sincronización de la Estructura del Modelo de Dominio con el modelo ER donde se

persistirán los datos, generación automática de las sentencias de inserción, actualización y

Page 93: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 93 de 159

eliminación, carga de objetos, implementar las características anteriores independientes del

sistema RDBMS o contenedor usado, parametrización, etc. Todas estas característicos son

explicadas en la secciones siguientes del presente capitulo.

4.2 Sincronización Estructura ER y Modelo de Dominio

4.2.1 Planteamiento del Requerimiento

Dado que la persistencia de datos es una característica que debemos de implementar sobre

el modelo de dominio, es necesario que la funcionalidad del motor de persistencia a crear

contenga un mecanismo a través del cual se mantenga una relación bien sincronizada entre

el modelo de dominio y su respectivo equivalente en el RDBMS. Esta sincronización debe

de garantizar que cada instancia de una clase del Dominio pueda ser persistida como una o

varias filas en una o varias tablas especificas, de la misma forma se debe de garantizar que

la filas de las tablas puedan ser cargadas dentro de objetos en tiempo de ejecución.

Las operaciones antes mencionadas requieren que exista una forma de indicar al Motor una

relación uno a uno entre tablas y clases así como también relaciones uno a uno entre

columnas de una tabla y las propiedades de una clase.

Se debe de considerar como parte del requerimiento que esta operación de mapeo requiera

el menor tiempo posible al desarrollador, de tal forma que no le rastrase o le obligue a

realizar complejos o detallados mapeos entre cada propiedad de una tabla y las propiedades

de una clase.

4.2.2 Diseño de la Solución

Motores de persistencia como Hibernate o NHIbernate utilizan un archivo XML para

definir el mapeo entre clases y tablas. Para nuestro caso se ha considerado automatizar

totalmente dicho mapeo, sin embargo esta funcionalidad supone que el desarrollador

utilizará una herramienta CASE que le permita modelar un sistema en un diagrama de

clases, es decir construir un modelo de dominio y su respectivo código C# y a partir de este

generar el DDL para ser ejecutado en el RDBMS y construir de esa forma el ER a partir del

diagrama de clases. Este mecanismo solucionara el problema de mantener sincronizado

ambos modelos, asignando dicha responsabilidad a la herramienta CASE.

Page 94: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 94 de 159

4.2.2.1 Diseñando la Clase de Dominio

Por ejemplo para el modelamiento de los usuarios de un sistema, se diseña la siguiente

clase:

Usuario

-

-

-

-

-

-

-

-

-

-

-

-

-

-

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

usuarioID

usuarioNombres

usuarioApellidos

usuarioEmail

usuarioCelular

usuarioPassword

fechaActualizacion

_usuarioID

_usuarioNombres

_usuarioApell idos

_usuarioEmail

_usuarioCelular

_usuarioPassword

_fechaActualizacion

: string

: string

: string

: string

: string

: string

: Datetime

: string

: string

: string

: string

: string

: string

: Datetime

+

+

+

+

-

+

-

+

+

+

+

+

+

+

-

+

+

+

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

Usuario (string sUsuarioCuenta, string sUsuarioNombre, string sUsuarioPassword)

encriptarClave ()

validarClave (string sPassword)

cambiarPassword (string sPasswordAnterior, string sNuevoPassword)

set_usuarioID (string value)

get_usuarioID ()

set_usuarioNombres (string value)

get_usuarioNombres ()

set_usuarioApell idos (string value)

get_usuarioApellidos ()

set_usuarioEmail (string value)

get_usuarioEmail ()

set_usuarioCelular (string value)

get_usuarioCelular ()

set_usuarioPassword (string value)

get_usuarioPassword ()

set_fechaActualizacion (Datetime value)

get_fechaActualizacion ()

: void

: int

: bool

: int

: void

: string

: void

: string

: void

: string

: void

: string

: void

: string

: void

: string

: void

: Datetime

Se puede notar de esta clase que tiene 7 propiedades las cuales son privadas, es decir no

pueden ser acezadas directamente, sino solamente a través de la propiedades (getter y

setter) las cuales son métodos con el mismo nombre que los atributos de la clase, esta es la

implementación del Data Hidding y de la Encapsulación de objeto.

Adicionalmente se han agregado las siguientes reglas de negocio a este modelo:

• No es posible crear una nueva instancia de un objeto Usuario si no se cuenta con los

datos obligatorios UsuarioID, UsuarioNombre y UsuarioClave. Estos son

parámetros obligatorios del Constructor de la Clase.

Page 95: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 95 de 159

• No es posible cambiar las propiedades UsuarioID, UsuarioNombre e UsuacioClave

esta ultima solo puede ser cambiada a través del método cambiarPassword. Debido

a esto los Setter de la propiedades UsuarioID, UsuarioNombre y UsuarioClave, si

bien existen son privados por lo que no pueden ser invocados externamente.

• La clase cuenta con un método privado encriptarClave el cual se encarga de

codificar la clave del usuario de tal forma que este encriptada al momento que el

usuario sea persistido

• La clase Usuario cuenta con el método validarClave la cual recibe una cadena de

texto y devuelve un valor verdadero si es la clave asignada al usuario o falso si no

es así

Estas propiedades y métodos que mantienen un alto grado de cohesión permitirán dar a esta

clase la responsabilidad única de representar a los usuarios manteniendo un bajo grado de

acoplamiento de tal forma que el objeto pueda ser reutilizable.

El código generado por el case para esta clase, es el siguiente:

public class Usuario {

private string _usuarioID;

private string _usuarioNombres;

private string _usuarioApellidos;

private string _usuarioEmail;

private string _usuarioCelular;

private string _usuarioPassword;

private Datetime _fechaActualizacion;

public sealed void Usuario(string sUsuarioCuenta, string sUsuarioNombre, string

sUsuarioPassword) {

// TODO: implement

}

public sealed int encriptarClave() {

// TODO: implement

return 0;

}

public sealed bool validarClave(ref string sPassword) {

// TODO: implement

return false;

}

Page 96: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 96 de 159

public sealed int cambiarPassword(ref string sPasswordAnterior, ref string

sNuevoPassword) {

// TODO: implement

return 0; }

private string usuarioID {

get {

return _usuarioID;

}

Set {

if (this._usuarioID != value)

this._usuarioID = value;

}

}

private string usuarioNombres {

get {

return _usuarioNombres;

}

Set {

if (this._usuarioNombres != value)

this._usuarioNombres = value;

}

}

private string usuarioApellidos {

get {

return _usuarioApellidos;

}

Set {

if (this._usuarioApellidos != value)

this._usuarioApellidos = value;

}

}

private string usuarioEmail {

get {

return _usuarioEmail;

}

Set {

if (this._usuarioEmail != value)

this._usuarioEmail = value;

}

}

private string usuarioCelular {

get {

return _usuarioCelular;

}

Set {

if (this._usuarioCelular != value)

Page 97: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 97 de 159

this._usuarioCelular = value;

}

}

private string usuarioPassword {

get {

return _usuarioPassword;

}

Set {

if (this._usuarioPassword != value)

this._usuarioPassword = value;

}

}

Private Datetime fechaActualizacion {

Get {

return _fechaActualizacion;

}

Set {

if (this._fechaActualizacion != value)

this._fechaActualizacion = value;

}

}

}

4.2.2.2 Diseñando el Modelo Físico en el RDBMS Habiendo finalizado el modelo de dominio, podemos utilizar el CASE para que nos genere

el modelo Físico orientado a un sistema RDBMS especifico, para nuestro caso, generamos

el modelo físico especificando Microsoft SQL Server como RDBMS y el CASE nos genero

la siguiente tabla Usuario

usuarioID

usuarioNombres

usuarioApell idos

usuarioEmail

usuarioCelular

usuarioPassword

fechaActual izacion

varchar(50)

varchar(100)

varchar(100)

varchar(100n)

varchar(8)

varchar(100)

Datetime

<pk>

El DDL de dicha clase es el siguiente

create table Usuario ( usuarioID varchar(50) not null, usuarioNombres varchar(100) not null, usuarioApellidos varchar(100) null, usuarioEmail varchar(100n) null, usuarioCelular varchar(8) null, usuarioPassword varchar(100) not null, fechaActualizacion Datetime not null, constraint PK_USUARIO primary key (usuarioID) )

Este puede ya ser ejecutado contra la base de datos para definir el ER de nuestro sistema.

Page 98: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 98 de 159

4.2.3 Construcción de la Solución.

Los siguientes, son mas que construcciones dentro del prototipo, son bien lineamientos que

deberán seguirse al construir la aplicación particular para garantizar que el motor de

persistencia identifique la relación entre clases y tablas.

Se deberá construir un namespace denominado Dominio dentro del cual deberán de

declararse todas las clases de dominio que formen el aplicativo. Entonces el código

generado por el case quedaría de la siguiente manera:

Namespace Dominio {

public class Usuario {

private string _usuarioID;

private string _usuarioNombres;

private string _usuarioApellidos;

private string _usuarioEmail;

private string _usuarioCelular;

private string _usuarioPassword;

private Datetime _fechaActualizacion;…

}

}

Para cada clase de dominio se deberá crear una clase DAO en cuyo constructor se declare a

través de la ejecución del método setDoName el nombre de la tabla del ER al cual esta

mapeada dicha clase. Por nomenclatura el nombre de la clase deberá ser la cadena “DAO”

mas el nombre de la clase de dominio. Estas clases DAO deberán ser definidas dentro de un

namespace denominado “AccedoDatos” y cada clase deberá ser heredada de la clase

DAOMaster.

Para la clase de Dominio Usuario, la clase de acceso a datos quedaría de la siguiente forma:

using System; using System.Data;

using DAOMasterLibrary;

using Dominio;

namespace AccesoDatos

{

Page 99: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 99 de 159

class DAOUsuario : DAOMaster

{

public DAOUsuario()

{

this.setDOName("usuario");

}

}

}

4.3 Generación de operaciones transaccionales

4.3.1 Planteamiento del Requerimiento

El sistema a implementar debe de generar las operaciones de inserción, actualización y

eliminación de forma automática, recibiendo como insumo únicamente una instancia del

objeto a procesar.

Dado que el motor de persistencia trabaja en la capa de acceso a datos, será a este nivel

donde deberán de estar disponibles métodos para adicionar, actualizar y eliminar objetos.

Los cuales recibirán una instancia y generarán las operaciones pertinentes de la forma mas

eficiente posible. Esto significa para el caso de la actualización por ejemplo solo actualizar

las propiedades que hayan cambiado y no toda la fila.

4.3.2 Diseño de la Solución

Dado el requerimiento anterior, se han diseñado tres métodos concretos los cuales se

describen a continuación:

Método Parámetros Descripción

1 add Domain Object Adiciona el objeto 2 Update Domain Object Actualiza las propiedades del objeto que han

cambiado 3 Delete Domain Object Elimina el Objeto

4.3.2.1 Método para la inserción de registros. El método Add que será implementado en la Capa de acceso a Datos para ser usado en la

capa de negocios, tendrá la responsabilidad de recibir una instancia de un Domain Object y

convertirlo a un registro de la correspondiente tabla mapeada, generando la correspondiente

Page 100: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 100 de 159

sentencia insert. Para desarrollar esta tarea dicho método, se auxiliara de una serie de

métodos privados siguiendo la secuencia que se muestra en el siguiente diagrama:

Los métodos utilizados en la secuencia anterior se describen a continuación:

Método Descripción

SetdoName Método Setter que establece el nombre de la clase a procesar getSchema Obtiene el esquema de la tabla identificada por el nombre del objeto getPropierties Recibe la instancia del objeto a persistir y un Datarow vació con la

estructura de la tabla, barre la instancia y asigna los valores de cada propiedad a su respeciva columna en el datarow, devolviendo el datarow poblado

saveDS Toma un Dataset y genera una sentencia insert para el datarow contenido

4.3.2.2 Método para la actualización de registros. El método update a implementar en la Capa de Acceso a Datos. Recibirá la referencia del

objeto de dominio a actualizar y tendrá la responsabilidad de generar la sentencia update

Setear Nombre Objeto

Solicitar Esquema

Devuelve Esquema Tabla

Crear Row a paritr de esquema Envio de objeto y DataRow vacío

DataRow poblado con propiedades de objeto

Adicionar Datarow a Dataset

Envio DataSet envio de sentencia Insert generada

Resultado Exito o Exepción Exito o Exepción

Solicitar Pk de registro insertado

PK insertado

add setdoName getSchema getPropierties saveDS getID RDBMS

Setear Nombre Objeto

Solicitar Esquema

Devuelve Esquema Tabla

Crear Row a paritr de esquema Envio de objeto y DataRow vacío

DataRow poblado con propiedades de objeto

Adicionar Datarow a Dataset

Envio DataSet envio de sentencia Insert generada

Resultado Exito o Exepción Exito o Exepción

Solicitar Pk de registro insertado

PK insertado

Page 101: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 101 de 159

basado en los primary keys del registro actualizando únicamente las columnas que han

cambiado.

Para realizar esta actividad el método update, se Valera de la ayuda de una serie de métodos

privados, siguiendo la secuencia del diagrama siguiente:

Los métodos utilizados en la secuencia anterior se describen a continuación:

Método Descripción

SetdoName Método Setter que establece el nombre de la clase a procesar getSchema Obtiene el esquema de la tabla identificada por el nombre del objeto getPropierties Recibe la instancia del objeto a persistir y un Datarow vació con la

estructura de la tabla, barre la instancia y asigna los valores de cada

Setear Nombre Objeto

Solicitar Esquema

Devuelve Esquema Tabla

Crear DataSet a paritr de esquema

Envio de objeto y DataRow vacío

DataRow poblado con propiedades de objeto

Asignar nuevo valores a existentes en DataRow

Envio DataSet envio de sentencia update generada

Resultado Exito o Exepción Exito o Exepción

Generar Where para registro a partir de primaries Keys

Sentencia Where ejecutar select con el where construido

DataRow poblado

Asignar Datarow poblado a DataSet Creado

update setDoName getSchema getPropierties saveDS getStrWhere RDBMS2

Setear Nombre Objeto

Solicitar Esquema

Devuelve Esquema Tabla

Crear DataSet a paritr de esquema

Envio de objeto y DataRow vacío

DataRow poblado con propiedades de objeto

Asignar nuevo valores a existentes en DataRow

Envio DataSet envio de sentencia update generada

Resultado Exito o Exepción Exito o Exepción

Generar Where para registro a partir de primaries Keys

Sentencia Where ejecutar select con el where construido

DataRow poblado

Asignar Datarow poblado a DataSet Creado

Page 102: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 102 de 159

propiedad a su respectiva columna en el datarow, devolviendo el datarow poblado

saveDS Toma un Dataset y genera una sentencia update para el datarow contenido getWhere Genera un string que servirá como filtro where para un Quero, esta

sentencia esta formada por las columnas definidas como Primary Keys para la tabla mapeada así como el valor respectivo que hace único al registro

4.3.2.3 Método para la eliminación de registros El método delete que implementara el motor de persistencia, recibirá un objeto de dominio

y partir de esto deberá de generar la sentencia delete respectiva filtrada por las columnas

que forman la primary Key y sus valores respectivos. Al igual que los casos de adición y

actualización el método se auxiliara de métodos privados, siguiendo la secuencia mostrada

en el siguiente diagrama:

Los métodos utilizados en la secuencia anterior se describen a continuación:

Método Descripción

SetdoName Método Setter que establece el nombre de la clase a procesar getStrWhere Genera un string que servirá como filtro where para un Quero, esta

sentencia esta formada por las columnas definidas como Primary Keys para la tabla mapeada así como el valor respectivo que hace único al registro

execSQL Ejecuta una sentencia SQL

Setear Nombre Objeto

Contruir Where con Primary keys String para where

Envio de sentencia delete con where creado

Exito o Exepcion

Ejecutar Delete

Exito o Exepcion

delete setdoName execSQL getStrWhere RDBMS

Setear Nombre Objeto

Contruir Where con Primary keys String para where

Envio de sentencia delete con where creado

Exito o Exepcion

Ejecutar Delete

Exito o Exepcion

Page 103: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 103 de 159

4.3.3 Construcción de la Solución

En esta sección se muestra el código de los métodos implementados para soportar las

operaciones de adición, actualización y eliminación siguiendo la lógica y secuencias

planteados en el diseño de los mismos.

4.3.3.1 Método Add Este método público recibe un Domain Object e intenta persistirlo en Data Source

especificado. El código de dicho método es el siguiente:

// Salva el Domain Object en el Datasource

public long add(object aDO) {

try {

setDOName(aDO.GetType().Name.ToString());

DataSet oDS = new DataSet() ;

oDS.ReadXmlSchema(getSchema());

DataRow oRow = oDS.Tables[0].NewRow();

getPropiedades(oRow,aDO);

oDS.Tables[0].Rows.Add(oRow);

saveDS(oDS);

} catch (Exception ex) {

throw new Exception("Error Insertando objeto " + this._doName + " / " +

ex.Message);

}

return getID();

}

Puede observarse que debido a que el parámetro es un objeto de tipo Domain Object que

puede ser en si cualquier objeto, es necesario la utilización de “Late Binding” al momento

de definir el tipo de dato del argumento recibido.

El método ADD utiliza se vale de una serie de modos como se mostró en la secuencia del

diseño, el código de estos métodos es mostrado a continuación:

// Devuelve el Schema en formato XML StrinReader de la estructura de persistencia

del Domain Object actual

private System.IO.StringReader getSchema() {

string sXML = this.getDsSchema().GetXmlSchema();

return new System.IO.StringReader(sXML);

}

//Función privada que ejecuta y devuelve el Schema del Objeto mapeado private DataSet getDsSchema(){

if (dsSchema != null) return dsSchema;

else

{

Page 104: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 104 de 159

DataSet ds;

DbCommand oCommand;

DbDataAdapter oAdapter;

string SqlString = "select * from " + this._doName;

try

{

if (setConnection())

{

ds = new DataSet();

oCommand = _oCon.CreateCommand();

oAdapter = dbFactory.CreateDataAdapter();

oCommand.Connection = _oCon;

oCommand.CommandType = CommandType.Text;

oCommand.CommandText = SqlString;

oAdapter.SelectCommand = oCommand;

oAdapter.FillSchema(ds, SchemaType.Mapped);

dsSchema = ds;

}

else

{

return null;

}

}

catch (Exception ex)

{

throw ex;

}

return ds;

}

}

// Obtiene las propiedades de un Domain Object asignandolas a un DataRow a

traves de invocaciones dinamicas a los Getter

private void getPropiedades(DataRow aRow, object aDO){

PropertyInfo[] oProperties;

string sPropertyName="";

MethodInfo oMetodo;

try {

oProperties =

aDO.GetType().GetProperties(BindingFlags.NonPublic|BindingFlags.Instance|BindingF

lags.Static|BindingFlags.Public);

foreach(PropertyInfo oProperty in oProperties) {

sPropertyName = oProperty.Name.ToString();

oMetodo = oProperty.GetGetMethod(true);

switch (oMetodo.ReturnType.ToString()) {

case "System.String":

aRow[sPropertyName] = (string)oMetodo.Invoke(aDO, null);

break;

case "System.DateTime":

aRow[sPropertyName] = (DateTime)oMetodo.Invoke(aDO, null);

break;

case "System.Int16":

aRow[sPropertyName] = (Int16)oMetodo.Invoke(aDO, null);

break;

case "System.Int32":

aRow[sPropertyName] = (Int32)oMetodo.Invoke(aDO, null);

break;

case "System.Int64":

aRow[sPropertyName] = (Int64)oMetodo.Invoke(aDO, null);

break;

case "System.Decimal":

aRow[sPropertyName] = (Decimal)oMetodo.Invoke(aDO, null);

break;

case "System.Double":

Page 105: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 105 de 159

aRow[sPropertyName] = (Double)oMetodo.Invoke(aDO, null);

break;

case "System.Boolean":

aRow[sPropertyName] = (Boolean)oMetodo.Invoke(aDO, null);

break;

case "System.Char":

aRow[sPropertyName] = (Char)oMetodo.Invoke(aDO, null);

break;

}

}

} catch(Exception ex) {

throw new Exception("Error accesando la propiedad " + sPropertyName + " /

" + ex.Message);

}

}

// Objetivo: Actualizar el Dataset en el DataSource

private int saveDS(DataSet ds)

{

string sSQL = "select * from " + this._doName;

DbDataAdapter oAdapter;

DbCommandBuilder oCBuilder;

int iResult = 0;

if (setConnection())

{

try

{

oAdapter = dbFactory.CreateDataAdapter();

oAdapter.SelectCommand.CommandText = sSQL;

oAdapter.SelectCommand.Connection = this._oCon;

oCBuilder = dbFactory.CreateCommandBuilder();

oCBuilder.DataAdapter = oAdapter;

iResult = oAdapter.Update(ds);

oAdapter.Dispose();

oAdapter = null;

}

catch (Exception ex)

{

throw new Exception("Error actualizando objeto " + this._doName + " / " +

ex.Message);

}

}

return iResult;

}

4.3.3.2 Método Update. Este método público recibe un Domain Object e intenta actualizarlo en el Data Source

especificado. El código de dicho método es el siguiente:

Page 106: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 106 de 159

//Actualizar el Domain Object en el Datasource

public bool update(object aDO) {

this.setDOName(aDO.GetType().Name.ToString());

try {

string sSQL = "select * from " + this._doName + " " + this.getWhere(aDO);

DataSet oDS, fDS;

fDS = new DataSet();

fDS.ReadXmlSchema(getSchema());

oDS = getDS(sSQL);

DataRow oRow = oDS.Tables[0].Rows[0];

DataRow fRow = fDS.Tables[0].NewRow();

foreach(DataColumn oColumn in oDS.Tables[0].Columns) {

fRow[oColumn.ColumnName.ToString()] =

oRow[oColumn.ColumnName.ToString()];

}

fDS.Tables[0].Rows.Add(fRow);

fDS.AcceptChanges();

getPropiedades(fRow, aDO);

saveDS(fDS,true,aDO);

} catch(Exception ex) {

throw new Exception("Error actualizando objeto " + this._doName + " / " +

ex.Message);

}

return true;

}

El método actualizar se vale de los mismos métodos que Add, es decir los métodos

getSchema(), readXMLSchema(),getPropiedades() y saveDS() incorpora además el método

getDS() y getWhere() de los cuales se muestra el código a continuación:

//Función protected que ejecuta y devuelve un DataSet

protected DataSet getDS(string SqlString){

DataSet ds;

DbCommand oCommand = _oCon.CreateCommand();

DbDataAdapter oAdapter = dbFactory.CreateDataAdapter();

try {

if(setConnection()) {

ds = new DataSet() ;

oCommand.Connection = _oCon;

oCommand.CommandType = CommandType.Text;

oCommand.CommandText = SqlString;

oAdapter.SelectCommand = oCommand;

oAdapter.Fill(ds);

} else {

return null;

}

} catch(Exception ex) {

throw ex;

}

return ds;

}

// Generar la Sentencia where correspondiente usando los primary key y sus

valores

private string getWhere(object aDO)

{

DataColumn[] colArr;

string sWhere = "", sColumn, sAND, sType;

DataSet ds;

DataRow fila;

Page 107: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 107 de 159

int ikeys;

try

{

ds = getDsSchema();

fila = ds.Tables[0].NewRow();

getPropiedades(fila,aDO);

colArr = ds.Tables[0].PrimaryKey;

ikeys = colArr.Length;

sColumn = "";

sWhere = " where ";

if (ikeys == 0) throw new Exception("Objeto " + _doName + " no tiene definido

Primary Key en el ER, imposible continuar");

for (int i = 1; i < ikeys; i++) {

sAND = (i>0)? " AND ":"";

sColumn = colArr[i].ColumnName;

sType = colArr[i].DataType.Name.ToString();

if(sType.CompareTo("String")==0||sType.CompareTo("Char")==0) {

sWhere += sAND + sColumn + " = '" + fila[sColumn] + "'";

} else {

sWhere += sAND + sColumn + " = " + Convert.ToString(fila[sColumn]) +

" ";

}

}

}

catch (Exception ex) {

throw new Exception("Error obteniendo Primary Keys / " + ex.Message);

}

return sWhere;

}

4.3.3.3 Método Delete Este método público recibe un Domain Object e intenta eliminarlo del Data Source

especificado. El código de dicho método es el siguiente:

// Elimina el DVO en el Datasource

public bool delete(object aDO) {

try {

setDOName(aDO.GetType().Name.ToString());

string sSQL = "delete from " + this._doName + " " + getWhere(aDO);

execSQL(sSQL);

} catch(Exception ex) {

throw new Exception("Error eliminando objeto " + this._doName + " / " +

ex.Message);

}

return true;

}

Este método utiliza el mismo método getWhere utilizado en el Update, incorpora además

un nuevo método de tipo protected denominado execSQL. El código de este método se

muestra a continuación:

Page 108: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 108 de 159

// Ejecutar un SQL

protected bool execSQL(string sSQL) {

DbCommand oCommand;

if(setConnection()) {

oCommand = dbFactory.CreateCommand();

try {

oCommand.CommandText = sSQL;

oCommand.Connection = this._oCon ;

oCommand.ExecuteNonQuery();

} catch(Exception ex) {

throw ex;

}finally {

oCommand.Dispose();

oCommand = null;

}

} else return false;

return true;

}

4.4 Construcción y Cargas de los Objetos

4.4.1 Planteamiento del Requerimiento

El motor de persistencia, debe de ser capas de recuperar un objeto indicando únicamente el

ID del objeto a recuperar.

4.4.2 Diseño de la Solución

Dado el requerimiento anterior, se han diseñado dos métodos para realizar la carga de un

objeto a través de su ID

Método Parámetros Descripción 1 cargar ID de tipo numérico Devuelve la instancia de la clase llena con las

propiedades identificados por el ID numérico dado

2 cargar ID de tipo string Devuelve la instancia de la clase llena con las propiedades identificados por el ID string dado

El método “cargar” hace uso de los servicios proporcionados por otros métodos de la

misma clase, esto se muestra en la siguiente secuencia:

Page 109: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 109 de 159

Contruir Where con ID enviado

String para where

Envio de sentencia sql con filtro por ID

Exito o Exepcion

Solicitar Registro

Exito o Exepcion

Envio de Registro y Domain Object

Domain Object Poblado

Enviar SQL y Solicitar Objeto

Instancia Domain Object Poblado

Identificación de Tipo de Objeto

Creación de instancia de Tipo de Objeto

cargar getObject getDSgetWhereID RDBMSsetPropiedades

Contruir Where con ID enviado

String para where

Envio de sentencia sql con filtro por ID

Exito o Exepcion

Solicitar Registro

Exito o Exepcion

Envio de Registro y Domain Object

Domain Object Poblado

Enviar SQL y Solicitar Objeto

Instancia Domain Object Poblado

Identificación de Tipo de Objeto

Creación de instancia de Tipo de Objeto

4.4.3 Construcción de la Solución

El código C# del método sobrecargado “cargar” tanto en su versión para id numérico como string, se muestra a continuación: // Metodo cargar para menejo de ID numericos public object cargar(long id)

{

string sSQL;

object aDO;

try

{

sSQL = "select * from " + this._doName + getWhereID(id);

aDO = getObject(sSQL);

}

catch (Exception ex)

{

throw ex;

}

return aDO;

}

// Metodo cargar para menejo de ID string public object cargar(string id)

{

string sSQL;

object aDO;

try

{

Page 110: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 110 de 159

sSQL = "select * from " + this._doName + getWhereID(id);

aDO = getObject(sSQL);

}

catch (Exception ex)

{

throw ex;

}

return aDO;

}

El método cargar una ves construido el SQL con filtro Where, delega la responsabilidad de creación y poblado de los datos al método getObjet, el código de este método, se muestra a continuación: //Metodo privado que devuelve la instancia cargada del objeto a partir de

un registro private object getObject(string sSQL)

{

DataSet miDs;

object aDO;

try

{

string spaceName = this.GetType().AssemblyQualifiedName;

string objectDAOName = this.GetType().Namespace + "." + this.GetType().Name;

string objectName = "Dominio." + this._doName ;

spaceName = spaceName.Replace(objectDAOName, objectName);

Type tTipo = Type.GetType(spaceName,true,true);

aDO = Activator.CreateInstance(tTipo);

miDs = this.getDS(sSQL);

if (miDs.Tables[0].Rows.Count > 0) setPropiedades(miDs.Tables[0].Rows[0],

aDO); else throw new Exception("Problemas con el objeto " + this._doName );

}

catch (Exception ex)

{

throw new Exception("Error en objeto " + this.GetType().Name + " / " +

ex.Message);

}

finally

{

miDs = null;

}

return aDO;

}

El método cargar utiliza en su secuencia de ejecución los métodos getWhereID que

devuelve un string con el filtro Where compuesto por el ID del objeto, por su lado el

metodo getobject utiliza el método setPropiedades el cual puebla las propiedades de un

objeto con los datos de un DataRow utilizando la Reflexión.

El código de ambos métodos, se detalla a continuación:

//Metodo que devuelve una cadena con la construccion del Where con los

primarykeys del objeto

private string getWhereID(string id){

DataColumn[] colArr;

string sColumn;

int ikeys;

try {

DataSet ds = getDsSchema();

Page 111: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 111 de 159

colArr = ds.Tables[0].PrimaryKey;

ikeys = colArr.Length;

sColumn = " where " ;

if(ikeys==0) throw new Exception("Objeto " + _doName + " no tiene definido

Primary Key en el ER, imposible continuar");

for(int i = 1; i<ikeys;i++) sColumn += colArr[i].ColumnName + " = '" + id

+ "'";

} catch(Exception ex) {

throw new Exception("Error obteniendo Primary Keys / " + ex.Message );

}

return sColumn;

}

// Llenar el Domain Object a partir del DataRow invocando dinamicamente los

Setter de cada propiedad

private void setPropiedades(DataRow aRow, object aDO) {

PropertyInfo[] oProperties;

string sPropertyName="";

MethodInfo oMetodo;

try {

oProperties =

aDO.GetType().GetProperties(BindingFlags.NonPublic|BindingFlags.Instance|BindingF

lags.Static|BindingFlags.Public);

foreach(PropertyInfo oProperty in oProperties) {

sPropertyName = oProperty.Name.ToString();

if(aRow.IsNull(sPropertyName)) {

oProperty.SetValue(aDO,null,null);

} else {

oMetodo = oProperty.GetGetMethod(true);

switch (oProperty.GetSetMethod(true).ReturnType.Name.ToString()) {

case "System.String":

oProperty.SetValue(aDO, (string)aRow[sPropertyName], null);

break;

case "System.DateTime":

oProperty.SetValue(aDO, (DateTime)aRow[sPropertyName], null);

break;

case "System.Int16":

oProperty.SetValue(aDO, (Int16)aRow[sPropertyName], null);

break;

case "System.Int32":

oProperty.SetValue(aDO, (Int32)aRow[sPropertyName], null);

break;

case "System.Int64":

oProperty.SetValue(aDO, (Int64)aRow[sPropertyName], null);

break;

case "System.Decimal":

oProperty.SetValue(aDO, (Decimal)aRow[sPropertyName], null);

break;

case "System.Double":

oProperty.SetValue(aDO, (Double)aRow[sPropertyName], null);

break;

case "System.Boolean":

Boolean bValor;

if(aRow[sPropertyName].GetType().ToString().CompareTo("System.SByte")==0) {

SByte sbValor = (SByte)aRow[sPropertyName];

bValor = (sbValor.ToString().Equals("1"))?true:false;

} else

if(aRow[sPropertyName].GetType().ToString().CompareTo("System.Byte")==0) {

Byte sbValor = (Byte)aRow[sPropertyName];

bValor = (sbValor.ToString().Equals("1"))?true:false;

} else {

Page 112: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 112 de 159

bValor = (Boolean)aRow[sPropertyName];

}

oProperty.SetValue(aDO,bValor,null);

break;

case "System.Char":

oProperty.SetValue(aDO, (string)aRow[sPropertyName], null);

break;

}

}

}

} catch(Exception ex) {

throw new Exception("Error seteando la propiedad " + sPropertyName + " / "

+ ex.Message); }

}

4.5 Acceso Independiente del sistema RDBMS

4.5.1 Planteamiento del Requerimiento

La funcionalidad a construir ya que implementará la “Capa de Acceso a Datos”, debe de ser

capas de manejar eficientemente el acceso a distintos sistema de bases de datos relacionales

de forma transparente y parametrizada para el desarrollador. Esto supone que el

desarrollador solo deberá indicar dentro de la configuración del aplicativo que motor de

base de datos utilizará y el motor de persistencia debe de hacer el resto. Sin embargo esto

supone los siguientes problemas

Aunque ADO .Net 2.0 contiene una serie de objetos genéricos agrupados en el namespace

System.Data, entre otros el DataSet, DataTable, DataView, DataColumn, DataRow, etc., al

momento de interactuar con distintas bases de datos como SQL Server u Oracle, hace uso

de controles específicos para cada RDBMS. De esta forma existe una clase SqlConenction

para Microsoft SQL y una clase OraConnection para Oracle, así como MySqlConnections

para Mysql y OleConnection para acceso via OleDB.

El uso de estas clases especificas por proveedor es necesaria ya que garantiza la eficiencia

en las operaciones en contra de cada contenedor.

Si bien esta considerado el uso de acceso vía OleDB a cualquier base con este tipo de

acceso, esto ocasiona una perdida de rendimiento por lo que es conveniente utilizar los

namespaces ofrecidos por Microsoft o construidos por cada proveedor.

Page 113: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 113 de 159

La funcionalidad a construir requiere de la utilización de objetos específicos para cada

RDBMS tales como:

Clase Descripción Microsoft SQL Oracle OleDB

Connection Clase Conexión especifica para cada proveedor

SqlConnection OraConnection OleConnection

DataAdapter Adaptador de datos especifico para cada proveedor, permite incorporar un contenido de datos dentro de un DataSet.

SqlDataAdapter OraDataAdapter OleDataAdapter

Command Clase Coomand, la que ejecuta un sql en una conexión especifica para cada proveedor

SqlCommand OraCommand OleCommand

DataReader Clase para acceso conectado especifica para cada proveedor (implementa un cursor Forward Only)

SqlDataReader OraDataReader OleDataReader

4.5.2 Diseño de la Solución

Conociendo el requerimiento establecido. Donde se plantea la necesidad de crear familias

de objetos en tiempo de ejecución, el patrón idóneo para modelar una solución de este tipo

es el patrón Abstract Factory 6.

El framework .Net 2.0 posee dentro de ADO .Net 2.0 una implementación de este patrón, el

cual esta disponible en el namespace System.Data.Common, esta solución permite la

creación de objetos específicos para cada proveedor. Sin embargo a la fecha de este estudio,

únicamente existen Factorías concretas para SQL , Oracle y OLE DB, las cuales son

proporcionadas por Microsoft a través del mismo framework. Proveedores como Mysql,

Sybase, PostGress y el mismo Oracle ofrecen conectores específicos para ADO .Net, pero

6 Ver numeral 3.4.7 para mayor información sobre el patrón Abstract Factory

Page 114: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 114 de 159

estos no son heredados de la clase System.Data.Comon por lo que no pueden ser utilizados

para implementar el patrón Abstract Factory. Dado esto para el caso de Proveedores

distintos a SQL y Oracle se utilizará el método de Acceso OLE DB, esperando que en

pronto tiempo el resto de proveedores liberen conectores que si puedan ser utilizados dentro

de este esquema.

Un esquema de la solución propuesta a través del patrón Abstract Factory implementado en

.Net, se muestra a continuación:

<<Usa>>

<<Usa>>

<<Usa>>

<<Crea>>

<<Crea>>

<<Crea>>

<<Crea>>

DbProviderFactory

{abstract}

+

+

+

+

+

+

getFactory (string Provider)

createCommand ()

createConnection ()

createParameter ()

createDataAdapter ()

createTransaction ()

: DbProviderFactory

: DbCommand

: DbConnection

: DbParameter

: DbDataAdapter

: DbTransaction

DAOMasterl ibrary

SQLProviderFactory

+

+

+

+

+

createCommand ()

createConnection ()

createParameter ()

createDataAdapter ()

createTransaction ()

: SQLCommand

: SQLConnection

: SQLParameter

: SQLDataAdapter

: SQLTransaction

OraProviderFactory

+

+

+

+

+

createCommand ()

createConnection ()

createParameter ()

createDataAdapter ()

createTransaction ()

: OraCommand

: OraConnection

: OraParameter

: OraDataAdapter

: OraTransaction

DbConnection

{abstract}

DbCommand

{abstract}

SQLConnection OraConnection

SqlCommandOraCommand

ADO .Net provee la clase Abstracta DbProviderFactory la cual es capas de crear instancias

de clases xxConnections, xxCommand, xxDataAdapter, etc. Estos son referenciados a

través de productos abstractos DbConnection, DbCommand, DbDataAdapter que en

realidad contienen objetos concretos de tipo SqlConnection, SqlCommand, SqlDataAdapter

u OraConnection, OraCommand, OraDataAdapter para el caso de Oracle.

Page 115: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 115 de 159

Dado que dentro de la funcionalidad a crear se deberá manejar mecanismos de crear la

DBFactory adecuada, así como crear las cadenas de conexión correctas, etc. Se deberá

diseñar una clase separada para implementar estos mecanismos la cual proporcionara sus

servicios a la clase principal que implementara el patrón DAO.

Dado que la clase DAOMaster implementara los métodos de persistencia, la

responsabilidad de crear el DBFactory correcta, así como el de crear conexiones a la base

de datos caerá sobre una nueva clase denominada DataFactory cuyos servicios serán usados

por la clase principal DAOMaster. Esta relación se muestra en el siguiente diagrama.

DAOMasterLibrarydataFactory

<<Crea>>

<<Usa>>

0..1

1..1

DataFactory

-

-

-

dataFactory

dbFactory

dbCon

: DataFactory

: DbProviderFactory

: DbConnection

= new DataFactory()

-

+

+

+

-

DbFactory ()

getInstancia ()

getFactory ()

getConnection ()

setDB ()

: void

: DataFactory

: DbProviderFactory

: DbConnection

: void

DBProviderFactory

DAOMaster

4.5.3 Construcción de la Solución

El procedimiento de utilización de la Factory consiste en los siguientes pasos: 1. Definición de la Factory Para realizar esta tarea bastara con definir una instancia de tipo DbProvider Factory

de la siguiente manera:

Page 116: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 116 de 159

DbProviderFactory DbFactoria;

2. Instanciamiento de la Factory de acuerdo al Proveedor Teniendo la definición del tipo de dato, pasaremos al proceso de creación de la

instancia a través del método getFactory() el cual devuelve una instancia concreta

de acuerdo al argumento enviado el cual debe de indicar el namespace del

proveedor a utilizar, así:

DbFactoria = DbProviderFactory.GetFactory(“System.Data.SqlClient”);

Crea una instancia de una factory para SQL Server.

3. Definición de productos abstractos

Para utilizar objetos de tipo Connection, Command , TableAdapter o DataAdapter

dentro del código del motor de persistencia se hace referencia a objetos de tipo DB

como se muestra en las siguientes definiciones

DbConnection conn;

DbCommand command;

DbTableAdapter tableAdapter;

DbDataAdapter dataAdapter;

4. Creación de Productos concretos.

Para la instanciación de objetos concretos se hará referencia a la clase DbFactoria como se

muestra a continuación.

Conn = DbFactoria.createConnection() ; Command = DbFactoria.createCommand(); tableAdapter = DbFactoria.createTableAdapter(); dataAdapter = DbFactoria.createDataAdapter();

El código C# de la clase DataFactory se muestra a continuación: using System;

using System.Data.Common;

namespace DAOMasterLibrary

{

class DataFactory

Page 117: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 117 de 159

{

static DataFactory dataFactory = new DataFactory();

DbProviderFactory dbFactory;

DbConnection dbCon;

private void DbFactory()

{

}

static public DataFactory getInstancia()

{

return dataFactory;

}

public DbProviderFactory getFactory()

{

if (dbFactory == null) setDB();

return dbFactory;

}

public DbConnection getConnection()

{

try

{

if (dbCon == null)

{

setDB();

dbCon = dbFactory.CreateConnection();

dbCon.ConnectionString = "";

dbCon.Open();

}

}

catch (Exception ex)

{

throw new Exception("Imposible Crear Conexión a RDBMS / " +

ex.Message);

}

return dbCon;

}

private void setDB()

{

dbFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");

}

}

}

4.6 Configuración y Parametrización

4.6.1 Planteamiento del Requerimiento

Para que el motor de persistencia sea reutilizable en cualquier aplicación, debe de permitir

su parametrización, es decir el desarrollador al utilizar esta funcionalidad debe poder

indicar el tipo de dialecto o contenedor a utilizar, indicar parámetros de servidor, usuario,

password y bases de datos, etc.

Page 118: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 118 de 159

4.6.2 Diseño de la Solución

Para definir los parámetros como datos de la conexión, dialectos, etc. Se ha considerado la

creación de un archivo XML el cual será denominado DAOConfig.ini, este contendrá entre

otros los siguientes parámetros.

• Dialecto: Es el nombre del sistema RDBMS a utiliza, podrá tomar los valores

SqlClient, Oracle, MySql, OleDB.

• DataSource: Es el nombre del servidor o la ip address del datasource.

• Usuario: El nombre del usuario con el cual se crearán las conexiones hacia el

datasource

• Password: El password del usuario a conectarse.

• DataBase: El nombre de la base de datos a la cual se deberá conectar la aplicación.

4.6.3 Construcción de la Solución

El archivo DAOConfig deberá ser ubicado en el mismo directorio donde se ubique la

librería DAOMasterLibrary.dll, como generalmente se agregará como referencia a un

proyecto .Net. El directorio por defecto será el directorio bin el cual ya esta protegido para

no descargar información desde dicha ruta.

Un ejemplo del archivo de configuración, se muestra a continuación:

<DAOConfig>

<Parametros>

<Dialecto>SqlClient</dialecto>

<DataSource>Localhost<DataSource>

<Usuario>sa<Usuario>

<Password>daoMasterSA<Password>

<DataBase>Northwind<DataBase>

</Parametros>

</DAOConfig>

Page 119: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 119 de 159

Dado que la responsabilidad de crear y manejar las conexiones es de la clase DataFactory,

esta que es implementada a través del patrón Singleton, tendrá una serie de propiedades

asociadas a los parámetros ingresados en el archivo XML

namespace DAOMasterLibrary

{

class DataFactory

{

private string _dialecto;

private string _datasource;

private string _database;

private string _usuario;

private string _password;

De igual forma esta clase posee el método loadParameters() el cual se encarga de leer el

archivo XML cargando los parámetros a las propiedades de la clase. La implementación de

este método, se muestra a continuación:

private void loadParameters()

{

XPathDocument doc;

XPathNavigator nav;

try

{

StreamReader stFile = new StreamReader("DAOConfig.xml");

string xml = stFile.ReadToEnd();

stFile.Close();

doc = new XPathDocument(new StringReader(xml));

nav = doc.CreateNavigator();

_dialecto = nav.SelectSingleNode("/*/Parametros/Dialecto").InnerXml;

_datasource = nav.SelectSingleNode("/*/Parametros/DataSource").InnerXml;

_database = nav.SelectSingleNode("/*/Parametros/DataBase").InnerXml;

_usuario = nav.SelectSingleNode("/*/Parametros/Usuario").InnerXml;

_password = nav.SelectSingleNode("/*/Parametros/Password").InnerXml;

}catch (Exception ex) {

throw new Exception("Problemas cargando parametros de conexion al

datasource / " + ex.Message );

}

}

Page 120: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 120 de 159

V. RESULTADOS Y VERIFICACION EXPERIMENTAL

Este capitulo documenta procedimiento empleado para verificar la funcionalidad del

producto creado, así como los resultados obtenidos a partir de dichas pruebas.

Para la pruebas del motor de persistencia, se construyo un mantenimiento de usuarios, este

es en si, una interfase Win32 construida con C# .

5.1 Objetivo de las Pruebas

• Verificar que el motor de persistencia creado, ejecuta automáticamente las

conversiones entre operaciones con objetos a sentencias SQL y viceversa.

• Demostrar que la utilización del motor de persistencia reduce el tiempo necesario

para el desarrollo de un aplicativo.

• Demostrar que la utilización del motor de persistencia permite abstraer el diseño y

construcción del sistema de forma tal que es independiente la base de datos

empleada.

5.2 Definición del Requerimiento

Para realizar las pruebas de prototipo desarrollado, se deberá construir un aplicativo que de

mantenimiento a usuarios, ya que esta es una funcionalidad común en muchas aplicaciones.

El aplicativo deberá de contener.

• Herramienta de carga y búsqueda de usuarios

• Herramienta de Adición de Usuarios

• Herramienta de actualización de los datos de un usuario

• Herramienta de Eliminación de Usuarios.

• Del usuario nos interesan los siguientes datos:

o Cuenta asociada al usuario

o Password del Usuario

Page 121: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 121 de 159

o Nombres del Usuario

o Apellidos del Usuario

o Email del Usuario

o Si el usuario esta activo o no

o Fecha de Creación

o Fecha de Actualización de los datos del usuario

Se deben de considerar las siguientes consideraciones.

• Por razones de seguridad el password debe de persistirse de forma encriptada

• Se debe de considerar métodos de cambio de password

• No pueden existir dos usuarios con el mismo nombre de cuenta

• Los datos obligatorio para crear un usuario es el nombre de cuenta, su password y

su nombre.

• Para la implementación, se utilizará el RDBMS. SQL Server 2005 para manejar la

base de datos

5.3 Modelado y Diseño de la Solución A continuación se diseñan los distintos modelos que componen el sistema

5.3.1 Modelo de Dominio.

Dado que nuestro requerimiento solo establece un concepto, es decir el Usuario al momento

de modelar solo tendremos esta entidad la cual quedara modelada de la siguiente forma:

Usuario

-

-

-

-

-

-

-

-

cuenta

password

nombres

apell idos

email

activo

fechaCreacion

fechaActualización

: string

: string

: string

: string

: string

: bool

: DateTime

: DateTime

La clase anterior cuenta únicamente con los atributos definidos para la entidad usuario.

Estas posteriormente al aplicarles el encapsulamiento y Data Hide son convertidos en

propiedades quedando de la siguiente forma:

Page 122: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 122 de 159

Usuario

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

cuenta

password

nombres

apell idos

email

activo

fechaCreacion

fechaActualización

_cuenta

_password

_nombres

_apellidos

_email

_activo

_fechaCreacion

_fechaActualización

: string

: string

: string

: string

: string

: bool

: DateTime

: DateTime

: string

: string

: string

: string

: string

: bool

: DateTime

: DateTime

-

+

-

-

-

+

+

+

+

+

+

+

+

+

+

+

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

set_Cuenta (string value)

get_Cuenta ()

set_Password (string value)

get_Password ()

set_Nombres (string value)

get_Nombres ()

set_Apellidos (string value)

get_Apel lidos ()

set_Email (string value)

get_Email ()

set_Activo (bool value)

get_Activo ()

set_FechaCreacion (DateTime value)

get_FechaCreacion ()

set_FechaActualizacion (DateTime value)

get_FechaActualizacion ()

: void

: string

: void

: string

: void

: string

: void

: string

: void

: string

: void

: bool

: void

: DateTime

: void

: DateTime

Finalmente, se agregan métodos para soportar las operaciones de validar password, cambiar

password y encriptar el password ingresado. Además se adiciona un constructor que no

dejara se cree una instancia a menos que se ingrese la cuenta, password y nombre del

usuario, los correspondientes Setters de estas propiedades son declarados privados, para

que no puedan ser invocados externamente y las propiedades seteadas únicamente a través

del constructor. La clase queda de la siguiente forma

Page 123: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 123 de 159

Usuario

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

cuenta

password

nombres

apell idos

email

activo

fechaCreacion

fechaActualización

_cuenta

_password

_nombres

_apellidos

_email

_activo

_fechaCreacion

_fechaActualización

: string

: string

: string

: string

: string

: bool

: DateTime

: DateTime

: string

: string

: string

: string

: string

: bool

: DateTime

: DateTime

+

-

+

-

-

-

+

+

+

+

+

+

+

+

+

+

+

-

+

+

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

<<Setter>>

<<Getter>>

Usuario (string sCuenta, string sPassword, string sNombre)

set_Cuenta (string value)

get_Cuenta ()

set_Password (string value)

get_Password ()

set_Nombres (string value)

get_Nombres ()

set_Apell idos (string value)

get_Apell idos ()

set_Email (string value)

get_Email ()

set_Activo (bool value)

get_Activo ()

set_FechaCreacion (DateTime value)

get_FechaCreacion ()

set_FechaActualizacion (DateTime value)

get_FechaActualizacion ()

encryptPassword (string sCadena)

passwordIsValid (string sPassword)

cambiarPassword (string sPasswordAnterior, string sNuevoPassword)

: void

: void

: string

: void

: string

: void

: string

: void

: string

: void

: string

: void

: bool

: void

: DateTime

: void

: DateTime

: void

: bool

: bool

El código de la clase es el siguiente:

using System;

public sealed class Usuario

{

private string _Cuenta;

private string _Password;

private string _Nombres;

private string _Apellidos;

private string _Email;

private bool _Activo;

private DateTime _FechaCreacion;

private DateTime _FechaActualizacion;

public sealed void Usuario(string sCuenta, string sPassword, string sNombre)

{

// TODO: implement

}

private string Cuenta {

get {

return _Cuenta;

Page 124: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 124 de 159

}

set {

if (this._Cuenta != value)

this._Cuenta = value;

}

}

private string Password {

get {

return _Password;

}

set {

if (this._Password != value)

this._Password = value;

}

}

private string Nombres {

get {

return _Nombres;

}

set {

if (this._Nombres != value)

this._Nombres = value;

}

}

private string Apellidos {

get {

return _Apellidos;

}

set {

if (this._Apellidos != value)

this._Apellidos = value;

}

}

private string Email {

get {

return _Email;

}

set {

if (this._Email != value)

this._Email = value;

}

}

private bool Activo {

get {

return _Activo;

}

set {

if (this._Activo != value)

this._Activo = value;

}

}

private DateTime FechaCreacion {

get {

return _FechaCreacion;

}

set {

if (this._FechaCreacion != value)

this._FechaCreacion = value;

Page 125: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 125 de 159

}

}

private DateTime FechaActualizacion {

get {

return _FechaActualizacion;

}

set {

if (this._FechaActualizacion != value)

this._FechaActualizacion = value;

}

}

public sealed bool PasswordIsValid(string sPassword)

{

// TODO: implement

return false;

}

public sealed bool CambiarPassword(string sPasswordAnterior, string

sNuevoPassword)

{

// TODO: implement

return false;

}

private sealed string EncryptPassword(string sCadena)

{

// TODO: implement

return "";

}

}

5.3.2 Modelo de Acceso a Datos

Para el modelado de la Capa de Acceso a Datos, tenemos como directivas la utilización del

patrón DAO y la incorporación de la funcionalidad del motor de persistencia creado a

través de la Herencia en nuestra clase DAO. El modelado de esta capa se muestra en la

siguiente figura:

DAOMaster

DAOUsuario

+ DAOUsuario () : void

Page 126: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 126 de 159

Ya que solo utilizaremos una entidad, también en la capa de acceso a datos solo tendremos

una sola clase denominada DAOUsuario.

Gracias a la utilización del motor de persistencia la funcionalidad se heredara por lo que no

será necesario escribir mucho código, el único método que deberá de implementarse es el

constructor de la clase, en este se invocara el método de setteo del nombre del objeto de

dominio a procesar. El código generado a nivel de diseño es el siguiente:

public class DAOUsuario : DAOMaster

{

public void DAOUsuario()

{

// TODO: implement

}

}

5.3.3 Modelo de Reglas del Negocio.

Para la capa de negocio se modela una clase que se denominará NgcUsuario la cual

brindara los servicios a la capa de presentación, esta clase contendrá los métodos de

adición, actualización, eliminación y carga de una entidad. Sin embargo es importante

recalcar que la interfase de los métodos de esta clase recibirán valores primitivos, es decir

enteros, Strings, fechas, etc e internamente se manipularan como objetos. La siguiente

figura muestra el modelado de dicha clase:

NgcUsuario

+

+

+

+

+

adicionarUsuario (string sCuenta, string sPassword, string sNombre, string sApell ido, string sEmail)

actualizarUsuario (string sCuenta, string sNombre, string sApellido, string sEmail)

eliminarUsuario (string sCuenta)

cambiarPassword (string sCuenta, string sPassword, string sNuevoPassword)

obtenerUsuario (string sCuenta)

: int

: int

: int

: int

: Usuario

El código generado para la clase es el siguiente:

public sealed class NgcUsuario

{

Page 127: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 127 de 159

public sealed int AdicionarUsuario(string sCuenta, string sPassword, string

sNombre, string sApellido, string sEmail)

{

// TODO: implement

return 0;

}

public sealed int ActualizarUsuario(string sCuenta, string sNombre, string

sApellido, string sEmail)

{

// TODO: implement

return 0;

}

public int EliminarUsuario(string sCuenta)

{

// TODO: implement

return 0;

}

public int CambiarPassword(string sCuenta, string sPassword, string

sNuevoPassword)

{

// TODO: implement

return 0;

}

public Usuario ObtenerUsuario(string sCuenta)

{

// TODO: implement

return null;

}

}

El modelado final de todas las clases que interactúan es el siguiente:

Page 128: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 128 de 159

<<Usa>>

<<Crea>>

<<Usa>>

Usuario

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

-

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

<<PropertyImplementation>>

cuenta

password

nombres

apell idos

email

activo

fechaCreacion

fechaActualización

_cuenta

_password

_nombres

_apellidos

_email

_activo

_fechaCreacion

_fechaActualización

: string

: string

: string

: string

: string

: bool

: DateTime

: DateTime

: string

: string

: string

: string

: string

: bool

: DateTime

: DateTime

+

- <<Setter>>

Usuario (string sCuenta, string sPassword, string sNombre)

set_Cuenta (string value)

DAOMaster

DAOUsuario

+ DAOUsuario () : void

NgcUsuario

+

+

+

+

+

adicionarUsuario (string sCuenta, string sPassword, string sNombre, string sApell ido, string sEmail)

actualizarUsuario (string sCuenta, string sNombre, string sApell ido, string sEmail)

el iminarUsuario (string sCuenta)

cambiarPassword (string sCuenta, string sPassword, string sNuevoPassword)

obtenerUsuario (string sCuenta)

: int

: int

: int

: int

: Usuario

5.4 Construcción de la Aplicación

5.4.1 Creación de la Estructura de Datos.

Dado que el motor de persistencia creado requiere una total sincronía entre el modelo de

dominio y el las estructuras de persistencia, la mejor forma de garantizar esto como ya se

explico antes, es utilizar un CASE que pueda manejar ambos modelos es decir objetos y

datos o DDL . Para nuestro caso utilizamos el producto PowerDesigner 12.0 de la empresa

Sybase. Sin embargo se puede utilizar el producto que mas le convenga o parezca al

desarrollador.

Como solo tenemos una entidad en el modelo de dominio, igual al transformar este modelo

en un ER obtendremos una sola entidad como muestra la siguiente figura:

Page 129: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 129 de 159

Usuario

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

<<Property>>

cuenta

password

nombres

apellidos

email

activo

fechaCreacion

fechaActualización

varchar(30)

varchar(50)

varchar(50)

varchar(50)

varchar(75)

bit

datetime

datetime

El código DDL para esta entidad y generado por el CASE PowerDesigner, es el siguiente:

/*==============================================================*/

/* Table: Usuario */

/*==============================================================*/

create table Usuario (

Cuenta varchar(30) not null,

Password varchar(100) not null,

Nombres varchar(50) not null,

Apellidos varchar(50) null,

Email varchar(75) null,

Activo bit null,

FechaCreacion datetime not null,

FechaActualizacion datetime not null,

constraint PK_USUARIO primary key (Cuenta)

)

Go

Este Script se ejecutara sobre una instancia de SQL Server 2005 con las siguientes

características de conexión:

• Servidor: Localhost

• Base de Datos: Maestria

• Usuario: MaestriaUFG

• Password: Maestria$UFG$2006

5.4.2 Creación del Proyecto Visual C# Win32

Ya con el diseño de la solución y la base de datos creada, procedemos a abrir el Visual C#

2005 Express Edition y creamos un nuevo proyecto de tipo Win32 Application, como se

muestra en la siguiente imagen:

Page 130: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 130 de 159

Se puede notar que en el Solution Explorer se agregaron automáticamente las referencias a

las librerías necesarias para manejar la parte visual del proyecto.

Procederemos a agregar una referencia a nuestro motor de persistencia el cual reside dentro

del Assembly DAOMasterLibrary.dll, para esto deberemos copiar dicho dll a una ruta física

en la maquina de desarrollo y agregar la referencia a dicha ruta como se muestra a

continuación:

Page 131: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 131 de 159

Se deberá observar la referencia agregada en el proyecto como se muestra en la siguiente

imagen:

Posteriormente procederemos a incorporar el código generado a partir del modelamiento y

diseño, para organizar mejor dicho código se ha creado un Fólder al que nombramos

“Clases” y bajo este subfolders “Dominio”, “AccesoDatos” y “Negocio” donde crearemos

las clases respectivamente, esto se muestra en la siguiente imagen.

Page 132: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 132 de 159

El código final de cada una de las clases es el siguiente:

***************************** ****** Clase Usuario ********** ***************************** using System;

namespace Dominio

{

public sealed class Usuario

{

private string _Cuenta;

private string _Password;

private string _Nombres;

private string _Apellidos;

private string _Email;

private bool _Activo;

private DateTime _FechaCreacion;

private DateTime _FechaActualizacion;

public Usuario(string sCuenta, string sPassword, string sNombre)

{

_Cuenta = sCuenta;

_Password = this.EncryptPassword(sPassword);

_Nombres = sNombre;

}

private string Cuenta

{

get

{

return _Cuenta;

}

set

{

if (this._Cuenta != value)

this._Cuenta = value;

}

}

private string Password

{

get

{

return _Password;

}

set

{

if (this._Password != value)

this._Password = value;

}

}

public string Nombres

{

get

{

return _Nombres;

}

set

Page 133: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 133 de 159

{

if (this._Nombres != value)

this._Nombres = value;

}

}

public string Apellidos

{

get

{

return _Apellidos;

}

set

{

if (this._Apellidos != value)

this._Apellidos = value;

}

}

public string Email

{

get

{

return _Email;

}

set

{

if (this._Email != value)

this._Email = value;

}

}

public bool Activo

{

get

{

return _Activo;

}

set

{

if (this._Activo != value)

this._Activo = value;

}

}

public DateTime FechaCreacion

{

get

{

return _FechaCreacion;

}

set

{

if (this._FechaCreacion != value)

this._FechaCreacion = value;

}

}

public DateTime FechaActualizacion

{

get

{

return _FechaActualizacion;

}

Page 134: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 134 de 159

set

{

if (this._FechaActualizacion != value)

this._FechaActualizacion = value;

}

}

//Devuelve verdadero si el password enviado coincide con el almacenado en

la instancia

public bool PasswordIsValid(string sPassword)

{

return _Password.Equals(this.EncryptPassword(sPassword));

}

//Realiza cambio de password en instancia si el password actual enviado

coincide con el almacenado en la instancia

public bool CambiarPassword(string sPasswordActual, string

sNuevoPassword)

{

if (PasswordIsValid(sPasswordAnterior)) _Password =

EncryptPassword(sNuevoPassword);

else

throw new Exception("Password Invalido");

return true;

}

//Devuelve Cadena Encriptada con algoritmo Hash SHA

private string EncryptPassword(string sCadena)

{

return Utils.Encrypt.encryptSHA(sCadena);

}

}

}

***************************** ****** Clase DAOUsuario ****** ***************************** using System;

using System.Data;

using DAOMasterLibrary;

using Dominio;

namespace AccesoDatos

{

class DAOUsuario : DAOMaster

{

public DAOUsuario()

{

this.setDOName("usuario");

}

}

}

Page 135: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 135 de 159

***************************** ****** Clase NgcUsuario ******* *****************************

using System;

using System.Data;

using Dominio;

using AccesoDatos;

namespace Negocio

{

class NgcUsuario

{

public int AdicionarUsuario(string sCuenta, string sPassword, string

sNombre, string sApellido, string sEmail)

{

DAOUsuario daoUsuario = new DAOUsuario();;

Usuario usuario;

try

{

usuario = new Usuario(sCuenta, sPassword, sNombre);

if (!daoUsuario.existe(usuario))

{

usuario.Apellidos = sApellido;

usuario.Activo = true;

usuario.FechaCreacion = DateTime.Now;

usuario.FechaActualizacion = DateTime.Now;

daoUsuario.add(usuario);

}

else throw new Exception("Cuenta de usuario ya existe...");

}

catch (Exception ex)

{

throw new Exception("Error al intentar adicionar Usuario / " +

ex.Message);

}

finally

{

if (daoUsuario != null) daoUsuario.release();

}

return 1;

}

public int ActualizarUsuario(string sCuenta, string sNombre, string

sApellido, string sEmail)

{

DAOUsuario daoUsuario = new DAOUsuario(); ;

Usuario usuario;

try

{

usuario = (Usuario)daoUsuario.cargar(sCuenta);

usuario.Nombres = sNombre;

usuario.Apellidos = sApellido;

usuario.Email = sEmail;

usuario.FechaActualizacion = DateTime.Now;

daoUsuario.update(usuario);

}

catch (Exception ex)

{

Page 136: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 136 de 159

throw new Exception("Error al intentar actualizar Usuario / " +

ex.Message);

}

finally

{

if (daoUsuario != null) daoUsuario.release();

}

return 1;

}

public int EliminarUsuario(string sCuenta)

{

DAOUsuario daoUsuario = new DAOUsuario(); ;

try

{

daoUsuario.delete(sCuenta);

}

catch (Exception ex)

{

throw new Exception("Error al intentar eliminar Usuario / " +

ex.Message);

}

finally

{

if (daoUsuario != null) daoUsuario.release();

}

}

public int CambiarPassword(string sCuenta, string sPassword, string

sNuevoPassword)

{

DAOUsuario daoUsuario = new DAOUsuario(); ;

Usuario usuario;

try

{

usuario = (Usuario)daoUsuario.cargar(sCuenta);

usuario.CambiarPassword(sPassword, sNuevoPassword);

daoUsuario.update(usuario);

}

catch (Exception ex)

{

throw new Exception("Error al intentar actualizar Password de

Usuario / " + ex.Message);

}

finally

{

if (daoUsuario != null) daoUsuario.release();

}

}

public Usuario ObtenerUsuario(string sCuenta)

{

DAOUsuario daoUsuario = new DAOUsuario(); ;

Usuario usuario;

try

{

usuario = (Usuario)daoUsuario.cargar(sCuenta);

}

catch (Exception ex)

{

throw new Exception("Error al intentar actualizar Usuario / " +

ex.Message);

Page 137: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 137 de 159

}

finally

{

if (daoUsuario != null) daoUsuario.release();

}

return usuario;

}

}

}

***************************** ****** Clase Visual Form1 ***** *****************************

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Text;

using System.Windows.Forms;

using Negocio;

using Dominio;

namespace pruebaPersistencia

{

public partial class Form1 : Form

{

public Form1()

{

InitializeComponent();

}

private void cbtAdd_Click(object sender, EventArgs e)

{

try

{

new NgcUsuario().AdicionarUsuario(txtCuenta.Text,

txtPassword.Text, txtNombre.Text, txtApellido.Text, txtEmail.Text);

}

catch (Exception ex)

{

MessageBox.Show(ex.Message, "Error");

}

}

private void cbtUpdate_Click(object sender, EventArgs e)

{

try

{

new NgcUsuario().ActualizarUsuario(txtCuenta.Text,

txtNombre.Text, txtApellido.Text, txtEmail.Text);

}

catch (Exception ex)

{

MessageBox.Show(ex.Message, "Error");

}

}

Page 138: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 138 de 159

private void cbtDelete_Click(object sender, EventArgs e)

{

try

{

new NgcUsuario().EliminarUsuario(txtCuenta.Text);

}

catch (Exception ex)

{

MessageBox.Show(ex.Message, "Error");

}

}

private void cbtLoad_Click(object sender, EventArgs e)

{

try

{

Usuario usuario = new

NgcUsuario().ObtenerUsuario(txtCuenta.Text);

txtNombre.Text = usuario.Nombres;

txtApellido.Text = usuario.Apellidos;

txtEmail.Text = usuario.Email;

usuario = null;

}

catch (Exception ex)

{

MessageBox.Show(ex.Message, "Error");

}

}

private void button5_Click(object sender, EventArgs e)

{

this.Close();

}

}

}

5.5 Ejecución y Resultados

Construida la interfase que invoca los servicios de la capa de negocios. Al momento de

ejecutarla se obtiene la siguiente interfase:

Page 139: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 139 de 159

Al ejecutar la funcionalidad de la interfase que invoca los métodos de la capa de negocios,

se obtienen los siguientes resultados.

Ya que se esta utilizando SQL como RDBMS se utilizará el SQL Server Profiler para

verificar las sentencias enviadas por el aplicativo al motor de base de datos.

5.5.1 Operación de Adición.

Al momento de ejecutar el método de negocio adicionarUsuario, el cual crea una instancia

de la clase de acceso a datos que hereda la funcionalidad creada y se invoca el método Add

específicamente la instrucción:

daoUsuario.add(usuario);

El motor de persistencia genera la siguiente instrucción SQL:

exec sp_executesql N'INSERT INTO [Usuario] ([Cuenta], [Password], [Nombres],

[Apellidos], [Email], [Activo], [FechaCreacion], [FechaActualizacion]) VALUES

(@p1, @p2, @p3, @p4,

@p5, @p6, @p7, @p8)',N'@p1 varchar(11),@p2 varchar(44),@p3 varchar(7),@p4

varchar(8),@p5 varchar(19),@p6 bit,@p7 datetime,@p8

datetime',@p1='ufgMaestria',@p2='Vr5RWMG2az/rADYZLrrvwB3QwFB1ZmdNYWVzdHJpYQ==',@p

3='Usuario',@p4='Maestría',@p5='[email protected]',@p6=1,@p7=''2006-12-22

16:17:48:423'',@p8=''2006-12-22 16:17:48:423''

Page 140: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 140 de 159

5.5.2 Operación de Actualización:

Al momento de ejecutar el método de negocio actualizaUsuario, el cual crea una instancia

de la clase de acceso a datos que hereda la funcionalidad creada y se invoca el método

cargar específicamente la instrucción:

usuario = (Usuario)daoUsuario.cargar(sCuenta);

El motor de persistencia genera la siguiente instrucción SQL:

select * from usuario where Cuenta = 'ufgMaestria'

Posteriormente cuando se ejecuta la instrucción de acceso a datos:

daoUsuario.update(usuario);

El motor de persistencia genera la siguiente instrucción SQL:

exec sp_executesql N'UPDATE [Usuario] SET [Nombres] = @p1, [FechaActualizacion] =

@p2 WHERE (([Cuenta] = @p3) AND ([Password] = @p4) AND ([Nombres] = @p5) AND

((@p6 = 1 AND

[Apellidos] IS NULL) OR ([Apellidos] = @p7)) AND ((@p8 = 1 AND [Email] IS NULL)

OR ([Email] = @p9)) AND ((@p10 = 1 AND [Activo] IS NULL) OR ([Activo] = @p11))

AND

([FechaCreacion] = @p12) AND ([FechaActualizacion] = @p13))',N'@p1

varchar(18),@p2 datetime,@p3 varchar(11),@p4 varchar(44),@p5 varchar(7),@p6

int,@p7 varchar(8),@p8 int,@p9

varchar(19),@p10 int,@p11 bit,@p12 datetime,@p13 datetime',@p1='Usuario

Acualizado',@p2=''2006-12-22

16:20:03:923'',@p3='ufgMaestria',@p4='Vr5RWMG2az/rADYZLrrvwB3QwFB1ZmdNYWVzdHJpYQ=

=',@p5='Usuario',@p6=0,@p7='Maestría',@p8=0,@p9='[email protected]',@p10=0,@p11

=1,@p12=''2006-12-22 16:17:48:423'',@p13=''2006-12-22 16:17:48:423''

Page 141: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 141 de 159

5.5.3 Operación de Eliminación.

Al momento de ejecutar el método de negocio eliminaUsuario, el cual crea una instancia de

la clase de acceso a datos que hereda la funcionalidad creada y se invoca el método cargar

específicamente la instrucción:

usuario = (Usuario)daoUsuario.cargar(sCuenta);

El motor de persistencia genera la siguiente instrucción SQL:

select * from usuario where Cuenta = 'ufgMaestria'

Posteriormente cuando se ejecuta la instrucción de acceso a datos:

daoUsuario.delete(usuario);

El motor de persistencia genera la siguiente instrucción SQL:

exec sp_executesql N'DELETE DROM [Usuario] WHERE (([Cuenta] = @p1))',N'@p1

varchar(18), ,@p1='ufgMaestria'

5.6 Conclusiones sobre las Pruebas. Al finalizar estas pruebas después de analizar el código construido podemos concluir.

• La funcionalidad del motor de persistencia heredada en las clases DAO genera

correctamente las operaciones SQL de inserción, actualización, eliminación y carga

de objetos.

• Estas construcción es automática y transparente para el desarrollador y el usuario.

• El motor de persistencia utiliza adecuadamente los campos que funcionan como

primary key para generar los filtros y condiciones where.

• Las operaciones de Update se realizan eficientemente únicamente sobre los campos

modificados.

Page 142: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 142 de 159

VI. CONCLUSIONES Y FUTURAS LINEAS DE

INVESTIGACION

6.1 Conclusiones Generales En el desarrollo de este proyecto se muestra las ventajas del desarrollo de aplicaciones

siguiendo un modelo de desarrollo completamente orientado a objetos, donde el acceso a

datos es abstraído y separado a una capa especifica de la aplicación, donde debe de

manejarse la relación entre objetos, las tablas y registros donde serán persistidos. Si bien

como objetivo general se ha demostrado la funcionalidad del prototipo creado al aplicarlo a

esta la capa de acceso a datos, existen una serie de puntos y conclusiones más específicos

donde resaltan los siguientes:

• Sobre la operabilidad del prototipo, podemos concluir, que es sencilla ya que solo

requiere la incorporación en el proyecto .Net del Assembly DAOMasterLibrary.dll

y seguir los linimientos de uso. Dado las características de la plataforma .Net el

proyecto puede ser de cualquier tipo que requiera acceso a un RDBMS y es

independiente del lenguaje a utilizar.

• El motor de persistencia construido es parametrizable a través del archivo XML de

configuración DAOConfig.xml. Cambiando por ejemplo el dialecto en este archivo,

nuestro prototipo puede trabajar perfectamente con otra base de datos, sin ningún

problema.

• El motor de persistencia construido permite fácilmente trabajar o interactuar con

distintos sistemas RDBMS, evitando que el desarrollador se preocupe de estas

actividades. El motor de persistencia oculta esta complejidad al desarrollador

teniendo este nada más que efectuare la parametrización y especificación del

dialecto a utilizar.

• El uso de un motor de persistencia, evita que el usuario se preocupe por las

operaciones transaccionales de Acceso a Datos. El desarrollador nada mas se

Page 143: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 143 de 159

preocupara por ejecutar métodos Add, cargar, Update o Delete sobre los objetos de

dominio, el motor se encargará del resto.

• El modelo distribuido propuesto facilita la reusabilidad de código, por ejemplo las

clases DAO construidas pueden ser reutilizadas por otras aplicaciones.

• La abstracción de la capa de Acceso a Datos permite hacer operaciones a nivel de

negocios sobre objetos y no sobre registros.

• El modelado de las clases de dominio permite que los objetos imiten de la realidad

modelada y como en el caso construido no solo contengan datos, sino ejecuten

métodos propios o internos a sus datos, cosa que no es natural para un registro.

• El uso de patrones de diseño, permite que el código generado sea muy flexible y

potencia grandemente la reusabilidad.

• El uso de este material por educadores será de beneficios para estudiantes que

puedan utilizar estos ejemplo como base para construir o mejorar el código o como

simple aplicación de diversos conceptos relacionados a la ingeniería de software.

6.2 Futuras Líneas de investigación. Dado que el prototipo desarrollado en este documento, esta limitado en su diseño y

funcionalidad principalmente por factores de tiempo, existen ciertos aspectos no

considerados en este documento que podrían ser desarrollados como futuras líneas de

investigación.

Entre esas posibles líneas de investigación se proponen las siguientes:

6.2.1 Manejo de Herencia y Composición.

El objetivo de este tema, es el de extender la funcionalidad actual del motor con el fin de

dar soporte a la herencia y la composición. Investigando la forma mas eficiente de definir

este tipo de relaciones y manejarlas al momento de ser persistidas.

Page 144: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 144 de 159

Se propone este tema, debido a que la herencia es una de las principales propiedades de la

Orientación a Objetos, es una de las características que más denotan la diferencia al

construir un modelo orientado a objetos contra uno relacional u orientado a datos. El

soporte de esta funcionalidad al igual que el caso de la composición en el motor de

persistencia como ya lo hacen productos como Hibernate, mejoraría en gran medida la

utilidad de esta herramienta.

6.2.2 Eficiencia y Rendimiento.

El desarrollo de este tema, abarca un proceso de revisión completo al aplicativo de tal

forma de buscar los mecanismos y técnicas mas eficientes para la construcción de los

métodos, documentando los resultados y exponiendo el porque de dichas mejoras y como

impactan el rendimiento de la funcionalidad construida en un ambiente de múltiples

usuarios o con cargas considerables de datos. Se propone tratar temas como manejo de

pools y cache de objetos y conexiones, etc.

Se propone este tema dado que los ejemplos planteados en este documento han sido

orientados más que todo a la funcionalidad en si del producto y no a un uso masivo o con

grandes cargas de estrés. Lo que permitiría la utilización de este modelo en aplicaciones de

tipo Enterprise o de alto rendimiento.

6.2.3 Ejecución sobre plataformas no Windows.

Este tema esta orientado a la ejecución del motor sobre una plataforma no Windows, esto

debido a las limitantes de la plataforma .Net y a que actualmente existen ya proyectos muy

avanzados de ejecución del framework sobre otras plataformas, como el proyecto Mono

(http://www.mono-project.com) , esto brindaría la oportunidad de ejecutar dicho aplicativo

sobre plataformas Linux, Unix, Mac, etc.

Page 145: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 145 de 159

VII. Bibliografía y Referencias Estudiadas.

• Design Patterns: Elements of Reusable Object-Oriented Software (Erich Gamma,

Richard Helm, Ralph Johnson and John Vlissides) 1995

• Paulk, Paul C. et al. The Capability Maturity Model, Guidelines for improving the

software process, CMU/SEI, Addison-Wesley, 1995.

• CBA Lead Assessor Training. Participant’s Guide. December, 2001. Version 1.2.

Software Engineering Institute. Carnegie Mellon University.

• Kitson David. CMMI: Current status & standardization aspects. SPIN meeting at

LA, October 2000.

• Kulpa, Margaret. CMM not for the little guy? SEPG Conference, February 2002.

• Servello, Kasse Tim. Et al. Panel. The loyal opposition versus the CMMI

champions: A frank discussion of CMMI models. Setting the stage. SEPG

Conference, February 2002.

• Diseño de Sistemas de Bases de Datos Merche Marqués. 12 de abril de 2002

Cattell, R.G. The Object Database Standard: ODMG-93 (Release 1.2). Morgan

Kauffman Publishers. San Francisco, 1995.

• Codd, E.F. A Relational Model of Data for Large Shared Data Banks. CACM

13(6): 377-387. 1970.

• Elmasri, R. & Navathe, S.B. Fundamentals of Database Systems 3e. Addison

Wesley, 2000.

• McClure, S. IDC Bulletin #14821E. August, 1997. Nahouraii, E. & Petry, F.

Object-Oriented Databases. IEEE, 1991.

• Rao, B.R. Object-Oriented Databases: Technology, Applications, and Products

McGraw-Hill. New York, 1994.

• Stonebraker, M. Architectural Options for Object-Relational DBMSs. Informix

Software, CA. Feb, 1997.

Page 146: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 146 de 159

• Stonebraker, M. Object-Relational DBMS: The Next Wave. Informix Software, CA.

Stonebraker, M., Brown, P., and Moore, D. Object-Relational DBMSs: Tracking the

Next Great Wave 2e. Morgan-Kauffman Publishers. San Francisco, 1999.

Page 147: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 147 de 159

VIII. ANEXO A: Código Fuente del Motor de Persistencia

********************************************************************************

**** Clase: DataFactoy

**** Descripción: Clase encargada del manejo de los factories y conexiones

********************************************************************************

using System;

using System.Data;

using System.Data.Common;

using System.Xml;

using System.Xml.XPath;

using System.IO;

namespace DAOMasterLibrary

{

class DataFactory

{

static DataFactory dataFactory = new DataFactory();

DbProviderFactory dbFactory;

DbConnection dbCon;

private string _dialecto;

private string _datasource;

private string _database;

private string _usuario;

private string _password;

private void DbFactory()

{

}

static public DataFactory getInstancia()

{

return dataFactory;

}

public DbProviderFactory getFactory()

{

if (dbFactory == null) setDB();

return dbFactory;

}

public DbConnection getConnection()

{

try

{

if (dbCon == null)

{

setDB();

dbCon = dbFactory.CreateConnection();

dbCon.ConnectionString = getStrCon();

dbCon.Open();

}

if (dbCon.State == ConnectionState.Closed || dbCon.State ==

ConnectionState.Broken)

{

dbCon.ConnectionString = getStrCon();

dbCon.Open();

}

}

catch (Exception ex)

{

throw new Exception("Imposible Crear Conexión a RDBMS / " + ex.Message);

}

return dbCon;

}

Page 148: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 148 de 159

private void setDB()

{

loadParameters();

switch (_dialecto.ToUpper())

{

case "SQLCLIENT":

dbFactory = DbProviderFactories.GetFactory("System.Data.SqlClient");

break;

case "ORACLE":

dbFactory = DbProviderFactories.GetFactory("System.Data.OraClient");

break;

case "MYSQL":

dbFactory = DbProviderFactories.GetFactory("System.Data.Odbc");

break;

case "OLEDB":

dbFactory = DbProviderFactories.GetFactory("System.Data.OleDb");

break;

case "ODBC":

dbFactory = DbProviderFactories.GetFactory("System.Data.Odbc");

break;

}

}

private string getStrCon()

{

string strCon="";

switch (_dialecto.ToUpper())

{

case "SQLCLIENT":

strCon = "Server=" + _datasource + ";Database=" + _database + ";User

ID=" + _usuario + ";Password=" + _password + ";Trusted_Connection=False";

break;

case "ORACLE":

strCon = "Data Source=" + _datasource + ";User Id=" + _usuario +

";Password=" + _password + ";Integrated Security=no;";

break;

case "MYSQL":

strCon = "Driver={MySQL ODBC 3.51 Driver};Server=" + _datasource +

";Database=" + _database + ";User=" + _usuario + ";Password=" + _password + ";Option=3";

break;

}

return strCon;

}

private void loadParameters()

{

XPathDocument doc;

XPathNavigator nav;

try

{

StreamReader stFile = new StreamReader("DAOConfig.xml");

string xml = stFile.ReadToEnd();

stFile.Close();

doc = new XPathDocument(new StringReader(xml));

nav = doc.CreateNavigator();

_dialecto = nav.SelectSingleNode("/*/Parametros/Dialecto").InnerXml;

_datasource = nav.SelectSingleNode("/*/Parametros/DataSource").InnerXml;

_database = nav.SelectSingleNode("/*/Parametros/DataBase").InnerXml;

_usuario = nav.SelectSingleNode("/*/Parametros/Usuario").InnerXml;

_password = nav.SelectSingleNode("/*/Parametros/Password").InnerXml;

}

catch (Exception ex)

{

throw new Exception("Problemas cargando parametros de conexion al datasource

/ " + ex.Message );

}

}

}

}

Page 149: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 149 de 159

********************************************************************************

**** Clase: DaoMaster

**** Descripción: Clase encargada de implementar la funcionalidad del motor

********************************************************************************

using System;

using System.Data;

using System.Data.Common;

using System.Reflection;

using System.Collections;

namespace DAOMasterLibrary

{

public abstract class DAOMaster : IDisposable

{

private DbConnection _oCon;

private string _doName;

private DbProviderFactory dbFactory;

private DataSet dsSchema;

protected bool disposed;

//Constructor

public DAOMaster()

{

dbFactory = DataFactory.getInstancia().getFactory();

}

//Getter y Setter de la Propieda Conexión

private DbConnection Conn

{

get

{

return _oCon;

}

set

{

if (this._oCon != value)

this._oCon = value;

}

}

//Getter y Setter de la Propieda Nombre del Domain Object

private string doName

{

get

{

return _doName;

}

set

{

if (this._doName != value)

this._doName = value;

}

}

//Setter del Domain Object Name

protected void setDOName(string sName)

{

if (dbFactory == null) dbFactory = DataFactory.getInstancia().getFactory();

this._doName = sName;

}

//Metodo Privado que obtiene uan conexion asignandola a la instancia actual

private bool setConnection()

{

try

{

if (_oCon == null) _oCon = DataFactory.getInstancia().getConnection();

Page 150: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 150 de 159

if (_oCon.State == ConnectionState.Closed || _oCon.State ==

ConnectionState.Broken) _oCon = DataFactory.getInstancia().getConnection();

} catch(Exception ex) {

throw new Exception("Error intentando obtener conexión / " + ex.Message );

}

return true;

}

//Función protected que ejecuta y devuelve un DataSet

protected DataSet getDS(string SqlString){

DataSet ds;

DbCommand oCommand;

DbDataAdapter oAdapter;

try {

if(setConnection()) {

ds = new DataSet() ;

oCommand = _oCon.CreateCommand();

oAdapter = dbFactory.CreateDataAdapter();

oCommand.Connection = _oCon;

oCommand.CommandType = CommandType.Text;

oCommand.CommandText = SqlString;

oAdapter.SelectCommand = oCommand;

oAdapter.Fill(ds);

} else {

return null;

}

} catch(Exception ex) {

throw ex;

}

return ds;

}

//Función privada que ejecuta y devuelve el Schema del Objeto mapeado

private DataSet getDsSchema(){

if (dsSchema != null) return dsSchema;

else

{

DataSet ds;

DbCommand oCommand;

DbDataAdapter oAdapter;

string SqlString = "select * from " + this._doName;

try

{

if (setConnection())

{

ds = new DataSet();

oCommand = _oCon.CreateCommand();

oAdapter = dbFactory.CreateDataAdapter();

oCommand.Connection = _oCon;

oCommand.CommandType = CommandType.Text;

oCommand.CommandText = SqlString;

oAdapter.SelectCommand = oCommand;

oAdapter.FillSchema(ds, SchemaType.Mapped);

dsSchema = ds;

}

else

{

return null;

}

}

catch (Exception ex)

{

throw ex;

}

return ds;

}

}

//Metodo getWhereId para ID de tipo Numero

private string getWhereID(long id) {

DataColumn[] colArr;

string sColumn;

int ikeys;

Page 151: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 151 de 159

try

{

DataSet ds = getDsSchema();

colArr = ds.Tables[0].PrimaryKey;

ikeys = colArr.Length;

sColumn = " where ";

if (ikeys == 0) throw new Exception("Objeto " + _doName + " no tiene

definido Primary Key en el ER, imposible continuar");

for (int i = 0; i < ikeys; i++) sColumn += colArr[i].ColumnName + " = " + id

+ " ";

}

catch (Exception ex)

{

throw new Exception("Error obteniendo Primary Keys / " + ex.Message);

}

return sColumn;

}

//Metodo que devuelve una cadena con la construccion del Where con los primarykeys

del objeto

private string getWhereID(string id){

DataColumn[] colArr;

string sColumn;

int ikeys;

try {

DataSet ds = getDsSchema();

colArr = ds.Tables[0].PrimaryKey;

ikeys = colArr.Length;

sColumn = " where " ;

if(ikeys==0) throw new Exception("Objeto " + _doName + " no tiene definido

Primary Key en el ER, imposible continuar");

for(int i = 0; i<ikeys;i++) sColumn += colArr[i].ColumnName + " = '" + id +

"'";

} catch(Exception ex) {

throw new Exception("Error obteniendo Primary Keys / " + ex.Message );

}

return sColumn;

}

// Devuelve el Schema en formato XML StrinReader del DVO actual

private System.IO.StringReader getSchema() {

string sXML = this.getDsSchema().GetXmlSchema();

return new System.IO.StringReader(sXML);

}

// Generar la Sentencia where correspondiente usando los primary key y sus valores

private string getWhere(object aDO)

{

DataColumn[] colArr;

string sWhere = "", sColumn, sAND, sType;

DataSet ds;

DataRow fila;

int ikeys;

try

{

ds = getDsSchema();

fila = ds.Tables[0].NewRow();

getPropiedades(fila,aDO,false);

colArr = ds.Tables[0].PrimaryKey;

ikeys = colArr.Length;

sColumn = "";

sWhere = " where ";

if (ikeys == 0) throw new Exception("Objeto " + _doName + " no tiene

definido Primary Key en el ER, imposible continuar");

for (int i = 0; i < ikeys; i++) {

sAND = (i>0)? " AND ":"";

sColumn = colArr[i].ColumnName;

sType = colArr[i].DataType.Name.ToString();

if(sType.CompareTo("String")==0||sType.CompareTo("Char")==0) {

sWhere += sAND + sColumn + " = '" + fila[sColumn] + "'";

} else {

Page 152: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 152 de 159

sWhere += sAND + sColumn + " = " + Convert.ToString(fila[sColumn])

+ " ";

}

}

}

catch (Exception ex)

{

throw new Exception("Error obteniendo Primary Keys / " + ex.Message);

}

return sWhere;

}

// Objetivo: Actualizar el Dataset en el DataSource

private int saveDS(DataSet ds)

{

string sSQL = "select * from " + this._doName;

DbDataAdapter oAdapter;

DbCommandBuilder oCBuilder;

DbCommand oCommand;

int iResult = 0;

if (setConnection())

{

try

{

oAdapter = dbFactory.CreateDataAdapter();

oCommand = _oCon.CreateCommand();

oCommand.CommandText = sSQL;

oAdapter.SelectCommand = oCommand;

oCBuilder = dbFactory.CreateCommandBuilder();

oCBuilder.DataAdapter = oAdapter;

iResult = oAdapter.Update(ds);

oAdapter.Dispose();

oAdapter = null;

}

catch (Exception ex)

{

throw new Exception("Error actualizando objeto " + this._doName + " / "

+ ex.Message);

}

}

return iResult;

}

// Actualizar el Dataset en el DataSource utilizando filtro where por primary

Key(Metodo Sobrecargado)

private int saveDS( DataSet ds, bool useWhere, object aDO) {

string sSQL = "select * from " + this._doName;

DbDataAdapter oAdapter;

DbCommandBuilder oCBuilder;

DbCommand oCommand;

int iResult = 0;

sSQL = (useWhere)? sSQL + " " + this.getWhere(aDO):sSQL;

if (setConnection())

{

try

{

oAdapter = dbFactory.CreateDataAdapter();

oCommand = _oCon.CreateCommand();

oCommand.CommandText = sSQL;

oAdapter.SelectCommand = oCommand;

oCBuilder = dbFactory.CreateCommandBuilder();

oCBuilder.DataAdapter = oAdapter;

iResult = oAdapter.Update(ds);

oAdapter.Dispose();

oAdapter = null;

}

catch (Exception ex)

{

throw new Exception("Error actualizando objeto " + this._doName + "

/ " + ex.Message);

}

Page 153: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 153 de 159

}

return iResult;

}

// Obtiene las propiedades de un Domain Object asignandolas a un DataRow a traves de

invocaciones dinamicas a los Getter

private void getPropiedades(DataRow aRow, object aDO, bool actualizar){

PropertyInfo[] oProperties;

string sPropertyName="";

MethodInfo oMetodo;

try {

oProperties =

aDO.GetType().GetProperties(BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static

|BindingFlags.Public);

foreach(PropertyInfo oProperty in oProperties) {

sPropertyName = oProperty.Name.ToString();

oMetodo = oProperty.GetGetMethod(true);

if (!(actualizar&&aRow.Table.Columns[sPropertyName].ReadOnly))

{

switch (oMetodo.ReturnType.ToString())

{

case "System.String":

aRow[sPropertyName] = (string)oMetodo.Invoke(aDO, null);

break;

case "System.DateTime":

aRow[sPropertyName] = (DateTime)oMetodo.Invoke(aDO, null);

break;

case "System.Int16":

aRow[sPropertyName] = (Int16)oMetodo.Invoke(aDO, null);

break;

case "System.Int32":

aRow[sPropertyName] = (Int32)oMetodo.Invoke(aDO, null);

break;

case "System.Int64":

aRow[sPropertyName] = (Int64)oMetodo.Invoke(aDO, null);

break;

case "System.Decimal":

aRow[sPropertyName] = (Decimal)oMetodo.Invoke(aDO, null);

break;

case "System.Double":

aRow[sPropertyName] = (Double)oMetodo.Invoke(aDO, null);

break;

case "System.Boolean":

aRow[sPropertyName] = (Boolean)oMetodo.Invoke(aDO, null);

break;

case "System.Char":

aRow[sPropertyName] = (Char)oMetodo.Invoke(aDO, null);

break;

}

}

}

} catch(Exception ex) {

throw new Exception("Error accesando la propiedad " + sPropertyName + " / "

+ ex.Message);

}

}

// Llenar el Domain Object a partir del DataRow invocando dinamicamente los Setter

de cada propiedad

private void setPropiedades(DataRow aRow, object aDO) {

PropertyInfo[] oProperties;

string sPropertyName="";

try {

oProperties =

aDO.GetType().GetProperties(BindingFlags.NonPublic|BindingFlags.Instance|BindingFlags.Static

|BindingFlags.Public);

foreach(PropertyInfo oProperty in oProperties) {

sPropertyName = oProperty.Name.ToString();

if(aRow.IsNull(sPropertyName)) {

oProperty.SetValue(aDO,null,null);

} else {

Page 154: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 154 de 159

switch (oProperty.GetGetMethod(true).ReturnType.ToString())

{

case "System.String":

oProperty.SetValue(aDO, (string)aRow[sPropertyName], null);

break;

case "System.DateTime":

oProperty.SetValue(aDO, (DateTime)aRow[sPropertyName],

null);

break;

case "System.Int16":

oProperty.SetValue(aDO, (Int16)aRow[sPropertyName], null);

break;

case "System.Int32":

oProperty.SetValue(aDO, (Int32)aRow[sPropertyName], null);

break;

case "System.Int64":

oProperty.SetValue(aDO, (Int64)aRow[sPropertyName], null);

break;

case "System.Decimal":

oProperty.SetValue(aDO, (Decimal)aRow[sPropertyName], null);

break;

case "System.Double":

oProperty.SetValue(aDO, (Double)aRow[sPropertyName], null);

break;

case "System.Boolean":

Boolean bValor;

if(aRow[sPropertyName].GetType().ToString().CompareTo("System.SByte")==0) {

SByte sbValor = (SByte)aRow[sPropertyName];

bValor = (sbValor.ToString().Equals("1"))?true:false;

} else

if(aRow[sPropertyName].GetType().ToString().CompareTo("System.Byte")==0) {

Byte sbValor = (Byte)aRow[sPropertyName];

bValor = (sbValor.ToString().Equals("1"))?true:false;

} else

if(aRow[sPropertyName].GetType().ToString().CompareTo("System.Int16")==0) {

Int16 sbValor = (Int16)aRow[sPropertyName];

bValor = (sbValor.ToString().Equals("1"))?true:false;

} else {

bValor = (Boolean)aRow[sPropertyName];

}

oProperty.SetValue(aDO,bValor,null);

break;

case "System.Char":

oProperty.SetValue(aDO, (string)aRow[sPropertyName], null);

break;

}

}

}

} catch(Exception ex) {

throw new Exception("Error seteando la propiedad " + sPropertyName + " / " +

ex.Message);

}

}

// Metodo cargar para manejo de ID numericos

public object cargar(long id)

{

string sSQL;

object aDO;

try

{

sSQL = "select * from " + this._doName + getWhereID(id);

aDO = getObject(sSQL);

}

catch (Exception ex)

{

throw ex;

}

Page 155: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 155 de 159

return aDO;

}

// Metodo cargar para manejo de ID string

public object cargar(string id)

{

string sSQL;

object aDO;

try

{

sSQL = "select * from " + this._doName + getWhereID(id);

aDO = getObject(sSQL);

}

catch (Exception ex)

{

throw ex;

}

return aDO;

}

//Metodo privado que devuelve la instancia cargada del objeto a partir de un

registro

private object getObject(string sSQL)

{

DataSet miDs;

object aDO;

try

{

string spaceName = this.GetType().AssemblyQualifiedName;

string objectDAOName = this.GetType().Namespace + "." + this.GetType().Name;

string objectName = "Dominio." + this._doName ;

spaceName = spaceName.Replace(objectDAOName, objectName);

Type tTipo = Type.GetType(spaceName,true,true);

aDO = Activator.CreateInstance(tTipo);

miDs = this.getDS(sSQL);

if (miDs.Tables[0].Rows.Count > 0) setPropiedades(miDs.Tables[0].Rows[0],

aDO); else throw new Exception("Problemas con el objeto " + this._doName );

}

catch (Exception ex)

{

throw new Exception("Error en objeto " + this.GetType().Name + " / " +

ex.Message);

}

finally

{

miDs = null;

}

return aDO;

}

//Metodo que verifica si una instancia de una clase ya ha sido persistida

public Boolean existe(object aDO)

{

long iResult = 0;

string sSQL;

try

{

sSQL = "select count(*) from " + _doName + " " + getWhere(aDO);

iResult = getVal(sSQL);

}

catch (Exception ex)

{

throw ex;

}

return (iResult > 0) ? true : false;

}

Page 156: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 156 de 159

// Ejecutar un SQL

protected bool execSQL(string sSQL) {

DbCommand oCommand;

if(setConnection()) {

oCommand = dbFactory.CreateCommand();

try {

oCommand.CommandText = sSQL;

oCommand.Connection = this._oCon ;

oCommand.ExecuteNonQuery();

} catch(Exception ex) {

throw ex;

}finally {

oCommand.Dispose();

oCommand = null;

}

} else return false;

return true;

}

// Obtener un valor numerico escalar

protected long getVal(string sSQL) {

DbCommand oCommand;

long iresult = 0;

if(setConnection()) {

oCommand = dbFactory.CreateCommand();

try {

oCommand.CommandText = sSQL;

oCommand.Connection = this._oCon ;

iresult = Convert.ToInt64(oCommand.ExecuteScalar());

} catch(Exception ex) {

throw ex;

}finally {

oCommand.Dispose();

oCommand = null;

}

} ;

return iresult;

}

// Obtener un valor String escalar

protected string getStrVal(string sSQL)

{

DbCommand oCommand;

string sResult ;

if (setConnection())

{

oCommand = dbFactory.CreateCommand();

try

{

oCommand.CommandText = sSQL;

oCommand.Connection = this._oCon;

sResult = Convert.ToString(oCommand.ExecuteScalar());

}

catch (Exception ex)

{

throw ex;

}

finally

{

oCommand.Dispose();

oCommand = null;

}

}

else return null;

return sResult;

}

// Obtener un valor decimal

protected decimal getDecimalVal(string sSQL)

{

DbCommand oCommand;

Page 157: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 157 de 159

decimal dResult = new decimal();

if (setConnection())

{

oCommand = dbFactory.CreateCommand();

try

{

oCommand.CommandText = sSQL;

oCommand.Connection = this._oCon;

dResult = Convert.ToDecimal(oCommand.ExecuteScalar());

}

catch (Exception ex)

{

throw ex;

}

finally

{

oCommand.Dispose();

oCommand = null;

}

}

return dResult;

}

// Obtener un valor de tipo DateTime

protected DateTime getDatetimeVal(string sSQL)

{

DbCommand oCommand;

DateTime dResult = new DateTime();

if (setConnection())

{

oCommand = dbFactory.CreateCommand();

try

{

oCommand.CommandText = sSQL;

oCommand.Connection = this._oCon;

dResult = Convert.ToDateTime(oCommand.ExecuteScalar());

}

catch (Exception ex)

{

throw ex;

}

finally

{

oCommand.Dispose();

oCommand = null;

}

}

return dResult;

}

// Metodo publico encargado de salvar el Domain Object en el Datasource

public long add(object aDO) {

try {

DataSet oDS = new DataSet() ;

oDS.ReadXmlSchema(getSchema());

DataRow oRow = oDS.Tables[0].NewRow();

getPropiedades(oRow,aDO,false);

oDS.Tables[0].Rows.Add(oRow);

saveDS(oDS);

} catch (Exception ex) {

throw new Exception("Error Insertando objeto " + this._doName + " / " +

ex.Message);

}

return getID();

}

public virtual long getID()

{

return 0;

}

Page 158: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 158 de 159

//Metodo publico encargado de actualizar el Domain Object en el Datasource

public bool update(object aDO) {

try {

string sSQL = "select * from " + this._doName + " " + this.getWhere(aDO);

DataSet oDS, fDS;

fDS = new DataSet();

fDS.ReadXmlSchema(getSchema());

oDS = getDS(sSQL);

DataRow oRow = oDS.Tables[0].Rows[0];

DataRow fRow = fDS.Tables[0].NewRow();

foreach(DataColumn oColumn in oDS.Tables[0].Columns) {

fRow[oColumn.ColumnName.ToString()] =

oRow[oColumn.ColumnName.ToString()];

}

fDS.Tables[0].Rows.Add(fRow);

fDS.AcceptChanges();

getPropiedades(fRow, aDO,true);

saveDS(fDS,true,aDO);

} catch(Exception ex) {

throw new Exception("Error actualizando objeto " + this._doName + " / " +

ex.Message);

}

return true;

}

// Metodo publico encargado de eliminar el objeto en el Datasource

public bool delete(object aDO) {

try {

string sSQL = "delete from " + this._doName + " " + getWhere(aDO);

execSQL(sSQL);

} catch(Exception ex) {

throw new Exception("Error eliminando objeto " + this._doName + " / " +

ex.Message);

}

return true;

}

// Metodo publico encargado de eliminar el objeto en el Datasource a partir de un Id

string

public bool deleteById(string id ) {

try

{

string sSQL = "delete from " + this._doName + " " + getWhereID(id);

execSQL(sSQL);

}

catch (Exception ex)

{

throw new Exception("Error eliminando objeto " + this._doName + " / " +

ex.Message);

}

return true;

}

// Metodo publico encargado de eliminar el objeto a partir de un Id numerico

public bool deleteById(long id)

{

try

{

string sSQL = "delete from " + this._doName + " " + getWhereID(id);

execSQL(sSQL);

}

catch (Exception ex)

{

throw new Exception("Error eliminando objeto " + this._doName + " / " +

ex.Message);

}

return true;

}

Page 159: Tesis-persistencia-maestria

Maestría en Informática Aplicada a Redes

Página 159 de 159

//Metodo publico que devuelve un Dataset con todos los registros de una tabla

filtrados por el Where enviado

public DataSet getDSWhere(string sWhere) {

try

{

if(setConnection()) return getDS("select * from " + this._doName + " where

" + sWhere);

return null;

} catch (Exception ex) {

throw new Exception("Imposible Obtener Datos de Objeto " + this._doName +

" filtrando por" + sWhere + " / " + ex.Message);

}

}

//Devuelve un Dataset con todos los registros de una tabla

public DataSet getDSAllRecords()

{

try

{

if (setConnection()) return getDS("select * from " + this._doName );

return null;

}

catch (Exception ex)

{

throw new Exception("Imposible Obtener Datos de Objeto " + this._doName +

" / " + ex.Message);

}

}

//Metodo Privado que libera la conexion

private bool releaseConnection()

{

try

{

if (_oCon != null) _oCon.Close();

}

catch (Exception ex)

{

throw new Exception("Error intentando liberar conexión / " + ex.Message);

}

return true;

}

//Metodo publico para liberar recursos y es invocado por el usuario

public void Dispose()

{

Dispose(true);

GC.SuppressFinalize(this);

}

//Metodo protegido que implementa el dispose de los recursos

protected virtual void Dispose(bool disposing)

{

if (!disposed)

{

if (disposing)

{

releaseConnection();

}

disposed = true;

}

}

//Destructor del objeto que sera llamado por el Garbage Colector e invocara el

metodo Dispose

~DAOMaster() {

Dispose(false);

}

}

}