Está en la página 1de 34

Análisis y diseño - Parte III ADOO - Lic. Morales Modelo conceptual

Un modelo conceptual explica los conceptos más significativos en un dominio del problema, identificando los atributos y las asociaciones, y es la herramienta más importante del análisis orientado a objetos. Los casos de uso son una importante herramienta para el análisis de requerimientos, pero realmente no están orientados a objetos. Un modelo conceptual representa cosas del mundo real, no componentes del software. En UML se representa mediante un grupo de diagramas de estructura estática donde no se define ninguna operación. En estos diagramas se muestran conceptos (objetos), asociaciones entre conceptos (relaciones) y atributos de conceptos (atributos). La siguiente figura muestra un modelo conceptual parcial del dominio de la tienda y las ventas.

Análisis y diseño - Parte III ADOO - Lic. Morales Modelo conceptual Un modelo conceptual explica

Un modelo conceptual es una descripción del dominio de un problema real, no es una descripción del diseño del software. Debido a esto, no es conveniente aquí incluir elementos como ventanas o bases de datos. En el dominio real de comprar productos en una tienda usando una terminal de punto de venta (TPDV), intervienen tres conceptos principales: tienda, TPDV y una venta. Por lo general es mejor exagerar un poco y especificar un modelo conceptual con muchos conceptos. Esto debido a que es frecuente omitir conceptos durante el análisis, y al descubrirlos más tarde, es más difícil incorporarlos. La siguiente lista muestra un conjunto de conceptos idóneos para ser incluidos en el modelo conceptual.

Categoría del concepto

Ejemplos

Objetos físicos o tangibles

TDPV, Dado

Especificaciones, diseño o descripciones de cosas

EspecicacióndeProducto, ReglasdeJuego

Lugares

Tienda, MesadeJuego

Transacciones

Venta, Pago, Reservacion, Apuesta

Línea o renglón de un elemento de transacciones

VentasLineadeProducto

Rol de las personas

Cajero, Gerente, Jugador

 

Contenedores de otras cosas

 

Tienda, Cesto, Biblioteca

 

Cosas dentro de un contenedor

 

Producto, Libro

 

Otros sistemas de cómputo o electromecánicos externos al sistema

SistemaAutorizacionTarjetasdeCredito

Conceptos de nombres abstractos

 

Hambre, Suerte

 

Organizaciones

DepartamentodeVentas, LineaAerea

 
 

Venta,

Robo,

Junta,

Vuelo,

Accidente,

Eventos

RodarDados

 

Procesos (A menudo no están representados como conceptos, pero pueden estarlo)

VentaUnProducto, ReservacionAsiento

 

PoliticadeReembolso,

 

Reglas y políticas

PoliticadeCancelaciones

Catálogos

CatalogodeProductos, CatalogodeLibros

Registros de finanzas, asuntos legales

de trabajo,

de contratos, de

Recibo, Mayor, ContratodeEmpleo

 

Instrumentos y servicios financieros

 

LineadeCredito, Existencia

 

Manuales y libros

ManualdePersonal, ManualdeReparaciones

Otra forma simple de obtener conceptos, es identificarlos de un análisis semántico de las descripciones textuales referentes al dominio del problema. Para hacer esto, los casos de uso expandidos proveen una buena fuente de conceptos. Por ejemplo, el caso de uso Comprar productos:

Acción de los actores

Respuesta del sistema

1. Este caso de uso comienza cuando un Cliente llega a una caja de TPV con los productos que desea comprar.

 

2. El Cajero registra el código de barras de

3. Determina el precio del producto

y

a

la

cada producto. Si hay más de un producto, el Cajero puede introducir también la cantidad.

transacción de venta le agrega la información sobre el producto. Se muestra la descripción y el precio del producto actual.

A partir de la lista de categorías de conceptos podemos generar un conjunto de conceptos para nuestro problema del punto de venta:

TPV

EspecificaciondeProducto

Producto

VentasLineadeProductos

Tienda

Cajero

Venta

Cliente

Pago

Gerente

CatalogodeProductos

¿Se debería incluir la boleta que imprime el punto de venta? Esta boleta es un informe del sistema, y dado que toda su información proviene de otros objetos, no es necesario incluirlo. Sin embargo, es posible que en una etapa posterior (por ejemplo cuando se implemente devolver productos) se justifique su inclusión. Por tanto, el modelo conceptual inicial del sistema de punto de venta (sin incluir atributos ni asociaciones) sería:

¿Se debería incluir la boleta que imprime el punto de venta? Esta boleta es un informe

Falta ahora agregar los atributos relevantes de cada concepto, y las asociaciones. Atributos Un atributo es un valor lógico de un dato de un objeto. Es preferible que los atributos sean simples. Entre los tipos de atributos más comunes se encuentran: booleanos (o lógicos), fechas, números, texto y horas. Algunos tipos comunes son: dirección, color, teléfono, RUT, código de barras, código postal. Los atributos no deberían usarse para relacionar conceptos en el modelo conceptual, solamente para describir estos conceptos. Una de las violaciones más comunes a esta regla consiste en agregar atributos como llaves foráneas. Por ejemplo:

¿Se debería incluir la boleta que imprime el punto de venta? Esta boleta es un informe

Uno de los errores más frecuentes al crear modelos conceptuales, es representar algo como un atributo, cuando debería haber sido un concepto aparte. Una regla práctica para evitar esto es: si en el mundo real no consideramos algún concepto X como número o texto, probablemente X sea un concepto y no un atributo. Por ejemplo, en un dominio de reservaciones en líneas aéreas, ¿el Destino debería ser un atributo de Vuelo u otro concepto?

¿Se debería incluir la boleta que imprime el punto de venta? Esta boleta es un informe

En el mundo real, un aeropuerto de destino no se considera número ni texto, por lo que debería ser un concepto. Sugerencia: En caso de duda, convierta el atributo en un concepto independiente. Otro error común, es incluir atributos con multiplicidad mayor que 1. Por ejemplo:

Asociaciones Una asociación es una relación entre dos conceptos que indica alguna conexión significativa entre ellos.

Asociaciones

Una asociación es una relación entre dos conceptos que indica alguna conexión significativa entre ellos. Las asociaciones útiles a determinar, suelen incluir el conocimiento de una relación que ha de preservarse por algún tiempo: puede tratarse de milisegundos o de años (según el contexto). Por ejemplo, ¿debemos recordar cuales instancias de VentasLineadeProducto están asociadas a Venta? Claro que si, porque de lo contrario no sería posible reconstruir la venta, imprimir la boleta ni calcular el total de la venta. Por otra parte, ¿necesitamos recordar una relación entre una Venta y Gerente? Probablemente no es indispensable ni útil dentro del contexto de nuestros requerimientos. Una asociación se representa como una línea entre conceptos, con el nombre de la asociación. La asociación es intrínsecamente bidireccional, es un posible nexo lógico entre los objetos. Este nexo es totalmente abstracto, no es una afirmación sobre las conexiones entre las entidades del software. Los extremos de una asociación pueden contener una expresión de multiplicidad que indica la relación numérica entre las instancias de los conceptos. Opcionalmente se puede poner una flecha que indique la dirección en que debe leerse el nombre de la asociación (no indica nada más, es sólo una ayuda para leer el diagrama).

Asociaciones Una asociación es una relación entre dos conceptos que indica alguna conexión significativa entre ellos.

Para identificar las asociaciones más comunes, la siguiente lista es de gran ayuda.

Categoría de la asociación

Ejemplos

A es una parte física de B

Caja-TPDV

A es una parte lógica de B

VentasLíneadeProducto-Venta

A está físicamente contenido en B

TPDV-Tienda, Producto-Estante

A está contenido lógicamente en B

DescripcióndeProducto-

Catálogo

A es una descripción de B

DescripcióndeProducto-

Producto

A es un elemento de línea (o renglón) en una transacción o reporte B

VentasLíneadeProducto-Venta

A se conoce/introduce/registra/presenta/captura en B

Venta-TPDV

A es miembro de B

Cajero-Tienda

A es una unidad organizacional de B

Departamento-Tienda

A usa o dirige a B

Cajero-TPDV

A se comunica con B

Cliente-Cajero

A se relaciona con una transacción B

Pago-Venta

A es una transacción relacionada con otra transacción B

Pago-Venta

A es propiedad de B

TPDV-Tienda

Las asociaciones más importantes son las siguientes:

· A es una parte física o lógica de B · A está física o lógicamente contenido en B · A está registrado en B Las asociaciones son importantes, pero no se debe dedicar tiempo excesivo a ellas. Es más importante identificar los conceptos que las asociaciones. Muchas asociaciones tienden a confundir el modelo conceptual, en vez de aclararlo. Se pueden incorporar las que se indican en los casos de uso, y las que se consideren necesarias para un adecuado entendimiento del problema. La multiplicidad define cuántas instancias de un tipo A pueden asociarse a una instancia del tipo B en determinado momento. Las expresiones de multiplicidad son las siguientes:

*

cero o más, muchos

1

*

uno o más

1

40

de uno a cuarenta

5

exactamente cinco

2,4,6

exactamente dos, cuatro o seis

Por ejemplo:

A es miembro de B Cajero-Tienda A es una unidad organizacional de B Departamento-Tienda A usa

Los nombres de las asociaciones deben ser lo más claros posibles, y deben permitir leer y entender fácilmente las relaciones entre conceptos. Por ejemplo:

A es miembro de B Cajero-Tienda A es una unidad organizacional de B Departamento-Tienda A usa

En síntesis, para construir un modelo conceptual se deben aplicar los siguientes pasos:

  • 1. Liste los conceptos idóneos usando la lista de categorías de conceptos.

  • 2. Dibújelos en un modelo conceptual.

  • 3. Incorpore las asociaciones necesarias para registrar las relaciones más importantes (las que se deben recordar).

  • 4. Agregue los atributos necesarios para cumplir con las necesidades de información.

El modelo conceptual de la siguiente figura muestra un conjunto de conceptos, asociaciones y atributos idóneos para la aplicación de punto de venta.

En síntesis, para construir un modelo conceptual se deben aplicar los siguientes pasos: 1. Liste los

El modelo conceptual es una herramienta de comunicación, con la cual se intenta comprender los conceptos importantes y sus relaciones. Es también útil para transmitir este conocimiento a otros.

Paquetes: Organización de los elementos

Veamos el caso de uso extendido del Pago con tarjeta de crédito.

Acción de los actores

Respuesta del sistema

1. Este caso de uso comienza cuando un Cliente decide pagar con tarjeta de crédito, una vez que le han comunicado el total de la venta.

 

2. El Cliente entrega su tarjeta de

  • 3. Genera una Solicitud de pago con tarjeta de crédito y la

crédito al Cajero, quien la pasa por un lector de tarjetas para efectuar el pago con tarjeta de crédito.

envía a un Servicio externo de autorización de crédito, a través de un modem conectado al TPV. Requiere que se registren los datos de la compra, se transmitan, y se espera por

el registro de respuesta.

 
  • 4. Recibe una respuesta aprobando el crédito por parte del

Servicio de autorización.

 
  • 5. Registra en el sistema Cuentas por cobrar el pago con la

tarjeta de crédito y la respuesta aprobando la transacción. (El Servicio externo de autorización le debe dinero a la tienda, y por eso Cuentas por Cobrar le debe dar seguimiento).

 
  • 6. Muestra el mensaje de autorización del crédito.

Falta considerar el caso en que la tarjeta se reprueba. El caso de uso para pago con cheque es similar.

Después de analizar todos los casos de uso extendidos (análisis semántico), y revisar la lista de posibles candidatos a conceptos, se obtiene la versión preliminar del modelo conceptual.

Paquetes: Organización de los elementos Veamos el caso de uso extendido del Pago con tarjeta de

Cuando el número de elementos del modelo conceptual empieza a ser grande, se hace necesario buscar una forma de organizarlos, y para esto usaremos paquetes. Un paquete UML se muestra gráficamente como una carpeta etiquetada. En su interior se pueden incluir los paquetes subordinados. Ejemplo:

Cuando el número de elementos del modelo conceptual empieza a ser grande, se hace necesario buscar

Un elemento es propiedad del paquete en el cual está definido, pero puede referenciarse en otros paquetes. En este caso, para referenciar el nombre de ruta se usa el nombre del paquete y luego el nombre del elemento, de la siguiente forma: NombrePaquete::NombreElemento. Ejemplo:

Cuando el número de elementos del modelo conceptual empieza a ser grande, se hace necesario buscar

Si un elemento de un modelo depende de otro, esta dependencia puede mostrarse a través de una relación de subordinación. Ejemplo:

Cuando el número de elementos del modelo conceptual empieza a ser grande, se hace necesario buscar

Para dividir el modelo conceptual en paquetes, se deben reunir los elementos que:

  • - Se encuentren en la misma área o tema (estrechamente relacionados).

  • - Se encuentren en la misma jerarquía de tipos.

  • - Participen en los mismos casos de uso.

Es conveniente crear un paquete llamado Conceptos del dominio, para agrupar todos los elementos del modelo conceptual. Los conceptos comunes compartidos por la mayoría de paquetes, se pueden agrupar en un paquete llamado Elementos básicos. De esta forma, el modelo conceptual del Sistema de TPV podría organizarse de la siguiente manera:

Es conveniente crear un paquete llamado Conceptos del dominio , para agrupar todos los elementos del
Es conveniente crear un paquete llamado Conceptos del dominio , para agrupar todos los elementos del
Es conveniente crear un paquete llamado Conceptos del dominio , para agrupar todos los elementos del
Es conveniente crear un paquete llamado Conceptos del dominio , para agrupar todos los elementos del
Patrones Los patrones de software describen un problema que ocurre repetidas veces en algún contexto determinado
Patrones Los patrones de software describen un problema que ocurre repetidas veces en algún contexto determinado

Patrones Los patrones de software describen un problema que ocurre repetidas veces en algún contexto determinado del proceso de desarrollo de software, y entregan una buena solución ya probada. Esto ayuda a diseñar correctamente en menos tiempo, ayuda a construir problemas reutilizables y extendibles, y facilita la documentación y la comunicación con otros miembros del equipo de desarrollo. Ejemplo: Delegación (Patrón de Diseño) Este es un patrón fundamental de tipo estructural. Indica cuándo no usar herencia. La delegación es una forma de extender y reutilizar la funcionalidad de una clase, escribiendo una clase adicional con funcionalidad extra que usa instancias de la clase original para proveer su propia funcionalidad. La delegación es una forma de extender el comportamiento de una clase mediante llamadas a métodos de otra clase, más que heredando de ella. La delegación es más apropiada que la herencia en muchas situaciones. Por ejemplo, la herencia es útil para modelar relaciones de tipo es-un o es-una, ya que

estos tipos de relaciones son de naturaleza estática. Sin embargo, relaciones de tipo es-un-rol- ejecutado-por son mal modeladas con herencia. En este tipo de relaciones, instancias de una clase pueden jugar múltiples roles. Por ejemplo, supongamos que tenemos el caso de una universidad donde se tienen tres tipos de roles:

estudiantes, académicos y funcionarios. Es posible representar esta situación mediante una clase llamada Persona (o Personal-universitario) que tiene las subclases correspondientes a cada uno de los roles.

estos tipos de relaciones son de naturaleza estática. Sin embargo, relaciones de tipo es-un-rol- ejecutado-por son

El problema con este diagrama, es que una misma persona puede jugar más de un rol al mismo tiempo. Alguien podría ser funcionario y a la vez estar estudiando una carrera. Del mismo modo, alguien podría ser académico y estar ocupando un puesto administrativo. Para modelar adecuadamente esta situación, se necesitarían 7 subclases de Persona: Estudiante, Académico, Funcionario, AcadémicoyEstudiante, FuncionarioyEstudiante, AcadémicoyFuncionario, EstudianteyAcadémicoyFuncionario. En este tipo de situaciones, el número de subclases que se necesitan, se incrementa exponencialmente con el número de roles (por ejemplo, se necesitarían 63 subclases para modelar 6 roles). Pero el problema más serio se presenta cuando la misma persona puede jugar combinaciones distintas de roles en distintos tiempos. La herencia es una relación estática que no cambia con el tiempo. Para resolver esta situación, es posible representar personas en diferentes roles usando delegación, como se muestra en la siguiente figura.

estos tipos de relaciones son de naturaleza estática. Sin embargo, relaciones de tipo es-un-rol- ejecutado-por son

La solución general propuesta en este patrón es: incorporar la funcionalidad de la clase original usando una instancia de la clase original y llamando sus métodos.

estos tipos de relaciones son de naturaleza estática. Sin embargo, relaciones de tipo es-un-rol- ejecutado-por son

En el diagrama anterior, se muestra una clase

con rol

Delegador que usa una clase

con

el

rol

Delegado. Aquí se usa la delegación para reutilizar y extender el comportamiento de la clase.

Patrones de Análisis Los patrones de análisis son un conjunto de clases y relaciones entre ellas, que tienen algún sentido en el contexto de una aplicación. Representan una estructura que puede ser válida para otras aplicaciones.

Ejemplo 1: Casa reparadora de computadores (Eduardo Fernández)

Se tiene una casa reparadora de computadores (casa matriz) que coordina una cadena de casas reparadoras. Los clientes traen las computadoras dañadas a alguna de estas casas, y un técnico realiza una estimación del daño y del costo de la reparación. Si el cliente está de acuerdo con la estimación, se asigna un técnico. Todos los eventos que ocurren durante la reparación son guardados en una especie de "expediente" del equipo (para futuras reparaciones). El modelo conceptual de este problema podría ser como el siguiente:

Ejemplo 1: Casa reparadora de computadores (Eduardo Fernández) Se tiene una casa reparadora de computadores (casa

El diagrama de modelo de estados podría ser el siguiente:

Ejemplo 1: Casa reparadora de computadores (Eduardo Fernández) Se tiene una casa reparadora de computadores (casa

Ejemplo 2: Hospital (Eduardo Fernández)

En un hospital se atienden personas. Por lo general, un hospital forma parte de una cadena de hospitales. Una persona trae al paciente al hospital. Los médicos hacen un diagnóstico de cada paciente que ingresa. Si el paciente (o la persona que lo trae) está de acuerdo, se le asigna un médico para que lo trate. Los eventos durante la estadía del paciente se almacenan en su expediente.

El modelo conceptual de este problema podría ser como el siguiente:

El diagrama de modelo de estados podría ser el siguiente: Diagramas de secuencia El diagrama de

El diagrama de modelo de estados podría ser el siguiente:

El diagrama de modelo de estados podría ser el siguiente: Diagramas de secuencia El diagrama de

Diagramas de secuencia El diagrama de secuencia de un sistema muestra gráficamente los eventos que originan los actores y que impactan al sistema. La creación de los diagramas de secuencia forma parte de la investigación para conocer el sistema, por lo que es parte del análisis del mismo. La creación de los diagramas de secuencia depende de la formulación de los casos de uso. Los casos de uso indican cómo los actores interactúan con el sistema. Durante la operación del sistema, los actores generan eventos, solicitando alguna operación a cambio. Por ejemplo, cuando un cajero ingresa un código de barras de un artículo, está pidiendo al sistema de TPV que registre esa compra. Con este evento se inicia una operación en el sistema. Antes de iniciar el diseño lógico de la aplicación de software, es necesario investigar y definir su comportamiento como una "caja negra". Vamos a estudiar el comportamiento del sistema, desde la perspectiva de qué es lo que hace, y no de cómo lo hace. Def.: El diagrama de secuencia de un sistema es una representación que muestra, en determinado escenario de un caso de uso, los eventos generados por actores externos, su orden y los eventos internos del sistema. Lo importante aquí son los eventos originados por los actores, que trascienden las fronteras del sistema. Los sistemas mismos son cajas negras. Recordemos el caso de uso Comprar productos:

Caso de uso: Comprar productos Actores: Cliente, cajero Tipo: Primario

Descripción: Un Cliente llega a la caja registradora con los artículos que va a comprar. El Cajero registra el código de cada producto. Si hay más de una unidad de un producto, puede registrar la cantidad. El sistema determina el precio del producto, y agrega la información a la transacción actual de venta. Se muestra la descripción del producto y el precio. Esto se repite para todos los artículos. Al final, el cajero cobra el importe. Al terminar la operación, el Cliente se marcha con los productos.

El siguiente diagrama de secuencia describe el caso de uso Comprar productos. En estos diagramas el tiempo avanza hacia abajo, y el orden de los eventos debería seguir el orden indicado en el caso de uso correspondiente.

Comprar productos Cliente, cajero Primario Un Cliente llega a la caja registradora con los artículos

En el diagrama anterior, se indica que el Cajero es el único actor, y que se generan los eventos del sistema: pasarProducto, terminarVenta y efectuarPago. Def.: Un evento es un hecho externo de entrada, que un actor produce en el sistema. Cada evento da origen a una operación del sistema como respuesta. En el ejemplo anterior, se tienen tres eventos:

pasarProducto, terminarVenta y efectuarPago. Los eventos y las operaciones del sistema tienen el mismo nombre, por ejemplo, cuando el cajero genera un evento de pasarProducto, causa que en el sistema se ejecute la operación pasarProducto. Una vez que se identifican los eventos, se "registran" en la entidad que corresponda, como operaciones. Por ejemplo:

Comprar productos Cliente, cajero Primario Un Cliente llega a la caja registradora con los artículos

En esta notación UML los parámetros son opcionales. Es conveniente que los nombres de los eventos comiencen con un verbo, pues están orientados a comandos del sistema. Dado que los eventos son hechos externos de entrada, es necesario definir la frontera del sistema. Por lo general la frontera será el sistema de software (puede también incluir el hardware). Es en este contexto que decimos que un evento del sistema es un hecho externo que estimula directamente al software. Observe que la representación del tipo Sistema es muy diferente a lo que se expresó en el modelo conceptual. Los elementos del modelo conceptual representan conceptos del mundo real, en cambio, el tipo Sistema es un concepto artificial. Además muestra las operaciones que realiza. Esto se debe a que,

a diferencia del modelo conceptual, que representa información estática, estamos ahora describiendo el comportamiento del sistema, que es información dinámica. En el caso de uso anterior (Comprar productos) lo primero que se hace es determinar los actores que interactúan directamente con el sistema de software. En este caso, el cliente interactúa con el cajero, pero no directamente con el software TPV. Es el cajero quien interactúa con el software. Por tanto, el cliente no genera eventos en el sistema. A veces es conveniente mostrar algunos fragmentos del texto del caso de uso dentro del diagrama de secuencia. Por ejemplo:

a diferencia del modelo conceptual, que representa información estática, estamos ahora describiendo el comportamiento del sistema,

Contratos Antes de construir el diseño lógico que dice cómo funcionará la aplicación de software, es conveniente definir su comportamiento como una caja negra. El comportamiento del sistema es una descripción de lo que hace, y no de cómo lo hace. Los contratos son documentos útiles para describir estos comportamientos, a partir de las operaciones del sistema o eventos. Un contrato ve las relaciones entre los proveedores y sus clientes como un acuerdo formal, que expresa los derechos y obligaciones de cada parte. La correctitud de un programa es algo relativo, y depende en gran parte de la especificación. Una fórmula de corrección (o tripleta de Hoare) es una expresión de la forma:

(1)

{P} A {Q}

La fórmula de corrección anterior se lee: una ejecución de A que comience en un estado en el que se cumpla P terminará en un estado en el que se cumple Q. Aquí A denota una operación. P y Q se denominan aserciones, de las cuales P será la pre-condición y Q será la post-condición. Ejemplo:

{x >= 9}

x

:= x + 5

{x >= 13}

En este caso, una post-condición más fuerte sería {x >= 14}. Las condiciones más fuertes acotan más el resultado. Una condición más débil hace lo contrario, por ejemplo: {x >= 10} es una post- condición más débil, pero para nuestros efectos, no es muy útil. La pre-condición establece las propiedades que se tienen que cumplir cada vez que se ejecute el procedimiento. La post-condición establece las propiedades que debe garantizar el procedimiento cuando termine. La propiedad de que un programa satisfaga su especificación, si termina, se conoce como corrección parcial. Si un programa satisface su especificación y termina, se dice que es totalmente correcto (total corrección implica además terminación).

Las aserciones permiten, a quienes desarrollan software, construir programas correctos, y documentar por qué son correctos. Ejemplo: Si una función raíz cuadrada sqrt(int x) que produce un número real como resultado, tiene como pre-condición que el valor de x tiene que ser mayor que cero, el programador puede escribir el algoritmo sin preocuparse del caso en que x sea negativo. El método de diseño por contrato va más allá. Escribir esta rutina de la forma:

if x < 0 then // Tratar el error de alguna manera else // Proceder con el cálculo de la raíz cuadrada end

no sólo es innecesario, sino inaceptable! Def.: Principio de no redundancia. Bajo ninguna circunstancia debe, el cuerpo de la rutina, verificar el cumplimiento de la pre-condición de la rutina. Esto último es contrario a lo que proponen la mayoría de libros de texto en ingeniería de software: es mejor comprobar demasiado, que demasiado poco (este último principio es comúnmente llamado programación defensiva). El diseño por contrato invita a identificar las condiciones de consistencia que son necesarias para el funcionamiento correcto de cada cooperación cliente-proveedor (cada contrato) y a especificar, para cada una de estas condiciones, de quién es la responsabilidad de asegurar la misma: del cliente o del proveedor.

Contratos para las operaciones

Para ayudar a explicar lo que una operación (o evento del sistema) se propone hacer, es conveniente

usar contratos. Un contrato de operación del sistema describe los cambios de estado del sistema total cuando se llama a una de sus operaciones. Por ejemplo, para la operación pasarProducto se puede definir el siguiente contrato:

Contrato

Nombre:

pasarProducto(código:número, cantidad:entero)

Responsabilidades: Capturar (registrar) la venta de un producto y agregarla a la venta. Desplegar la descripción y el precio del producto.

Tipo:

Sistema.

Referencias

Funciones del sistema: R1.1, R1.3, R1.9.

cruzadas:

Casos de uso: Comprar productos.

Notas: Utilizar acceso super-rápido a la base de datos. Excepciones: Si el código no es válido, indicar que se cometió un error. Precondiciones: El sistema conoce el código.

Postcondiciones:

· Si se trata de una nueva venta, se crea una Venta (creación de instancia). · Si se trata de una nueva venta, la nueva Venta fue asociada a TPV (asociación formada). · Se creó una instancia de VentasLíneadeProducto (creación de instancia). · Se asoció una instancia de VentasLíneadeProducto a la Venta (asociación formada). · Se asignó cantidad a VentasLíneadeProducto.cantidad (modificación de atributo). · Se asoció una instancia VentasLíneadeProducto a la instancia EspecificacióndeProducto, basado en la correspondencia del código (asociación formada).

Algunas recomendaciones para la elaboración de los contratos:

  • 1. Identificar las operaciones a partir de los diagramas de secuencia.

  • 2. Elaborar un contrato por cada operación.

  • 3. Redactar inicialmente la sección de Responsabilidades. Luego se describe informalmente el propósito de la operación.

  • 4. Se completa la sección de Postcondiciones, describiendo en forma declarativa los cambios de estado de los objetos en el modelo conceptual.

  • 5. Para describir las Postcondiciones utilice las siguiente categorías: creación y eliminación de instancias, modificación de los atributos, asociaciones formadas y canceladas.

Los contratos para terminarVenta, efectuarPago e inicio son los siguientes:

Contrato

Nombre:

terminarVenta( )

Responsabilidades: Registrar que es el final de la captura de los productos de la venta y desplegar el total de la venta.

Tipo:

Sistema.

Referencias

Funciones del sistema: R1.2.

cruzadas:

Casos de uso: Comprar productos.

Notas:

Excepciones:

Si no está realizándose una venta, indicar que se cometió un error.

Precondiciones:

Se está realizando una venta.

Postcondiciones:

· Estableció Venta.estaTerminada en verdadero (modificación de atributo).

Contrato

Nombre:

efectuarPago(monto:número)

Responsabilidades: Registrar el pago, calcular el saldo, imprimir la boleta.

Tipo:

Sistema.

Referencias

Funciones del sistema: R2.1.

cruzadas:

Casos de uso: Comprar productos.

Notas:

Excepciones:

Si la venta no está concluida, indicar que se cometió un error.

Precondiciones:

Postcondiciones:

· Se creó un Pago (creación de instancia). · Se asignó a Pago.montoOfrecido el valor de monto (modificación de atributo). · Se asoció el Pago a la Venta (relación formada). · Se asoció la Venta a la Tienda para agregarla al registro histórico de las ventas terminadas (relación formada).

Contrato

Nombre:

inicio( )

Responsabilidades: Iniciar el sistema.

Tipo:

Sistema.

Referencias

cruzadas:

Notas:

Excepciones:

Precondiciones:

Postcondiciones:

· Se creó una instancia de Tienda, TPV, CatálogodeProductos, y EspecificacióndeProducto (creación de instancias). · Se asoció CatálogodeProductos a EspecificacionesdeProducto (asociación formada). · Se asoció Tienda a CatálogodeProductos (asociación formada). · Se asoció Tienda a TPV (asociación formada). · Se asoció TPV a CatálogodeProductos (asociación formada).

Otros diagramas de secuencia del sistema son los siguientes:

Precondiciones: · Se creó una instancia de Tienda, TPV, CatálogodeProductos, y EspecificacióndeProducto (creación de instancias). ·

Pago con tarjeta de crédito

Precondiciones: · Se creó una instancia de Tienda, TPV, CatálogodeProductos, y EspecificacióndeProducto (creación de instancias). ·

Pago con cheque

Con estos nuevos diagramas de secuencia, se agregan nuevas operaciones del sistema (o eventos):

efectuarPagoTarjeta, respuestaCredito, efectuarPagoCheque, respuestaCheque.

Con estos nuevos eventos, la lista de operaciones del sistema crece:

Con estos nuevos diagramas de secuencia, se agregan nuevas operaciones del sistema (o eventos): efectuarPagoTarjeta, respuestaCredito,

Los nuevos contratos serían los siguientes:

Contrato

Nombre:

efectuarPagoTarjeta(num:número, fechaVencimiento:fecha)

Responsabilidades: Crear y solicitar autorización de un pago con tarjeta de crédito.

Tipo:

Sistema.

Salida:

Una solicitud de pago con tarjeta se envía al servicio de autorización de crédito.

Precondiciones:

Se terminó la venta actual.

Postcondiciones:

· Se creó un pagoTarjeta pgo. · Se asoció el pgo con la Venta actual. · Se creó una tarjetaCrédito tc con tc.numero = tc.Num, tc.fechaVencimiento = fechaVencimiento. · Se asoció tc a pgo. · Se creó una solicitudPagoTarjeta spt. · Se asoció spt a servicioAutorizacionCredito.

Contrato

Nombre:

respuestaCredito(respuesta:respuestaPagoTarjeta)

Responsabilidades: Atender la respuesta del servicio de autorización de crédito. Si la respuesta es positiva, se concluye la venta y se registra el pago en las cuentas por cobrar.

Tipo:

Sistema.

Salida: Si se aprueba la solicitud, la respuesta se envía a cuentas por cobrar. Precondiciones: La solicitud de pago con tarjeta se envió al servicio de autorización de crédito.

Postcondiciones:

Si la respuesta fue positiva:

· Se creó una aprobación respuestaPagoTarjera. · Se asoció aprobación a cuentasPorCobrar. · Se asoció la Venta a la Tienda para incorporarla al registro histórico de ventas terminadas. Si la respuesta fue negativa:

· Se creó una reprobatoria respuestaPagoTarjeta.

Diagramas de estado

Los diagramas de estado describen gráficamente los eventos y los estados de los objetos. Los diagramas de estado son útiles, entre otras cosas, para indicar los eventos del sistema en los casos de

uso.

Un evento es un acontecimiento importante a tomar en cuenta para el sistema. Un estado es la condición de un objeto en un momento determinado: el tiempo que transcurre entre eventos. Una transición es una relación entre dos estados, e indica que, cuando ocurre un evento, el objeto pasa del estado anterior al siguiente. En UML, los estados se representan mediante óvalos. Las transiciones se representan mediante flechas con el nombre del evento respectivo. Se acostumbra poner un estado inicial (círculo negro). Por ejemplo:

Un evento es un acontecimiento importante a tomar en cuenta para el sistema. Un estado es

Un diagrama de estado representa el ciclo de vida de un objeto: los eventos que le ocurren, sus transiciones, y los estados que median entre estos eventos. En particular, es útil hacer diagramas de estado para describir la secuencia permitida de eventos en los casos de uso. Por ejemplo, en el caso de uso comprarProductos no está permitido efectuar pagoTarjeta mientras no haya ocurrido el evento terminarVenta. Un diagrama de estado que describe los eventos globales del sistema y su secuencia en un caso de uso es un diagrama de estado para casos de uso. Por ejemplo, una versión simplificada del diagrama de estados para el caso de uso comprarProductos es el siguiente:

Un evento es un acontecimiento importante a tomar en cuenta para el sistema. Un estado es

Una versión más completa del diagrama anterior se muestra en la siguiente figura:

Una versión más completa del diagrama anterior se muestra en la siguiente figura: El diagrama anterior

El diagrama anterior aun no está completo, pues falta considerar algunos casos excepcionales, como por ejemplo, si al rechazar una tarjeta de crédito o un cheque, el cliente decide pagar usando otro método, por ejemplo pagando en efectivo. Una transición puede tener una protección condicional, o prueba booleana, que permite pasar al siguiente estado solamente si esta protección es válida. Estas protecciones se colocan entre paréntesis debajo de los eventos (ver validación del usuario al descolgar el auricular, en la siguiente figura). También se pueden tener sub-estados anidados.

Una versión más completa del diagrama anterior se muestra en la siguiente figura: El diagrama anterior

Las herramientas usadas en la etapa de análisis (investigación del problema) se pueden resumir en la siguiente tabla.

Herramienta de análisis

Preguntas que responde

Casos de uso

¿Cuáles son los procesos del dominio?

Modelo conceptual

¿Cuáles son los conceptos, los términos?

Diagramas de secuencia

¿Cuáles son los eventos y las operaciones del sistema?

Contratos

¿Qué hacen las operaciones del sistema?

Casos de uso reales Los casos reales de uso representan un diseño concreto de cómo se va a realizar el caso, a partir de una tecnología particular. Por ejemplo, si se necesita una interfaz gráfica de usuario, se deben incluir diagramas de las ventanas requeridas. Los diagramas de ventanas de todos los casos de uso, así como el modelo de navegación de éstas, constituye la versión "en papel" del primer prototipo del sistema. Para la creación de los casos de uso reales, se refinan los casos esenciales creados en la etapa de análisis.

Diagramas de colaboración Los contratos muestran qué hacen las operaciones del sistema, pero no muestran cómo los objetos de software van a cumplir con ellas. Los diagramas de interacción (diagramas de secuencia o diagramas de colaboración) explican gráficamente cómo los objetos interactúan a través de mensajes para realizar las tareas. Antes de definir estos diagramas, hay que generar el modelo conceptual, los contratos de operación y los casos de uso reales (estos últimos se generan a partir de los casos de uso definidos en el análisis).

Los diagramas de colaboración explican gráficamente las interacciones entre las instancias del modelo (objetos). Por ejemplo:

Las herramientas usadas en la etapa de análisis (investigación del problema) se pueden resumir en la

El punto de partida de las interacciones son las poscondiciones de los contratos de operación. El siguiente ejemplo muestra el diagrama de colaboración de la operación efectuarPago.

Las herramientas usadas en la etapa de análisis (investigación del problema) se pueden resumir en la

Los diagramas de interacción constituyen una de las herramientas más importantes para el análisis y diseño orientado a objetos. El tiempo y esfuerzo dedicado a la preparación de éstos, corresponde a un porcentaje considerable de la actividad total del proyecto.

Notación: Para representar gráficamente el hecho de que un mensaje devuelva un valor, se puede hacer de la siguiente manera:

Notación: Un objeto puede enviarse un mensaje a si mismo: También es posible indicar el número

Notación: Un objeto puede enviarse un mensaje a si mismo:

Notación: Un objeto puede enviarse un mensaje a si mismo: También es posible indicar el número

También es posible indicar el número de veces (iteraciones) que un mensaje va a ser enviado. Por ejemplo, el siguiente método:

msg1() { for i := 1 to 10 {

miB.mens2();

miC.mens3();

}

}

puede ser representado mediante el siguiente diagrama:

Notación: Un objeto puede enviarse un mensaje a si mismo: También es posible indicar el número

Notación: El siguiente ejemplo muestra la forma de definir la secuencia de los mensajes dentro de un diagrama de colaboración.

Notación: Un objeto puede enviarse un mensaje a si mismo: También es posible indicar el número

Notación: Es posible definir mensajes condicionales. Para esto, se define la condición entre corchetes, y el mensaje se envía solamente si la condición es verdadera. Por ejemplo:

Notación: Un objeto puede enviarse un mensaje a si mismo: También es posible indicar el número

Notación: Es posible definir trayectorias condicionales mutuamente excluyentes. Por ejemplo:

Notación: Es posible definir trayectorias condicionales mutuamente excluyentes. Por ejemplo: Notación: Un multiobjeto , o conjunto

Notación: Un multiobjeto, o conjunto de instancias (por ejemplo un arreglo en Java), se dibuja en forma de pila. Por ejemplo:

Notación: Es posible definir trayectorias condicionales mutuamente excluyentes. Por ejemplo: Notación: Un multiobjeto , o conjunto

De esta forma, también podemos enviar mensajes a multiobjetos. Por ejemplo:

Notación: Es posible definir trayectorias condicionales mutuamente excluyentes. Por ejemplo: Notación: Un multiobjeto , o conjunto

La siguiente figura muestra cómo enviar mensajes para crear una instancia de un objeto, y agregarla a un multiobjeto.

Notación: Es posible definir trayectorias condicionales mutuamente excluyentes. Por ejemplo: Notación: Un multiobjeto , o conjunto

También es posible enviar mensajes a la clase y no a una instancia, con el fin de llamar a métodos de la clase. Por ejemplo:

Notación: Es posible definir trayectorias condicionales mutuamente excluyentes. Por ejemplo: Notación: Un multiobjeto , o conjunto

Las herramientas utilizadas en las etapas anteriores se pueden resumir en la siguiente tabla:

Herramienta

Preguntas que responde

Requerimientos

¿Cuáles son las necesidades o deseos del producto?

Casos de uso

¿Cuáles son los procesos del dominio?

Modelo conceptual

¿Cuáles son los conceptos, los términos?

Diagramas de secuencia

¿Cuáles son los eventos y las operaciones del sistema?

Contratos

¿Qué hacen las operaciones del sistema?

Diagramas de estado

¿Cuáles son los estados de los objetos en los eventos?

Diagramas de colaboración

¿Cómo hacen los objetos para cumplir con las operaciones?

Un sistema orientado a objetos se compone de objetos que envían mensajes a otros objetos para que lleven a cabo ciertas operaciones. Cada clase de objetos tiene ciertas responsabilidades, que son cumplidas a través de sus métodos, y por la forma en que colabora con las otras clases de objetos. Decisiones poco acertadas sobre la asignación de responsabilidades de cada clase, dan origen a sistemas y componentes frágiles y difíciles de mantener, entender, reutilizar o extender. Veremos algunos patrones que se pueden aplicar durante la elaboración de los diagramas de interacción, al asignar las responsabilidades a los objetos y al diseñar la colaboración entre ellos.

Responsabilidades

Las responsabilidades se relacionan con las obligaciones de un objeto respecto de su comportamiento.

Estas responsabilidades pertenecen, esencialmente, a dos categorías: conocer y hacer. Entre las responsabilidades de un objeto relacionadas con el hacer se encuentran:

· Hacer algo en uno mismo. · Iniciar una acción en otros objetos. · Controlar y coordinar actividades en otros objetos.

Entre las responsabilidades de un objeto relacionadas con el conocer se encuentran:

· Estar enterado de los datos privados encapsulados. · Estar enterado de la existencia de objetos conexos. · Estar enterado de cosas que se pueden derivar o calcular.

Las responsabilidades se asignan a los objetos durante el diseño orientado a objetos. Por ejemplo, podría decirse que una Venta es responsable de imprimirse ella misma (un hacer), o que una Venta tiene la obligación de conocer su fecha (un conocer).

Responsabilidad no es lo mismo que método: los métodos se usan para cumplir con las responsabilidades. Éstas se implementan usando métodos que operen solos o en colaboración con otros métodos y objetos. Así por ejemplo, la clase Venta podría definir uno o varios métodos para imprimir una instancia Venta (por ejemplo el método imprimir). Para hacer esto, Venta puede colaborar con otros objetos, por ejemplo, enviando mensajes a VentasLineadeProducto para que se impriman ellos mismos.

Los diseñadores expertos en orientación a objetos, van formando un amplio repertorio de principios generales que los guían al crear software. Estos principios son llamados patrones, y se codifican en un formato estructurado que describe el problema y su solución. Cada patrón tiene un nombre. Los patrones no se proponen descubrir ni expresar principios nuevos en Ingeniería de Software. Todo lo contrario, intentan codificar el conocimiento y los principios ya existentes: cuanto más generalizados y usados, mejor.

Cinco patrones útiles para la asignación de responsabilidades son: Experto, Creador, Controlador, Bajo acoplamiento y Alta cohesión. A continuación se describen estos patrones.

El patrón Experto [Larman 98] Nombre: Experto.

Problema: ¿Cuál es el principio fundamental en virtud del cual se asignan las responsabilidades en el diseño orientado a objetos? Un modelo de clase puede definir docenas y hasta cientos de clases de software, y una aplicación tal vez requiera el cumplimiento de cientos o miles de responsabilidades. Durante el diseño orientado a objetos, cuando se definen las interacciones entre los objetos, se toman decisiones sobre la asignación de responsabilidades a clases. Si se hace en forma adecuada, los sistemas tienden a ser más fáciles de entender, mantener y ampliar, y se nos presenta la oportunidad de reutilizar los componentes en futuras aplicaciones.

Solución:

Asignar una responsabilidad al experto en información: la clase que cuenta con la información necesaria para cumplir la responsabilidad.

Ejemplo:

En la aplicación del punto de venta, alguna clase necesita conocer el gran total de la venta.

Beneficios: Se conserva el encapsulamiento, ya que los objetos se valen de su propia información para hacer lo que se les pide. Esto provee un bajo nivel de acoplamiento, lo que favorece el hecho de tener sistemas más robustos y de fácil mantenimiento.

El comportamiento se distribuye entre las clases que cuentan con la información requerida, lo que ayuda a definir clases "sencillas" y más cohesivas, que son más fáciles de comprender y mantener.

A partir de esta recomendación, se puede plantear la pregunta: ¿Quién es el responsable de conocer el gran total de la venta?

Desde el punto de vista del patrón Experto, deberíamos buscar la clase de objetos que posee la información necesaria para calcular el total. Por ejemplo:

El patrón Experto [Larman 98] Experto. ¿Cuál es el principio fundamental en virtud del cual se

¿Qué información hace falta para calcular el gran total? Hay que conocer todas las instancias VentaLineadeProducto de una venta, y la suma de sus subtotales, y esto lo conoce únicamente la instancia Venta. Por tanto, desde el punto de vista del Experto, Venta es la clase de objetos correcta para asumir esta responsabilidad. Venta es el experto en información. Entonces:

Todavía no terminamos. ¿Qué información hace falta para determinar el subtotal de la línea de productos?

Todavía no terminamos. ¿Qué información hace falta para determinar el subtotal de la línea de productos? Se necesitan VentasLineadeProducto.cantidad y EspecificaciondeProducto.precio. VentasLineadeProducto conoce su cantidad y su correspondiente EspecificaciondeProducto. Por tanto, desde la perspectiva del patrón Experto, VentasLineadeProducto debería calcular el subtotal.

Todavía no terminamos. ¿Qué información hace falta para determinar el subtotal de la línea de productos?

VentasLineadeProducto no puede cumplir la responsabilidad de conocer y dar el subtotal, si no conoce el precio del producto. EspecificaciondeProducto es un Experto en información para contestar su precio. Por tanto, habrá que enviarle un mensaje preguntándole el precio.

Todavía no terminamos. ¿Qué información hace falta para determinar el subtotal de la línea de productos?

En conclusión, para cumplir con la responsabilidad de conocer y dar el total de la venta, se asignaron tres responsabilidades a las tres clases de objetos:

Clase

Responsabilidad

Venta

Conoce el total de la venta

VentasLineadeProducto

Conoce el subtotal de la línea de producto

EspecificaciondeProducto

Conoce el precio del producto

Note que el cumplimiento de una responsabilidad requiere a menudo información distribuida en varias clases de objetos. Es decir, hay muchos "expertos parciales" que colaboran en la tarea. Cuando la información se encuentre esparcida entre varios objetos, éstos tendrán que interactuar a través de mensajes para compartir el trabajo.

El patrón Creador [Larman 98]

El patrón Creador guía la asignación de responsabilidades relacionadas con la creación de objetos, tarea muy frecuente en los sistemas orientados a objetos. El objetivo de este patrón es encontrar un creador que debemos conectar con el objeto producido en cualquier evento.

Nombre:

Creador.

Problema:

¿Quién debería ser responsable de crear una

nueva instancia de alguna

clase?

La creación de objetos es una de las actividades más frecuentes en un sistema orientado a objetos. En consecuencia, conviene contar con un principio general para asignar las responsabilidades concernientes a ella. El diseño, bien asignado, puede apoyar un bajo acoplamiento, una mayor claridad, el encapsulamiento y la reutilización.

Solución:

Asignarle a la clase B la responsabilidad de crear una instancia de la clase A en uno de los siguientes casos:

· B agrega los objetos de A. · B contiene los objetos de A. · B registra las instancias de los objetos de A. · B tiene los datos de inicialización que serán enviados a A cuando este objeto sea creado (B es un experto respecto a la creación de A). B es un creador de los objetos A. Si existe más de una opción, prefiera la clase B que agregue o contenga la clase A.

Ejemplo:

En la aplicación del punto de venta, ¿quién debería encargarse de crear una instancia de VentasLineadeProducto? Desde el punto de vista del patrón Creador, deberíamos buscar una clase que agregue, contenga, y realice otras operaciones sobre este tipo de instancias.

Beneficios:

Se brinda apoyo a un bajo acoplamiento, lo cual supone menos dependencias respecto al mantenimiento y mejores oportunidades de reutilización.

Una Venta contiene (en realidad, agrega) muchos objetos VentasLineadeProducto. Es por esto que el patrón Creador sugiere que Venta es la clase idónea para asumir la responsabilidad de crear las instancias de VentasLineadeProducto. Esta asignación de responsabilidades requiere definir en Venta un método para hacerLineadeProducto.

Creador. ¿Quién debería ser responsable de crear una nueva instancia de alguna clase? La creación de

El patrón Controlador [Larman 98] Nombre: Controlador.

Problema: ¿Quién debería

encargarse

de

atender

un

evento

del

sistema?

Un evento del sistema es un evento de alto nivel generado por un actor externo. Es un evento de entrada externa. Se asocia a operaciones del sistema: las que se emiten en respuesta a los eventos del sistema. Por ejemplo, cuando un cajero que usa una

terminal de punto de venta oprime el botón "terminar venta", está generando un evento sistémico que indica que "la venta ha terminado". Del mismo modo, cuando alguien que usa un editor de texto pulsa el botón "revisar ortografía", está produciendo un evento del sistema.

Un controlador es un objeto de interfaz que se encarga de manejar un evento del sistema. Define además el método de su operación.

Solución:

Asignar la responsabilidad del manejo de mensajes de los eventos del sistema a una clase que represente alguna de las siguientes opciones:

· El "sistema" global (controlador de fachada). · La empresa u organización global (controlador de fachada). · Algo en el mundo real que es activo (por ejemplo el rol de una persona) y que pueda participar en la tarea (controlador de tareas). · Un manejador artificial de todos los eventos del sistema de un caso de uso (controlador de casos de uso).

Utilice la misma clase controlador con todos los eventos del sistema en el mismo caso de uso.

Ejemplo:

En la aplicación del punto de venta se dan varias operaciones del sistema, como

terminarVenta(), pasarProducto(), efectuarPago().

Beneficios:

Garantiza que la empresa o los procesos de dominio sean manejados por la capa de los objetos del dominio y no por la interfaz.

Durante el análisis del comportamiento del sistema, sus operaciones son asignadas al tipo Sistema, para indicar que son operaciones del sistema.

terminal de punto de venta oprime el botón "terminar venta", está generando un evento sistémico que

Pero esto no significa que una clase llamada Sistema las ejecuta durante el diseño. Durante el diseño, a la clase Controlador se le asigna la responsabilidad de las operaciones del sistema.

¿Quién debería ser el controlador de eventos sistémicos como pasarProducto y terminarVenta? Según el patrón Controlador, disponemos de las siguientes opciones:

TPDV

Representa el "sistema" global.

Tienda

Representa la empresa u organización global.

Cajero

Representa algo en el mundo real que está activo (por ejemplo el rol de una persona) y que puede intervenir en la tarea.

ManejadordeComprar-

Representa un manejador artificial de todas las operaciones del sistema de un

Productos

caso de uso.

Las operaciones del sistema, detectadas en el análisis, se asignarán a TPDV.

Las operaciones del sistema, detectadas en el análisis, se asignarán a TPDV . La mayor parte

La mayor parte de los sistemas reciben eventos de entrada externa, los cuales generalmente incluyen una interfaz gráfica para el usuario (GUI), operada por una persona. Otros medios de entrada son los mensajes externos, o señales procedentes de censores. En todos estos casos, hay que elegir los controladores que manejan estos eventos de entrada. La misma clase controlador debería usarse con todos los eventos sistémicos de un caso de uso. Esto es útil por ejemplo para detectar eventos del sistema fuera de secuencia (por ejemplo, una operación efectuarPago antes de terminarVenta). La primera categoría de controlador, es un controlador de fachada, que representa al "sistema" global. Es una clase que, para el diseñador, representa de alguna manera al sistema entero. Si se recurre a la cuarta categoría de controlador (un "manejador artificial de casos de uso"), habrá entonces un controlador para cada caso. Este no es un objeto del dominio, es un concepto artificial. Por ejemplo, si la aplicación de punto de venta contiene casos como "Comprar Productos" y "Devolver Productos", habrá una clase ManejadordeComprarProductos y una clase ManejadordeDevolverProductos. Un controlador de casos de uso es una buena alternativa cuando hay muchos eventos de sistema entre varios procesos: asigna su manejo a clases individuales controlables.

El patrón Bajo acoplamiento [Larman98]

Nombre:

Bajo acoplamiento.

Problema: ¿Cómo dar soporte a una mínima dependencia y a un aumento en la reutilización?

El acoplamiento mide qué tan fuerte está una clase conectada con otras (es decir, cuántas clases conoce y necesita). Una clase con bajo (o débil) acoplamiento no depende de "muchas otras" clases. Una clase con alto (o fuerte) acoplamiento recurre a muchas otras clases. Este tipo de clase no es conveniente, pues: cambios en las clases relacionadas ocasionan cambios en la clase local; son más difíciles de entender; son más difíciles de reutilizar.

Solución:

Asignar una responsabilidad para mantener bajo acoplamiento.

Ejemplo:

Tres de las clases de la aplicación de punto de venta era: Pago, TPV y Venta. Supongamos que necesitamos crear una instancia de Pago y asociarla a Venta. Como TPV "registra" un Pago en el mundo real, es un buen candidato para crearlo. Ejemplo:

Las operaciones del sistema, detectadas en el análisis, se asignarán a TPDV . La mayor parte

Esta asignación de responsabilidades acopla la clase TPV al conocimiento de la clase Pago. Una solución alterna sería crear Pago y asociarlo a Venta. Por ejemplo:

Esta asignación de responsabilidades acopla la clase TPV al conocimiento de la clase Pago . Una

Este último diseño es mejor porque conserva un menor acoplamiento global. El anterior es un ejemplo donde dos patrones distintos (Creador y Bajo acoplamiento) pueden sugerir soluciones distintas.

Explicación: Las formas más comunes de acoplamiento son las siguientes:

  • - Una clase X posee un atributo o variable de instancia que se refiere a otra instancia de clase
    Y.

  • - X tiene un método que referencia una instancia de clase Y.

  • - X tiene un parámetro o una variable local de tipo Y.

  • - El objeto devuelto en un mensaje invocado por X es una instancia de clase Y.

  • - X es una subclase de Y.

  • - Y es una interfaz y X la implementa.

El bajo acoplamiento apoya el diseño de clases más independientes, que reducen el impacto de los cambios, así como clases más reutilizables. El acoplamiento no es importante si no se busca la reutilización.

Diseño de la solución Para cada evento del sistema se debe construir un diagrama de colaboración cuyo mensaje inicial sea el de sus eventos. En el caso del punto de venta, tendremos cuatro diagramas, uno para cada evento:

pasarProducto, terminarVenta, efectuarPago, iniciar. El diagrama de colaboración de pasarProducto sería el siguiente:

Esta asignación de responsabilidades acopla la clase TPV al conocimiento de la clase Pago . Una

El método especificacion(cod) fue asignado a la clase CatalogodeProductos según el patrón Experto. La asignación de los métodos hacerLineadeProducto(especif,cant), crear() y crear(especif,cant), fueron asignados a sus respectivas clases según el patrón Creador.

La operación terminarVenta ocurre cuando un cajero oprime un botón para indicar la conclusión de una venta. El diagrama de colaboración de terminarVenta para indicar que se terminó de realizar la captura de productos sería el siguiente:

El método especificacion(cod) fue asignado a la clase CatalogodeProductos según el patrón Experto . La asignación

La asignación del método terminarVenta() a la clase TPDV fue realizada según el patrón Controlador. La asignación del método seTermina() a la clase Venta fue realizada según el patrón Experto.

El diagrama de colaboración de terminarVenta para calcular el total de la venta, sería el siguiente:

El método especificacion(cod) fue asignado a la clase CatalogodeProductos según el patrón Experto . La asignación

La asignación del método total() a la clase Venta, así como la asignación del método subtotal() a la clase VentasLineadeProducto fueron realizadas según el patrón Experto.

La operación efectuarPago ocurre cuando un cajero captura el efectivo ofrecido por el cliente como pago de la compra. La compra en la tienda se debe registrar como terminada. El diagrama de colaboración de efectuarPago sería el siguiente:

El método efectuarPago(efectivoOfrecido) fue asignado a la clase TPDV según el patrón Controlador . La asignación

El método efectuarPago(efectivoOfrecido) fue asignado a la clase TPDV según el patrón Controlador. La asignación de efectuarPago(efectivoOfrecido) a Venta, y de crear(efectivoOfrecido) a Pago se realizó según el patrón Creador. Para asignar el método agregarVenta(v) a la clase Tienda se usó el patrón Experto. El siguiente diagrama de colaboración permite conocer el saldo final de la venta, es decir, el monto pagado menos el total de la venta:

El método efectuarPago(efectivoOfrecido) fue asignado a la clase TPDV según el patrón Controlador . La asignación

Finalmente, la operación Iniciar representa, en forma abstracta, la fase inicializadora de la ejecución al comenzar la aplicación. Este proceso, por lo general, debe crear el objeto inicial del dominio. Además, es posible que también ejecute algún otro proceso. Antes de ver el diagrama de colaboración de Iniciar, revisemos el patrón MVC. Este es un patrón arquitectural (patrones del más alto nivel).

Nombre: Modelo-Vista-Controlador (MVC) [Buschmann 96].

Problema: Las interfaces de usuario son especialmente propensas a cambios de requerimientos. Cuando se extiende la funcionalidad de una aplicación, se deben modificar cosas, como por ejemplo: menús, botones, ventanas, etc.

Solución:

MVC divide una aplicación en tres áreas: procesamiento, entrada y salida. El componente modelo encapsula los datos y la funcionalidad principales de la aplicación. El componente Vista despliega la información al usuario, a partir de los datos del Modelo. Cada Vista tiene un componente Controlador asociado, que se encarga de recibir las entradas del usuario (usualmente en forma de eventos como:

movimiento del mouse, activación de los botones del mouse, o entradas de teclado). Esta separación de componentes, permite, entre otras cosas, tener distintas vistas del mismo modelo.

Ejemplo:

La mayoría de aplicaciones con interfaz gráfica utilizan este esquema. La programación con herramientas visuales como Visual Basic, JBuilder, Delphi, etc. sigue este esquema.

Beneficios: Es posible tener múltiples vistas de un mismo modelo. Es posible sincronizar las vistas cuando varios usuarios usan la misma aplicación (juegos multiusuario, sistemas colaborativos, etc). La separación conceptual permite intercambiar la vista y el controlador de un determinado modelo (plug and play).

El patrón MVC separa dos conceptos fundamentales en toda aplicación: la interfaz (vista y controlador) y el modelo (datos y funcionalidad). Al usar este patrón, podríamos implementar la interfaz de nuestra aplicación de punto de venta como un applet Java, como un programa Java stand- alone, y de otras formas (no necesariamente en Java). Desde esta interfaz se invocaría el llamado del método Iniciar, que debería realizar las siguientes acciones (según su contrato): Crear Tienda, TPV, CatalogodePooductos y EspecificaciodeProducto; Asociar Tienda a CatalogodeProductos; Asociar Tienda a TPV; Asociar TPV a CatalogodeProductos. Esto se muestra en el siguiente diagrama:

El patrón MVC separa dos conceptos fundamentales en toda aplicación: la interfaz (vista y controlador) y

Además, si desarrolláramos la interfaz como un applet Java (por ejemplo), deberíamos desde la interfaz crear la instancia de Tienda, y solicitar a esta instancia de Tienda una referencia a la correspondiente instancia de TPDV creada. Esto para conectar la capa de presentación con la capa de dominio.

El patrón MVC separa dos conceptos fundamentales en toda aplicación: la interfaz (vista y controlador) y