lunes, 7 de diciembre de 2015

APO1 - Nivel 4 - Club Social

Índice

1. Introducción
2. Palabras Clave
3. Problema
3.1 Enunciado
3.2 Interfaz gráfica de usuario (versión Java)
4. Requerimientos
4.1 R1 - Registrar una persona autorizada por un socio
4.2 R2 - Pagar una factura
4.3 R3 - Afiliar un socio al club
4.4 R4 - Registrar un consumo en la cuenta de un socio
5. Modelo del Mundo del Problema
6. Modelo de la Interfaz Gráfica de Usuario
7. Modelo de Pruebas Unitarios
8. Repositorio: Exploración de Código Fuente C#
9. Recursos
9.1 Java
9.2 C#
9.2.1 Solución y proyectos
9.2.2 Documentación código fuente
9.2.3 Aplicación en ejecución
9.2.3.1 Capturas de pantalla
9.2.3.2 Demostración
10. Cambios
11. Conclusiones
12. Literatura & Enlaces

1. Introducción

Se inicia esta serie de aplicaciones del Nivel 4 de Algoritmia y Programación Orientada a Objetos 1 (APO1) donde principalmente se comprende los conceptos de definición de contrato de un método, uso del contrato para la invocación de un método, asignación de responsabilidades a clases, uso de la técnica de dividir y conquistar para facilitar la resolución de un problema, entre otras más.


En cuanto a la primea aplicación a desarrollar en este nivel, ésta consiste en la administración de un club social. En esta aplicación se crean socios y asignar las personas que poseen autorización para el ingreso al club y uso de sus servicios. Además, cuenta con la administración de los gastos generados por las personas autorizadas; gastos que serán cargados a la cuenta del socio.

2. Palabras Clave

  • .NET
  • Aplicación
  • Clase
  • Cupi2
  • Cupi2.NET
  • Enumeración
  • Excepción
  • Software

3. Problema

3.1 Enunciado

Descripción literal del problema original "Enunciado" (2015):

Se quiere construir una aplicación para un club, el club tiene socios afiliados y personas autorizadas por los socios. Cada socio está identificado con su nombre y su cédula, el autorizado se caracteriza por su nombre y la cédula del socio quien lo autoriza. Dentro del club se pueden realizar consumos que serán cargados al socio, esto se manejará en la contabilidad del club. Estos consumos se caracterizan por un concepto que lo identifica y el valor de los consumido.

Las cuentas pendientes de un socio es la lista de sus facturas. Cada factura contiene el concepto y el valor del consumo o servicio que el club lee prestó. Los pagos se realizarán de acuerdo con la factura que el usuario seleccione.

3.2 Interfaz gráfica de usuario (versión Java)


En la Figura 1 se presenta la interfaz gráfica de usuario de la aplicación Club construida con los elementos de programa del lenguaje de programación Java.
GUI en Java
Figura 1. GUI en Java.

4. Requerimientos

4.1 R1 - Registrar una persona autorizada por un socio

Código: R1

Nombre: Registrar una persona autorizada por un socio

Descripción: Los socios tienen un conjunto de personas autorizadas que pueden ingresar al club y hacer consumos en sus restaurantes. Este requerimiento permite a un socio registrar una de estas personas.

Entradas:
  • Nombre: Nombre de la persona autorizada por el socio.
  • Cédula: Cédula del socio al que se registrará el autorizado.
Resultados:
  • Registro de autorizado: El socio tiene una nueva persona autorizada.

4.2 R2 - Pagar una factura

Código: R2

Nombre: Pagar una factura

Descripción: La factura que quiere pagar el socio, de su lista de facturas pendientes.

Entradas:
  • Socio: Cédula del socio que pagará la factura.
  • Factura: La factura que quiere pagar el socio, de su lista de facturas pendientes.
Resultados:
  • La factura ha sido pagada: La factura cancelada ya no está pendiente para el socio.

4.3 R3 - Afiliar un socio al club

Código: R3

Nombre: Afiliar un socio al club

Descripción: Se agregar un nuevo socio al club.

Entradas:
  • Nombre: Nombre del socio.
  • Cédula: Cédula del socio.
Resultados:
  • Afiliación del socio: Se adicionó el nuevo socio al club.

4.4 R4 - Registrar un consumo en la cuenta de un socio

Código: R4

Nombre: Registrar un consumo en la cuenta de un socio

Descripción: El socio o una de sus personas autorizadas, puede agregar un consumo a la cuenta del socio.

Entradas:
  • Concepto: Concepto del consumo.
  • Valor: Valor por el cual fue el consumo.
  • Nombre: Persona que realizó el consumo.
Resultados:
  • Registro de consumo: Se crea una nueva factura por el valor del consumo y se rgistra al socio.

5. Modelo del Mundo del Problema

En la Figura 2 se describe el diagrama UML con las entidades que integran el modelo del mundo del problema (dominio). (Original en "Modelo conceptual" (2015)).
Modelo del mundo del problema
Figura 2. Modelo del mundo del problema.

6. Modelo de la Interfaz Gráfica de Usuario

En la Figura 3 se muestra el diagrama UML que describe los controles visuales que integran la interfaz gráfica de usuario. (Original en "Interfaz" (2015)).
Modelo de la interfaz gráfica de usuario
Figura 3. Modelo de la interfaz gráfica de usuario.

7. Modelo de Pruebas Unitarias

En el diagrama UML presentando en la Figura 4 se modelan las clases de pruebas del modelo del mundo del problema. (Original en "Pruebas" (2015)).
Modelo de pruebas unitarias
Figura 4. Modelo de pruebas unitarias.

8. Repositorio: Exploración de Código Fuente C#

En el siguiente enlace de repositorio en GitHub se puede explorar todo el código fuente de la aplicación; el cual comprende:
  • Modelo del mundo del problema
  • Controles de la interfaz gráfica de usuario
  • Archivos de configuración
  • Recursos (imágenes, íconos, cadenas de texto, entre otros)
  • Clases de pruebas unitarias del comportamiento y estado de las entidades del modelo del mundo del problema.

9. Recursos

9.1 Java

Recursos del proyecto en su versión original:

9.2.1 Solución y proyectos

Enlaces de descarga de archivos ZIP con la solución y los proyectos integrales de la aplicación en Visual Studio:

9.2.2 Documentación código fuente

Archivo CHM con la documentación del código fuente C#:

9.2.3 Aplicación en ejecución

9.2.3.1 Capturas de pantalla
Club Social en C#
Figura 6. Club Social en C#.
9.2.3.2 Demostración

10. Cambios

Cambios sobresalientes en la solución respecto al proyecto original:

Clase Factura:
  • El tipo de dato para el campo valor pasa de double a decimal (apto para representar valores que requieren precisión).
  • Se remueven los métodos darConcepto, darValor y darNombre y se usan propiedades para obtener el valor de los campos correspondientes.
Clase Socio:
  • En lugar de los métodos darCedula, darNombre, darFacturas y darAutorizados, se crearon propiedades de solo lectura.
  • El método AfiliarSocio recibe, ahora, un parámetro de tipo Socio.
Nuevo:
  • Agregada la clase AutoreferenciaSocioException que hereda de System.Exception. Útil para manejar la excepción cuando el autorizado es el mismo socio.
  • Agregada la clase SocioExisteException que hereda de System.Exception. Clase útil para la gestión de excepciones relacionadas con la existencia de un socio.
  • Agregada la clase AutorizadoExisteException que hereda de System.Exception. Clase útil para la gestión de excepciones relacionadas con la existe de autorizado.
  • Agregada enumeración Operaciones para determinar el tipo de operación que debe asociar en la búsqueda de socio desde un control personalizado.

11. Conclusiones

A través de esta aplicación se ha adquirido conocimiento práctico acerca de una de las estructuras de datos integrados en .NET Framework: ArrayList.Estructura útil para el almacenamiento y manipulación de objetos. Se realizaron cambios en el proyecto C# con el propósito de aprovechar sus componentes sintácticos de descripción de entidades de un modelo: propiedades, enumeraciones; en especial. En la próxima publicación se desarrollará una aplicación controlar un brazo mecánico de una bodega.

12. Literatura & Enlaces

Universidad de los Andes - Colombia (2015, diciembre 7). Recuperado desde: http://www.uniandes.edu.co/.
Cupi2 (2015, diciembre 7). Recuperado desde: http://cupi2.uniandes.edu.co/sitio/.
APO1 (2015, diciembre 7). Recuperado desde: http://cupi2.uniandes.edu.co/sitio/index.php/cursos/apo1.
Enunciado (2015, diciembre 7). Recuperado desde: http://cupi2.uniandes.edu.co/sitio/index.php/cursos/apo1/nivel-4/club.
Modelo Conceptual (2015, diciembre 7). Recuperado desde: http://cupi2.uniandes.edu.co/sitio/index.php/cursos/apo1/nivel-4/club/modeloconceptual-n4club.
Interfaz (2015, diciembre 7). Recuperado desde: http://cupi2.uniandes.edu.co/sitio/index.php/cursos/apo1/nivel-4/club/interfaz-n4club.
Pruebas (2015, diciembre 7). Recuperado desde: http://cupi2.uniandes.edu.co/sitio/index.php/cursos/apo1/nivel-4/club/pruebas-n4club.


V

viernes, 4 de diciembre de 2015

Receta T-SQL No. 3-6: Forzar la Unicidad de una Columna con NULL

Índice

1. Introducción
2. Palabras Clave
3. Problmea
4. Solución
5. Discusión de la Solución
5.1 Índice único -unique index-
6. Práctica: Código T-SQL
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

Esta nueva receta Transact-SQL enseña a utilizar un mecanismo para asegurar la unicidad de una columna que admita NULL. Se demuestra en primera instancia que un índice único -unique index- evita duplicados tanto de valores concretos para un tipo de dato específico como de valores desconocidos NULL. Esto es posible a través de la creación de un índice único nonclustered, el cual permite la unicidad de valores concretos y multiplicidad o asignación de NULL a múltiples registros para el mismo campo.

2. Palabras Clave

  • Índice
  • Índice único
  • Multiplicidad
  • Unicidad
  • Nonclustered index

3. Problema

Permitir que una columna de una tabla pueda contener valores concretos únicos de un tipo de dato específico. Además que se permitan múltiples valores NULL.

4. Solución

Usar un índice no-agrupado o nonclustered para el campo que debe cumplir el requerimiento de unicidad para valores concretos y multiplicidad para valores no conocidos o NULL.

5. Discusión de la Solución

5.1 Índice único -unique index-

Un índice único (o unique index) es un tipo de índice que garantiza la unicidad o no duplicado de valores para un campo o columna llave ("Create Unique Indexes", 2015). Además, este tipo de índice puede involucrar varias columnas. Por ejemplo se puede crear un índice para un número de teléfono para un requerimiento de negocio que especifique que cada cliente debe tener uno o más números de teléfono distintos a cualquiera de los demás clientes.

Lo anterior también aplica para una combinación de columnas como PrimerNombre, SegundoNombre, Apellidos. En el índice único no puede existir más de un registro que tenga la misma combinación de primer nombre, segundo nombre y apellidos.

Otro propósito interesante de este clase de índice es garantizar la integridad de datos sobre la o las columnas que forman parte del índice. Además, como se manifiesta en "Create Unique Indexes" (2015), un índice único facilita información extra para el optimizador de consultas de SQL Server.

6. Práctica: Código T-SQL

Creación de tabla Producto:

CREATE TABLE Producto
(
IdProducto INT NOT NULL
CONSTRAINT PK_Producto PRIMARY KEY CLUSTERED,
NombreProducto NVARCHAR(50) NOT NULL,
NombreClave NVARCHAR(50)
);

A coninuación se ha de crear el índice único nonclustered:

CREATE UNIQUE INDEX UX_Producto_NombreClave ON Producto(NombreClave);

A partir de aquí se prueba con la inserción de registros en la misma tabla:

INSERT INTO Producto (IdProducto, NombreProducto, NombreClave)
VALUES (1, 'Producto #1', 'Adven');

INSERT INTO Producto (IdProducto, NombreProducto, NombreClave)
VALUES (2, 'Producto #2', 'Fomich');

INSERT INTO Producto (IdProducto, NombreProducto, NombreClave)
VALUES (3, 'Producto #3', NULL);

INSERT INTO Producto (IdProducto, NombreProducto, NombreClave)
VALUES (4, 'Producto #4', NULL);

Al intentar ejecutar esas sentencias de inserción de registros se genera un mensaje de error para la última:

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)
Msg 2601, Level 14, State 1, Line ...
Cannot insert duplicate key row in object 'dbo.Producto' with unique index 'UX_Producto_NombreClave'. The duplicate key value is ().

The statement has been terminated.

La causa del error se debe esencialmente a que el tipo de índice creado no permite la inserción de múltiples valores no conocidos NULL.

Para resolver esta limitación, SQL Server cuenta con la función de creación de índices filtrados; esto es, la especificación de una condición para un subconjunto determinados valores del dominio de un tipo de dato (Brimhall et al, 2015).

Proceso de la solución:

Eliminación del índice creado anteriormente:

DROP INDEX Producto.UX_Producto_NombreClave;

Creación del nuevo índice único filtrado:

CREATE UNIQUE INDEX UX_Producto_NombreClave ON Producto(NombreClave) WHERE NombreClave IS NOT NULL;

Nótese la especificación del filtro a través de WHERE NombreClave IS NOT NULL.: con esto se está indiciado que el campo NombreClave solo debe conservar la unicidad sobre valores distintos a NULL.

A continuación se han de insertar otros registros

INSERT INTO Producto (IdProducto, NombreProducto, NombreClave)
VALUES (4, 'Producto #4', NULL);

INSERT INTO Producto (IdProducto, NombreProducto, NombreClave)
VALUES (5, 'Producto #5', NULL);

Ahora ya es permitido la inserción de múltiples valores NULL:

(1 row(s) affected)

(1 row(s) affected)

Contenido de la tabla Producto:
Contenido de la tabla Producto
Figura 1. Contenido de la tabla Producto.

7. Conclusiones

Se ha demostrado cómo a través de un índice único filtrado es posible establecer una condición sobre la unicidad para los valores de una columna o varias columnas que pertenezcan al índice. En otras palabras: este tipo de operación es de inmensa utilidad para el programador de bases de datos, pues le permitirá aplicar una condición de unicidad para un subconjunto de datos que pertenezcan a un índice único. La próxima receta T-SQL explica cómo forzar la integridad referencial sobre columnas que permiten valores NULL.

8. Literatura & Enlaces

Brimhall, J., Dye, D., Gennick, J., Roberts, A., Sheffield, W. (2012). SQL Server 2012 T-SQL Recipes - A Problem-Solucion Approach. United States: Apress.
Create Unique Indexes (2015, diciembre 4). Recuperado desde: https://msdn.microsoft.com/en-us/library/ms187019.aspx.
Create Nonclustered Indexes (2015, diciembre 4). Recuperado desde: https://msdn.microsoft.com/en-us/library/ms189280.aspx.


V

jueves, 3 de diciembre de 2015

Receta C# No. 6-3: Inserción Rápida de Nodos en un Documento XML

Índice

1. Introducción
2. Palabras Clave
3. Problema
4. Solución
5. Discusión de la Solución
5.1 Clase ayudante AyudanteXml
5.2 Clonación de un nodo
6. Práctica: Código C#
7. Conclusiones
8. Literatura & Enlaces

1. Introducción

Esta nueva receta C# enseña cómo el programador puede insertar nodos en un documento XML de forma más ágil. En la receta anterior se demostró cómo insertar un nodo usando los métodos directos que provee la clase XmlDocument; en esta oportunidad se muestra a través de una clase ayudante cómo realizar el mismo proceso escribiendo menos código sin dejar a un lado su legibilidad. Además, en breve, se demuestra cómo a través del mecanismo de clonación se puede efectuar una inserción rápida con un número inferior de líneas de código respecto al enfoque de la receta C# No. 6.2.

2. Palabras Clave

  • Atributo
  • Clase ayudante
  • Clonación
  • Documento XML
  • Elemento
  • Nodo
  • XML

3. Problema

Se requiere un enfoque programático más ágil para la inserción de nodos en un documento XML.

4. Solución

La solución consiste en la creación de una clase ayudante que contiene los métodos de agregación de un elemento y un atributo. (Una solución alternativa consiste en la clonación de un nodo existe, alterar sus valores, y agregarlo al documento XML usando los étodos de la clase XmlDocument).

5. Discusión de la Solución

5.1 Clase ayudante AyudanteHelper

En la receta Receta C# No. 6-2: Inserción de Nodos en un Documento XML se mostró cómo insertar elementos -nodos y atributos- en un documento XML usando dos de los métodos disponibles en la clase XmlDocument ("XmlDocument Class", 2015) -CreateElement y CreateAttribute-. A pesar de la abstracción que soporta el diseño de la clase XmlDocument para estas tareas, se puede optar aún por la escritura de una clase ayudante que simplifique los procesos de inserción de nodos y atributos de forma más ágil y sencilla.

Continuando, la clase AyudanteHelper que se diseña en la sección de práctica cuenta con métodos de alto nivel para soportar el requerimiento:
  • InsertarElemento y 
  • InsertarAtributo
Esta clase será usada por la clase cliente InsercionAgilNodos.

5.2 Clonación de un nodo

La clase XmlNode ("XmlNode Class", 2015) cuenta con el método CloneNode ("XmlNode.CloneNode Method", 2015) para crear una copia de un nodo. El parámetro de este método permite especificar si se copia el contenido anidado o no; para ello es necesario especificar true o false como argumento:

// Creación de un nuevo elemento a partir de uno existente:
producto = producto.CloneNode(true);

// Modificación de los valores del nodo recién clonado:
producto.Attributes[0].Value = "10002";
producto.ChildNodes[0].ChildNodes[0].Value = "Cappuccino";
producto.ChildNodes[1].ChildNodes[0].Value = "9500";

// Agrega el nuevo elemento:
productos.AppendChild(producto);

6. Práctica: Código C#

En primer lugar se escribe la clase AyudanteXml:

En las líneas 9-26 se especifica el método static AgregarElemento con los parámetros:
  • nodoPadre: referencia al nodo padre sobre el que se creará/agregará el nuevo nodo.
  • nombreEtiqueta: nombre para el nuevo nodo.
  • contenido: contenido textual para un nodo anidado al recién creado. (Opcional).
Más adelante -líneas 29-38-, se crea el método static AgregarAtributo para agregar un nuevo atributo al documento XML. Estos son sus parámetros:
  • nodoPadre: referencia al nodo padre sobre el que se creará el nuevo atributo.
  • nombreAtributo: nombre para el nuevo atributo.
  • contenido: contenido textual para el atributo recién creado.
Compilación:

csc /t:library AyudanteXml.cs

Las líneas de interés de este archivo son:
  • Líneas 22-25: crea un primer elemento y añade otros nodos y atributos usando los métodos AyudanteXml.AgregarElemento y AyudanteXml.AgregarAtributo. Estos operaciones se realizan para crear el producto con ID 10001.
  • Líneas 27-30: de manera análoga al caso anterior, estas líneas crean un producto con ID 10002.
Compilación: 

csc /t:exe /r:AyudanteXml.dll \InsercionAgilNodos.cs

Ejecución assembly:

.\InsercionAgilNodos.exe
Ejecución assembly InsercionAgilNodos.exe
Figura 1. Ejecución assembly InsercionAgilNodos.exe.

7. Conclusiones

Se comprendió el proceso de creación de una clase ayudante para agilizar el proceso de agregación de nodos y atributos a un documento XML. Es notable la diferencia respecto a la receta C# anterior: en este caso solo se requirió invocar los métodos de la clase ayudante en cuestión para especificar datos del nuevo elemento/atributo a crear en el documento XML. En la próxima receta C# se demostrará cómo buscar elementos en un documento XML a través de su nombre.

8. Literatura & Enlaces

Jones, A., Freeman (2010). Visual C# 2010 Recipes: A Problem-Solution Approach. United States: Apress.
Receta C# No. 6-2: Inserción de Nodos en un Documento XML (2015, diciembre 3). Recuperado desde: http://ortizol.blogspot.com/2015/11/receta-csharp-no-6-2-insercion-de-nodos-en-un-documento-xml.html.
XmlDocument Class (System.Xml) (2015, diciembre 29). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.xml.xmldocument(v=vs.110).aspx.
XmlNode Class (System.Xml) (2015, diciembre 29). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.xml.xmlnode(v=vs.110).aspx.
XmlNode.CloneNode Method (Boolean) (System.Xml) (2015, diciembre 3). Recuperado desde: https://msdn.microsoft.com/en-us/library/system.xml.xmlnode.clonenode(v=vs.110).aspx.


V