Computación
Análisis orientado a objetos

Ir al catálogo de monografías
y textos sobre otros temas

Glosarios - Biografías - Textos
históricos - Libros en línea


Buscar en Avizora y Atajo - by freefind

Historia de la computación y las computadoras - Del ábaco a la tarjeta perforada

1. Introducción y conceptos básicos.

2. Técnica de modelado de objetos (OMT).

2.1. Fases.

2.2. Modelos.

2.3. Diferencias con la metodología estructurada.

3. Casos de uso.

4. Modelo de objetos.

5. Modelo dinámico.

6. Modelo funcional.

7. Relación entre los modelos.

8. Método de análisis.

Tema: Análisis orientado a objetos.

5.1. Introducción y conceptos básicos.

Desde comienzos de la década de los 80, el paradigma "orientado a objetos" ha ido madurando como un enfoque de desarrollo de software alternativo a la programación estructurada o modular. Se empezó a crear diseños de aplicaciones de todo tipo usando una forma de pensar orientada a los objetos, y a implementar estos diseños utilizando lenguajes orientados a objetos. Sin embargo, el análisis de requisitos se quedó atrás. No se desarrollaron técnicas de análisis específicamente orientadas a objetos.

Esta situación ha ido cambiando poco a poco, a medida que se desarrollaban técnicas de análisis específicas para desarrollar software orientado a objetos, e incluso como complemento de otros métodos de análisis. Ejemplos de estas nuevas técnicas son los métodos de Coad/Yourdon, Jacobson, Booch y Rumbaugh (OMT) . En este tema seguiremos principalmente esta última metodología.

El Análisis Orientado a Objetos (AOO) se basa en conceptos sencillos, conocidos desde la infancia y que aplicamos continuamente: objetos y atributos, el todo y las partes, clases y miembros. Puede parecer llamativo que se haya tardado tanto tiempo en aplicar estos conceptos al desarrollo de software. Posiblemente, una de las razones es el éxito de los métodos de análisis estructurados, basados en el concepto de flujo de información, que monopolizaron el análisis de sistemas software durante los últimos veinte años.

En cualquier caso, el paradigma orientado a objetos ha sufrido una evolución similar al paradigma de programación estructurada: primero se empezaron a utilizar los lenguajes de programación estructurados, que permiten la descomposición modular de los programas; esto condujo a la adopción de técnicas de diseño estructuradas y de ahí se paso al análisis estructurado. El paradigma orientado a objetos ha seguido el mismo camino: el uso de la Programación Orientada a Objetos (POO) ha modificado las técnicas de diseño para adaptarlas a los nuevos lenguajes y ahora se están empezando a utilizar técnicas de análisis basadas en este nueva forma de desarrollar software.

El AOO ofrece un enfoque nuevo para el análisis de requisitos de sistemas software. En lugar de considerar el software desde una perspectiva clásica de entrada/proceso/salida, como los métodos estructurados clásicos, se basa en modelar el sistema mediante los objetos que forman parte de él y las relaciones estáticas (herencia y composición) o dinámicas (uso) entre estos objetos. Este enfoque pretende conseguir modelos que se ajusten mejor al problema real, a partir del conocimiento del llamado dominio del problema, evitando que influyan en el análisis consideraciones de que estamos analizando un sistema para implementarlo en un ordenador. Desde este punto de vista, el AOO consigue una abstracción mayor que el análisis estructurado, que modela los sistemas desde un punto de vista más próximo a su implementación en un ordenador (entrada/proceso/salida).

Este intento de conocer el dominio del problema ha sido siempre importante; no tiene sentido empezar a escribir los requisitos funcionales de un sistema de control de tráfico aéreo, y menos aún diseñarlo o programarlo sin estudiar primero qué es el tráfico aéreo o qué se espera de un sistema de control de este tipo. La ventaja del AOO es que se basa en la utilización de objetos como abstracciones del mundo real. Esto nos permite centrarnos en los aspectos significativos del dominio del problema (en las características de los objetos y las relaciones que se establecen entre ellos) y este conocimiento se convierte en la parte fundamental del análisis del sistema software, que será luego utilizado en el diseño y la implementación.

Este enfoque no es totalmente nuevo, sino que puede considerarse como una extensión del modelado de datos (DER) que se utiliza en los métodos estructurados. Sin embargo, el modelado de datos mediante DER está más orientado al diseño de bases de datos y se centra exclusivamente en la identificación de los datos que maneja un sistema y en las relaciones estáticas que se establecen entre esos datos. En el AOO, los objetos encapsulan tanto atributos como procedimientos (operaciones que se realizan sobre los objetos), e incorpora además conceptos como el polimorfismo o la herencia que facilitan la reutilización de código.

El uso de AOO puede facilitar mucho la creación de prototipos, y las técnicas de desarrollo evolutivo de software. Los objetos son inherentemente reutilizables, y se puede crear un catálogo de objetos que podemos usar en sucesivas aplicaciones. De esta forma, podemos obtener rápidamente un prototipo del sistema, que pueda ser evaluado por el cliente, a partir de objetos analizados, diseñados e implementados en aplicaciones anteriores. Y lo que es más importante, dada la facilidad de reutilización de estos objetos, el prototipo puede ir evolucionando hacia convertirse en el sistema final, según vamos refinando los objetos de acuerdo a un proceso de especificación incremental.

5.1.1. Deficiencias del análisis estructurado.

  • Descomposición funcional. El análisis estructurado se basa fundamentalmente en la descomposición funcional del sistema que queremos construir. Esta descomposición funcional requiere traducir el dominio del problema en una serie de funciones y subfunciones. El analista debe comprender primero el dominio del problema y a continuación documentar las funciones y subfunciones que debe proporcionar el sistema. El problema es que no existe un mecanismo para comprobar si la especificación del sistema expresa con exactitud los requisitos del sistema.

  • Flujo de datos. El análisis estructurado muestra cómo fluye la información a través del sistema. Aunque este enfoque se adapta bien al uso de sistemas informáticos para implementar el sistema, no es nuestra forma habitual de pensar. Sin embargo, la abstracción y la clasificación sí son conceptos que manejamos habitualmente, aunque sea de forma inconsciente.

  • Modelo de datos. El análisis clásico daba muy poca importancia al almacenamiento de datos. El análisis estructurado moderno incorpora modelos de datos, además de modelos de procesos y de comportamiento. Sin embargo la relación entre los modelos es muy débil, y hay muy poca influencia de un modelo en otro. En la práctica, los modelos de procesos y de datos de un mismo sistema se parecen muy poco. En muchos casos son visiones irreconciliables, no del mismo sistema, sino de dos puntos de vista totalmente diferentes de organizar la solución. Lo ideal sería que ambos modelos se complementasen, no por oposición sino de forma que el desarrollo de uno facilitase el desarrollo del otro.

5.1.2. Ventajas del AOO.

  • Dominio del problema. El paradigma OO es más que una forma de programar. Es una forma de pensar acerca de un problema en términos del mundo real en vez de en términos de un ordenador. El AOO permite analizar mejor el dominio del problema, sin pensar en términos de implementar el sistema en un ordenador. El AOO permite pasar directamente el dominio del problema al modelo del sistema.

  • Comunicación. El concepto OO es más simple y está menos relacionado con la informática que el concepto de flujo de datos. Esto permite una mejor comunicación entre el analista y el experto en el dominio del problema (es decir, el cliente).

  • Consistencia. Los objetos encapsulan tanto atributos como operaciones. Debido a esto, el AOO reduce la distancia entre el punto de vista de los datos y el punto de vista del proceso, dejando menos lugar a inconsistencias o disparidades entre ambos modelos.

  • Expresión de características comunes. El paradigma OO utiliza la herencia para expresar explícitamente las características comunes de una serie de objetos. Estas características comunes quedan escondidas en otros enfoques y llevan a duplicar entidades en el análisis y código en los programas. Sin embargo, el paradigma OO pone especial énfasis en la reutilización, y proporciona mecanismos efectivos que permiten reutilizar aquello que es común, sin impedir por ello describir las diferencias.

  • Resistencia al cambio. Los cambios en los requisitos afectan notablemente a la funcionalidad de un sistema, por lo que afectan mucho al software desarrollado con métodos estructurados. Sin embargo, los cambios afectan en mucha menor medida a los objetos que componen o maneja el sistema, que son mucho más estables. Las modificaciones necesarias para adaptar una aplicación basada en objetos a un cambio de requisitos suelen estar mucho más localizadas.

  • Reutilización. Aparte de la reutilización interna, basada en la expresión explícita de características comunes, el paradigma OO desarrolla modelos mucho más próximos al mundo real, con lo que aumentan las posibilidades de reutilización. Es probable que en futuras aplicaciones nos encontremos con objetos iguales o similares a los de la actual.

 

 

 

5.1.3. Conceptos básicos.

Las técnicas orientadas a objetos se basan en organizar el software como una colección de objetos discretos que incorporan tanto estructuras de datos como comportamiento. Esto contrasta con la programación convencional, en la que las estructuras de datos y el comportamiento estaban escasamente relacionadas.

Las características principales del enfoque orientado a objetos son, en primer lugar:

Identidad.

Los datos se organizan en entidades discretas y distinguibles llamadas objetos. Estos objetos pueden ser concretos o abstractos, pero cada objeto tiene su propia identidad. Dicho de otra forma: dos objetos son distintos incluso aún en el caso de que los valores de todos sus atributos (p. ej. nombre y tamaño) coincidan. Dos manzanas pueden ser totalmente idénticas pero no por eso pierden su identidad: nos podemos comer una u otra.

Clasificación.

Los objetos que tengan los mismos atributos y comportamiento se agrupan en clases. Todas las manzanas tienen una serie de atributos comunes: tamaño, peso, grado de maduración, y un comportamiento común: podemos coger una manzana, moverla o comerla. Los valores de los atributos podrán ser distintos para cada una de ellas, pero todas comparten los mismos atributos y comportamiento (las operaciones que se pueden realizar sobre ellas). Una clase es una abstracción que describe propiedades (atributos y comportamiento) relevantes para una aplicación determinada, ignorando el resto. La elección de clases es arbitraria, y depende del dominio del problema.

Según esto, una clase es una abstracción de un conjunto posiblemente infinito de objetos individuales. Cada uno de estos objetos se dice que es una instancia o ejemplar de dicha clase. Cada instancia de una clase tiene sus propios valores para sus atributos, pero comparte el nombre de estos atributos y las operaciones con el resto de instancias de su clase.

Polimorfismo.

El polimorfismo permite que una misma operación pueda llevarse a cabo de forma diferente en clases diferentes. Por ejemplo, la operación mover, es distinta para una pieza de ajedrez que para una ficha de parchís, pero ambos objetos pueden ser movidos. Una operación es una acción o transformación que realiza o padece un objeto. La implementación específica de una operación determinada en una clase determinada se denomina método.

Según lo dicho, una operación es una abstracción de un comportamiento similar (pero no idéntico) en diferentes clases de objetos. La semántica de la operación debe ser la misma para todas las clases. Sin embargo, cada método concreto seguirá unos pasos procedimentales específicos.

Herencia.

El concepto de herencia se refiere a la compartición de atributos y operaciones basada en una relación jerárquica entre varias clases. Una clase puede definirse de forma general y luego refinarse en sucesivas subclases. Cada clase hereda todas las propiedades (atributos y operaciones) de su superclase y añade sus propiedades particulares.

La posibilidad de agrupar las propiedades comunes de una serie de clases en una superclase y heredar estas propiedades en cada una de las subclases es lo que permite reducir la repetición de código en el paradigma OO y es una de sus principales ventajas.

5.2. Técnica de modelado de objetos (OMT).

La esencia del desarrollo de software OO es la identificación y organización de conceptos del dominio del problema, más que en su implementación final usando un determinado lenguaje.

La Técnica de Modelado de Objetos (OMT, Rumbaugh, 1991) es un procedimiento que se basa en aplicar el enfoque orientado a objetos a todo el proceso de desarrollo de un sistema software, desde el análisis hasta la implementación. Los métodos de análisis y diseño que propone son independientes del lenguaje de programación que se emplee para la implementación. Incluso esta implementación no tiene que basarse necesariamente en un lenguaje OO.

OMT es una metodología OO de desarrollo de software basada en una notación gráfica para representar conceptos OO. La metodología consiste en construir un modelo del dominio de aplicación y ir añadiendo detalles a este modelo durante la fase de diseño. OMT consta de las siguientes fases o etapas.

5.2.1. Fases.

  • Conceptualización. Consiste en la primera aproximación al problema que se debe resolver. Se realiza una lista inicial de requisitos y se describen los casos de uso.

  • Análisis. El analista construye un modelo del dominio del problema, mostrando sus propiedades más importantes. Los elementos del modelo deben ser conceptos del dominio de aplicación y no conceptos informáticos tales como estructuras de datos. Un buen modelo debe poder ser entendido y criticado por expertos en el dominio del problema que no tengan conocimientos informáticos.

  • Diseño del sistema. El diseñador del sistema toma decisiones de alto nivel sobre la arquitectura del mismo. Durante esta fase el sistema se organiza en subsistemas basándose tanto en la estructura del análisis como en la arquitectura propuesta.

  • Diseño de objetos. El diseñador de objetos construye un modelo de diseño basándose en el modelo de análisis, pero incorporando detalles de implementación. El diseño de objetos se centra en las estructuras de datos y algoritmos que son necesarios para implementar cada clase. OMT describe la forma en que el diseño puede ser implementado en distintos lenguajes (orientados y no orientados a objetos, bases de datos, etc.).

  • Implementación. Las clases de objetos y relaciones desarrolladas durante el análisis de objetos se traducen finalmente a una implementación concreta. Durante la fase de implementación es importante tener en cuenta los principios de la ingeniería del software de forma que la correspondencia con el diseño sea directa y el sistema implementado sea flexible y extensible. No tiene sentido que utilicemos AOO y DOO de forma que potenciemos la reutilización de código y la correspondencia entre el dominio del problema y el sistema informático, si luego perdemos todas estas ventajas con una implementación de mala calidad.

Algunas clases que aparecen en el sistema final no son parte del análisis sino que se introducen durante el diseño o la implementación. Este es el caso de estructuras como árboles, listas enlazadas o tablas hash, que no suelen estar presentes en el dominio de aplicación. Estas clases se añaden para permitir utilizar determinados algoritmos.

Los conceptos del paradigma OO pueden aplicarse durante todo el ciclo de desarrollo del software, desde el análisis a la implementación sin cambios de notación, sólo añadiendo progresivamente detalles al modelo inicial.

5.2.2. Modelos.

Al igual que los métodos estructurados, OMT utiliza tres tipos de modelos para describir un sistema:

  • Modelo de objetos. Describe la estructura estática de los objetos de un sistema y sus relaciones. El modelo de objetos contiene diagramas de objetos. Un diagrama de objetos es un grafo cuyos nodos son clases y cuyos arcos son relaciones entre clases.

  • Modelo dinámico. El modelo dinámico describe las características de un sistema que cambia a lo largo del tiempo. Se utiliza para especificar los aspectos de control de un sistema. Para representarlo utilizaremos DEs.

  • Modelo funcional. Describe las transformaciones de datos del sistema. El modelo funcional contiene DFDs y especificaciones de proceso.

Los tres modelos son vistas ortogonales (independientes) del mismo sistema, aunque existen relaciones entre ellos. Cada modelo contiene referencias a elementos de los otros dos. Por ejemplo, las operaciones que se asocian a los objetos del modelo de objetos figuran también, de forma más detallada en el modelo funcional. El más importante de los tres es el modelo de objetos, porque es necesario describir qué cambia antes que decir cuándo o cómo cambia.

5.2.3. Diferencias con los métodos estructurados.

OMT invierte el método estructurado, en el que se da más importancia a la descomposición funcional del sistema y, por tanto, a los diagramas de proceso. Este enfoque de descomposición funcional puede parecer que lleva de forma más directa a una implementación del sistema, pero con frecuencia este sistema suele ser más frágil. Si cambian los requisitos, un sistema basado en descomposición funcional puede requerir una reestructuración masiva. Por el contrario, el enfoque OO se centra en primer lugar en identificar los objetos del dominio de aplicación y después en establecer procedimientos que los manejen. Aunque esto puede parecer más indirecto, el software OO se mantiene mejor ante los cambios de requisitos, porque se basa en la estructura subyacente del dominio de aplicación, en vez de en los requisitos funcionales de un determinado problema.

De todas formas, los modelos son los mismos que en el análisis estructurado. El modelo de objetos, el único que parece nuevo, es bastante similar a los DERs. Las diferencias principales consisten en la mayor importancia que se da el modelo de datos, por encima de los otros dos, y en el enfoque orientado a objetos de este modelo (encapsulando tanto datos como operaciones) en vez de estar orientado a bases de datos como los DERs.

En este sentido, puede compararse a los paquetes de lenguajes como ADA, con los que se implementan TADs. La diferencia reside en que en la POO, la herencia y el polimorfismo favorecen la reutilización de código y la programación por especialización, desde una perspectiva distinta al uso de paquetes genéricos en ADA.

5.3. Casos de uso.

Una forma de describir los requisitos iniciales del usuario, durante la fase de conceptualización, es construir casos de uso del sistema, descritos inicialmente por Jacobson en 1987 y actualmente incorporados a la mayor parte de las metodologías de AOO.

Un caso de uso está formado por una serie de interacciones entre el sistema y un actor (una entidad externa, ejerciendo un rol determinado), que muestran una determinada forma de utilizar el sistema. Cada interacción comienza con un evento inicial que el actor envía al sistema y continua con una serie de eventos entre el actor, el sistema y posiblemente otros actores involucrados.

Un caso de uso puede ser descrito en lenguaje natural, mediante trazas de eventos o mediante diagramas de interacción de objetos.

5.4. Modelo de objetos.

El modelo de objetos describe la estructura de los objetos de un sistema: su identidad, sus relaciones con otros objetos, sus atributos y sus operaciones. Los cambios y las transformaciones no tienen sentido a menos que haya algo que cambiar o transformar. OMT considera este modelo el más importante de los tres.

El modelo de objetos se representa gráficamente con diagramas de objetos y diagramas de instancias, que contienen clases de objetos e instancias, respectivamente. Las clases se disponen en jerarquías que comparten una estructura de datos y un comportamiento comunes, y se relacionan con otras clases. Cada clase define los atributos que contiene cada uno de los objetos o instancias y las operaciones que realizan o sufren estos objetos.

5.4.1. Elementos del modelo de objetos.

El modelo de objetos puede contener los siguientes elementos:

Objetos o instancias.

Un objeto es un concepto, una abstracción o una cosa con unos límites definidos y que es relevante para el problema en cuestión. Los modelos de objetos sirven tanto para obtener un conocimiento mejor del dominio de aplicación como de base para la implementación del sistema en un ordenador.

Una característica de los objetos es que tienen identidad y son distinguibles. Aunque dos objetos tengan los mismos valores para todos sus atributos son diferentes.

El término objeto está sobrecargado. Mediante él podemos referirnos tanto a clases de objetos (p. ej. el concepto abstracto mesa) como a las instancias de estas clases (una mesa determinada). Es mejor utilizar los términos clase e instancia para evitar confusiones.

La mayoría de las instancias de una clase derivan su individualidad de tener valores diferentes en alguno/s de sus atributos o de tener relaciones con instancias diferentes. No obstante pueden existir instancias con los mismos valores de los atributos e idénticas relaciones.

El símbolo gráfico para representar instancias es un rectángulo de esquinas redondeadas. Dentro del rectángulo figura la clase a la que pertenece la instancia (entre paréntesis) y los valores de sus atributos.

Las instancias figuran en diagramas de instancias, que se utilizan normalmente para describir ejemplos que aclaren un diagrama de objetos complejos o para describir escenarios determinados (p. ej. situaciones típicas o anómalas, escenarios de prueba, etc.).

Clases.

Una clase o clase de objetos es una abstracción que describe un grupo de instancias con propiedades (atributos) comunes, comportamiento (operaciones) común, relaciones comunes con otros objetos y (lo que es más importante) una semántica común. Así un caballo y un establo tienen los dos un coste y una edad, pero posiblemente pertenezcan a clases diferentes (aunque esto depende del dominio de aplicación: en una aplicación financiera ambos pertenecerían posiblemente a la misma clase: Inversiones).

La diferencia entre instancia y clase está en el grado de abstracción. Un objeto es una abstracción de un objeto del mundo real, pero una clase es una abstracción de un grupo de objetos del mundo real. La abstracción permite la generalización y evita la redefinición de las características (atributos, comportamiento o relaciones) comunes, de forma que se produce una reutilización de estas definiciones comunes por parte de cada uno de los objetos. Por ejemplo todas las elipses (instancias) comparten las mismos operaciones para dibujarlas o calcular su área.

El símbolo gráfico para representar clases es un rectángulo, en el que figura el nombre de la clase. Las clases se representan en los diagramas de clases, que son plantillas que describen un conjunto de posibles diagramas de instancias. Describen, por tanto el caso general.

Atributos.

Un atributo es un dato contenido en todas las instancias de una clase. Cada atributo tiene un valor para cada una de las instancias. Varias clases pueden tener atributos comunes (p. ej. nombre, en las clases Persona y Calle) pero cada atributo debe ser único dentro de una clase.

Los atributos tienen que ser datos, no objetos. La diferencia entre unos y otros reside en la identidad: los objetos tienen identidad, pero los atributos no. Por ejemplo, todas las ocurrencias del valor ‘3’ de un atributo son indistinguibles.

Los atributos se representan en el segundo área de los símbolos de clase e instancia. En las clases, figurará el nombre del atributo, el tipo y el valor por defecto. En las instancias, el valor del atributo para ese objeto determinado.

Operaciones.

Una operación o método es una función o transformación. Cada operación lleva implícito un objeto destino, sobre el que se va a realizar la operación. El comportamiento de la operación depende de la clase del objeto destino. Todos los objetos de una clase comparten las mismas operaciones o métodos. Cada objeto conoce la clase a que pertenece y, por tanto, la implementación correcta de la operación. Una misma operación puede aplicarse a objetos de clases distintas. En este caso diremos que la operación es polimórfica, y a la implementación de la operación en cada una de las clases la llamaremos método.

Una operación puede tener una serie de argumentos explícitos, además del objeto destino, que actúa siempre como argumento implícito.

Las operaciones figuran en la tercer área del símbolo de las clases. Opcionalmente figuran también la lista de argumentos y el tipo de resultado de la operación (si es que la operación devuelve algún resultado). En los símbolos de instancia no figuran las operaciones.

Enlaces.

Un enlace es una conexión entre dos o más instancias (objetos). Los enlaces pueden ser considerados como las instancias de las asociaciones.

Asociaciones.

Una asociación es una abstracción de un grupo de enlaces con una estructura común (todos ellos conectan instancias de objetos de las mismas clases) y una semántica común (todos los enlaces tienen el mismo significado. Una asociación describe un conjunto de enlaces potenciales de la misma forma que una clase describe un conjunto de instancias potenciales.

Tanto los enlaces como las asociaciones se representan mediante arcos, generalmente etiquetados con el nombre de la asociación. Aunque la etiqueta induce a leer una asociación en un determinado sentido, las asociaciones pueden recorrerse en cualquier dirección.

Los enlaces y las asociaciones pueden conectar más de dos objetos. En este caso se representan mediante un rombo con conexiones a cada uno de los objetos:

La mayoría de las asociaciones conectan solamente dos clases de objetos y, siempre que sea posible usaremos asociaciones binarias porque son más sencillas de nombrar, entender y de implementar Sin embargo habrá casos en los que no podamos desglosar una asociación n-aria en varias asociaciones binarias. En el ejemplo anterior si desglosamos la asociación en tres (Programador - conoce - Lenguaje, Proyecto - se implementa en - Lenguaje, y Programador - participa en - Proyecto), no podemos representar que un Programador participa en un Proyecto programando en un Lenguaje determinado de lo que conoce.

Multiplicidad.

Cada asociación puede modelar la conexión un número indeterminado de objetos de las clases que conecta. Para representar el número de instancias de cada clase que pueden participar en una asociación utilizaremos la siguiente notación en cada extremo de la asociación:

¡ Opcional. La asociación puede relacionar 0 ó 1 instancias de la clase

· Muchos. Significa de 0 a N.

3 Exactamente 3.

2,4 Dos o cuatro.

2-4 De dos a cuatro.

4+ Más de cuatro.

Exactamente 1.

Una multiplicidad mayor que uno (p. ej. la existente entre las clases Clase1 y Clase2 abajo) indica que para cada instancia del Clase1 pueden existir muchas instancias de la asociación (muchos enlaces) que lo conecten a instancias de la Clase2.

Con frecuencia la multiplicidad no viene expresada en la especificación preliminar, por lo que tendremos que decidirla en base al uso que queremos hacer del sistema. No es conveniente abusar de relaciones del tipo muchos a muchos pues, aunque son las más generales, van a sobrecargar el sistema a la hora de la implementación. De todas formas, no hay que preocuparse mucho de la multiplicidad en las etapas iniciales del análisis, cuando tengamos un mayor conocimiento del dominio del problema será más fácil decidir sobre ella.

Atributos de una asociación.

Al igual que los objetos contienen atributos, las asociaciones pueden contenerlos también. (p. ej. asociación pide entre Clientes y Artículos, que tiene un atributo cantidad). Estos atributos no pertenecen a ninguna de las clases relacionadas por lo que no hay más remedio que representarlos en la asociación. Estos atributos tendrán un valor propio para cada una de las instancias de la asociación (enlaces).

No obstante, si la asociación tiene multiplicidad 1/1 o 1/M podemos incluir estos atributos en la clase que tiene multiplicidad 1. Por ejemplo, en la relación Persona - compra - Casa, el atributo fecha de compra. puede incluirse en la clase Casa. Sin embargo, si la asociación es M/M, no podemos hacer esto: por ejemplo en un sistema de multipropiedad una casa puede pertenecer a varias personas, que la compran en fechas distintas. En cualquier caso no es conveniente incluir los atributos de las asociaciones en alguna de las clases relacionadas, puesto que reducimos la flexibilidad de nuestro modelo, que tendrá que ser reestructurado en caso de que necesitemos cambiar la multiplicidad.

Una asociación con atributos se parece bastante a una clase. En determinados casos (si la asociación contiene también operaciones o si mantiene asociaciones con otras clases podemos modelarla como una clase.

Calificación.

Un tipo especial de asociaciones son las asociaciones calificadas. Si queremos expresar mediante el modelo que ‘un directorio contiene varios ficheros, cada uno de ellos identificados mediante un nombre’ podemos hacer una asociación 1/M normal, con nombre fichero como atributo de Fichero (1)

(1)

De esta forma, partiendo del directorio podemos acceder a todos sus ficheros mediante la asociación múltiple, pero así no expresamos que el nombre identifica a los ficheros dentro del directorio. La solución es utilizar nombre fichero como calificador en el extremo opuesto al M de la asociación (2), en este caso desaparece la multiplicidad en la asociación, puesto que utilizando el nombre la asociación múltiple se convierte en unitaria y, además, el modelo contiene una información mucho más exacta.

(2)

La calificación reduce la multiplicidad pero en algunos casos no se logra conseguir una multiplicidad unitaria. Tomemos como ejemplo el calificador cargo en la plantilla de una empresa. Suponemos que varias personas pueden ocupar el mismo cargo (3)

(3)

(4)

En algunos casos podemos considerar al calificador como un atributo especial del objeto situado al otro extremo de la asociación (1), o también podemos considerar la asociación calificada como una forma de asociación ternaria (4) o asociación con atributos (5). Por último si consideramos que una misma persona puede ocupar varios cargos distintos en la empresa, no podemos considerar cargo como un atributo de persona (6 *), pues esto significaría que una persona ocupa varias veces el mismo cargo en varias empresas.

(5)

En resumen, la calificación nos permite reducir la multiplicidad y tiene una mayor potencia expresiva que las otras dos opciones (considerar el calificador como atributo de una de las clases o incluirlo como atributo de la asociación) por lo que optaremos por la asociación calificada cuando nos encontremos ante situaciones similares a las descritas.

(6 *)

Roles o papeles.

Para mayor claridad podemos etiquetar los extremos de las asociaciones con el rol o papel que representa la clase en la asociación. Así, en la relación trabaja, las personas juegan el papel de empleados mientras que las empresas juegan el papel de contratantes.

Restricciones

Las restricciones son relaciones funcionales entre entidades de un modelo de objetos. El término entidad incluye objetos, clases, atributos, enlaces y asociaciones. Una restricción restringe los valores que una entidad puede tomar.

Ejemplos:

  • Restricción entre objetos: El salario de un empleado no puede superar el salario del jefe.

  • Restricciones entre atributos de un objeto: Una ventana tiene que ser más alta que ancha.

  • Restricciones sobre un objeto a lo largo del tiempo: la prioridad de un trabajo no puede aumentar.

  • Restricciones sobre enlaces:

    • La multiplicidad restringe el números de objetos relacionados con un objeto determinado.

    • Por regla general, las instancias conectadas al extremo M de una asociación no tienen ningún orden, pero en algunos casos sí que existe este orden. Un ejemplo de relación ordenada es la que se establece entre un documento y sus páginas. Para expresar esta característica etiquetaremos el extremo M con {ordenado} .

Las restricciones simples pueden situarse en el modelo de objetos; restricciones complejas aparecerán en el modelo funcional. Las restricciones no tienen porqué aparecer inicialmente en el modelo de objetos, estas irán añadiéndose conforme se vaya concretando en la definición del modelo.

Las restricciones se escriben entre llaves y se colocan junto a la entidad restringida. Las restricciones se expresan en lenguaje natural o con ecuaciones. En caso de que existan varias entidades involucradas en una restricción, dibujaremos una línea de puntos entre las entidades. (Ejemplo: una asociación puede ser subconjunto de otra: el presidente de una comisión debe ser un miembro de la comisión -la asociación presidente_de es un subconjunto de la asociación miembro_de).

5.4.2. Relaciones de composición o agregación.

La composición nos permite representar las relaciones de se compone de o es una parte de que existen entre los objetos del modelo. Podemos utilizar asociaciones normales para representar la composición (y así lo hemos hecho en alguno de los ejemplos anteriores) pero la relación de composición tiene unas características especiales, por lo que se ha incluido un tipo de asociación especial para representarla.

Estas características son que la composición es transitiva, mientras que las relaciones normales no lo son. Por otra parte, la composición es antisimétrica y, por último, algunas propiedades del conjunto se propagan o influyen a las partes (p. ej. Un robot móvil con un brazo articulado: la posición del manipulador en el extremo del brazo depende no sólo de la posición (ángulos de rotación del brazo) sino también de la posición de todo el robot móvil.

La relación de composición se expresa gráficamente con un rombo al extremo de la asociación (p. ej. los Documentos se componen de Párrafos, que a su vez se componen de Caracteres). Para modelar un objeto que se compone de objetos de varias clases distintas (p. ej. una cebra que se compone de una cabeza, un cuerpo, hasta cuatro patas y una cola opcional) podemos agrupar las relaciones de composición en una única asociación ramificada, indicando la multiplicidad en cada extremo.

A veces, la aplicación de una operación a un objeto supone la aplicación automática de esta operación a un conjunto de objetos. A esto se le llama propagación.. La operación de copiar se propaga del documento a sus párrafos y de estos a sus caracteres. La operación sin embargo no se propaga en la dirección inversa, el hecho de copiar un párrafo no implica la copia del documento.

Agregación y Asociación

Según lo visto, la agregación no es más que un tipo (frecuente) de asociación, que tiene unas características determinadas y que se representa en OMT mediante una notación gráfica especial. La diferencia entre asociación y agregación es fundamentalmente semántica, y hay que tener esto presente a la hora de decidir modelar una relación entre clases como asociación o como agregación. Por ejemplo, una Empresa es una agregación de Divisiones, que a su vez son agregaciones de Departamentos. Sin embargo, no es una agregación de Personas, puesto que Empresa y Persona son objetos independientes.

5.4.3. Generalización.

El último tipo de relación puede presentarse entre las clases es la relación de generalización o especialización (depende desde dónde se mire).

La generalización es una forma de abstracción que permite modelar que varias clases comparten una serie de características comunes, a la vez que tienen características propias. En el paradigma OO la generalización se relaciona con el mecanismo de herencia, mediante el que los objetos heredan las características comunes (atributos y operaciones) y es la fuente principal de la reutilización de código.

Generalización o especialización es la relación que se establece entre una clase y una o más versiones refinadas de esta clase. La clase general se denomina superclase y las clases especializadas, subclases.

En la superclase definiremos los atributos y operaciones comunes a todas las subclases. En cada subclase definiremos los atributos y métodos específicos para esa subclase. El mecanismo de herencia garantiza que todas las subclases heredan los atributos y operaciones definidos en la superclase.

La relación de generalización puede modelarse en varios niveles y es transitiva: las instancias de una subclase heredan los atributos y operaciones de todas las clases antecesoras. Además, cada instancia de una subclase puede considerarse también una instancia de cada una de las clases antecesoras: una lista ordenada doblemente encadenada es también una lista doblemente encadenada y una lista.

Si hay varias clases que particularizan una dada, podemos modelar esto mediante una sola relación de generalización ramificada. En ocasiones, existe un atributo de la superclase cuyos valores determinan la adscripción de un objeto a una u otra de las subclases. Un atributo de este tipo se denomina discriminante.

Redefinición.

Las subclases no sólo heredan los atributos y las operaciones de la superclase sino que también pueden redefinirlos. Esto se hace cuando un método general definido en una superclase no puede aplicarse tal como está a algunas de las subclases o puede realizarse una implementación más eficiente del método (p. ej. en la jerarquía anterior podemos redefinir el método girar. De la misma forma, las clases que hereden de Polígono redefinirán el método área.

La redefinición no puede cambiar la semántica de la característica redefinida (la operación tiene que ser la misma, aunque el método cambie) ni puede cambiar la signatura (es decir la forma: el número y tipo de los parámetros) de la característica redefinida. Algunos lenguajes de POO permiten que la redefinición restrinja el tipo de los parámetros (que sea por ejemplo un subrango).

Clases Abstractas

Una clase abstracta es una clase que no tiene instancias directas pero cuyas clases descendientes (clases concretas) sí pueden tener instancias directas. Una clase concreta puede tener subclases abstractas, pero éstas han de tener subclases concretas (las hojas de una jerarquía de clases han de ser clases concretas).

Las clases abstractas organizan características comunes a varias clases. A veces es útil crear una superclase abstracta que encapsule aquellas características (atributos, operaciones y asociaciones) comunes a un conjunto de clases. Puede ser que esta clase abstracta aparezca en el dominio del problema o bien que se introduzca artificialmente para facilitar la reutilización de código.

Normalmente las clases abstractas se usan para definir métodos que son heredados por sus subclases. Sin embargo, una clase abstracta puede definir el protocolo de una determinada operación sin proporcionar el correspondiente método. Esto de denomina operación abstracta, que define la forma de una operación para la que cada subclase concreta debe suministrar su propia implementación. Una clase concreta no puede tener operaciones abstractas porque los objetos de esta clase tendrían operaciones indefinidas. Para indicar que una operación es abstracta se coloca una restricción {abstracta} junto a ella.

Herencia múltiple

La herencia múltiple permite a una clase tener más de una superclase, y así heredar las características de todos sus padres. Esto complica las jerarquías de herencia, que dejan de ser árboles para convertirse en grafos. La gran ventaja de la herencia múltiple es el incremento en las posibilidades de reutilización. El inconveniente es la pérdida de simplicidad conceptual y de implementación.

La herencia múltiple presenta dos problemas: conflictos y herencia repetida. Cuando una clase hereda simultáneamente sus propiedades de varias clases, pueden existir en estas propiedades representadas por el mismo identificador con significados diferentes; a esto se le denomina conflicto. Los conflictos que provoca la herencia múltiple se agravan en presencia de situaciones en las que una clase es heredada por otra por medio de caminos distintos; es lo que se denomina herencia repetida.

Existen muchas propuestas para resolver este tipo de problemas, casi tantas como lenguajes orientados a objetos. Podemos encontrar desde sistemas que dejan al usuario su resolución (algunas versiones de Smalltalk), hasta los que prohiben situaciones conflictivas (C++, Eiffel), pasando por sistemas que usan algún heurístico linealizando el árbol de herencia (CommonLoops), o los que simplemente evitan el problema impidiendo la herencia múltiple (Java). Las ventajas e inconvenientes de las posibles alternativas de la herencia múltiple se han estudiado con cierta profundidad, llegando a la conclusión de que cada alternativa tiene razones a favor y en contra, lo que impide tomar decisiones de diseño que satisfagan todo tipo de exigencias. En la mayoría de los casos, la interpretación que se da a la herencia múltiple depende más de su adecuación a la implementación que a otros motivos.

5.4.4. Consejos prácticos.

Por último, una serie de consejos prácticos para realizar modelos de objetos. Muchos de estos consejos son muy similares a los de los métodos estructurados: lo importante de una notación gráfica es que represente de forma correcta y clara el dominio de aplicación.

  • No lanzarse a dibujar clases y asociaciones sin sentido. Primero hay que entender el problema. Los métodos y herramientas no hacen análisis, el análisis lo hacemos nosotros ayudándonos con estos métodos y herramientas.

  • Intentar que el modelo sea simple, evitando complicaciones innecesarias. De lo que se trata es de que el modelo sea claro, que alguien más pueda entenderlo, aceptarlo o criticarlo.

  • Los nombres de objetos, asociaciones, atributos y operaciones deben ser significativos. Antes de poner un nombre hay que pensárselo un poco: el nombre representa al elemento. Las clases deben nombrarse con sustantivos y las asociaciones con verbos. Por las asociaciones se envían mensajes, pero no objetos. Un nombre largo puede ser más significativo pero no será más claro.

  • No incluir en los objetos punteros a otros objetos. Esto sólo sirve para que las relaciones entre objetos queden ocultas. Hay que modelar estas relaciones mediante asociaciones. Los punteros es como implementan algunos lenguajes las asociaciones, pero nuestro modelo debe ser independiente de la implementación.

  • Utilizar, si es posible, asociaciones binarias. Las asociaciones de orden superior son más difíciles de nombrar, entender e implementar. De todas formas hay asociaciones que no podemos descomponer en binarias sin perder información.

  • Dejar la definición de la multiplicidad para cuando se tenga un mejor conocimiento del problema. Pero no hay que olvidarse de ella. No hay que abusar de la multiplicidad 1/M o M/M pues, aunque sea más general la implementación es menos eficiente. Por otra parte, hay que tener cuidado con la multiplicidad 1/1. En muchos casos se trata de multiplicidad opcional (es decir, 1/0-1). La multiplicidad 1/1 implica que los objetos conectados no pueden existir de forma independiente, sino sólo por pares. Normalmente esta consideración es excesivamente estricta y puede llevarnos a perder información).

  • No incluir los atributos de las asociaciones en las clases. Aunque las asociaciones sin atributos son más sencillas, el hacer esto limita la flexibilidad del modelo.

  • Utilizar preferentemente asociaciones calificadas en vez de ternarias o con atributos. Proporcionan una información más exacta del dominio de aplicación.

  • Evitar las jerarquías de composición o generalización de muchos niveles. Dificultan la legibilidad del modelo.

  • Revisar el modelo hasta que sea satisfactorio. No podemos pretender que la primera versión sea correcta. Es conveniente mostrar el modelo a otras personas (no en el examen).

  • Documentar el modelo. Una imagen vale más que mil palabras, pero una imagen con texto es siempre mucho más explicativa que otra sin él.

  • Utilizar sólo los elementos necesarios. No se trata de lucirse y mostrar que se dominan todos los conceptos del modelo, sino de que el modelo sea correcto y claro.

5.5. Modelo dinámico.

5.5.1. Diagramas de estados.

El modelo dinámico del método OMT se corresponde con el modelo de control o modelo de comportamiento de las técnicas de análisis estructurado. En ambos casos, el modelo se representa mediante DEs, pero en el caso de OMT estos DEs se utilizan para modelar el comportamiento de cada clase de objetos, es decir, para modelar el comportamiento común a todas las instancias de una clase.

Al igual que todas las instancias de una clase comparten atributos, pero tienen valores particulares para esos atributos, todas las instancias de una clase se comportan de igual forma, pero pueden encontrarse en estados distintos.

Los elementos que figuran en un DE ya son conocidos, aquí sólo vamos a referirnos a las diferencias con respecto al análisis estructurado.

Estados y eventos.

Por estado de un objeto entendemos los valores de los atributos y los enlaces que mantiene un objeto en un momento determinado. Los objetos interactúan unos con otros y como consecuencia de esas interacciones cambian de estado (es decir, cambian el valor de sus atributos o sus enlaces con otros objetos).

Los estados que figuran en los DEs son abstracciones de los valores de los atributos y enlaces de un objeto, es decir, engloban conjuntos de valores de los atributos, de forma que muestran situaciones en las que el objeto presenta un determinado comportamiento. Por ejemplo, en el objeto Cuenta Corriente, el estado En rojos engloba todos los estados del objeto en los que el saldo es negativo.

Al definir los estados, debemos ignorar los atributos que no afectan al comportamiento del objeto y agrupar todas las combinaciones de valores de atributos y enlaces en las que el objeto presente el mismo comportamiento.

La interacción entre objetos se realiza mediante eventos. Como consecuencia de (la recepción de) un evento, un objeto puede realizar una serie de acciones y/o enviar eventos a otros objetos y/o cambiar de estado. Los eventos son el método de intercambiar información entre los objetos. Esta información consistirá en la mayoría de los casos en una señal lógica, pero en otros puede tratarse de información más compleja, y el evento tendrá una serie de atributos:

cancelar evento lógico

retirar(numero de cuenta, 5000) evento con atributos

La respuesta de un objeto en un estado determinado ante un evento determinado puede depender de los valores exactos de los atributos, pero sólo cuantitativamente. Cualitativamente, la respuesta será la misma para todos los objetos que se encuentren en ese estado.

La relación o secuencia de estados, eventos, transiciones y acciones se representa en los DEs. El modelo dinámico es un conjunto de DEs, uno para cada clase de objetos que tenga un comportamiento dinámico no trivial (no es necesario hacer un DE para cada clase sino sólo para aquéllas que lo precisen). La relación entre los distintos DEs se establece mediante los eventos que emiten unos objetos y consumen otros (se emiten en un determinado DE y se consumen en otro).

Guardas.

La encapsulación propia del paradigma OO impide con carácter general el acceso directo a valores de los atributos de otros objetos. Por este motivo una guarda es una condición que se define sobre los atributos propios de un objeto . Al recibir un evento, la transición etiquetada con dicho evento se dispara si y sólo si se satisface la guarda.

Actividades y acciones.

Las actividades y las acciones son las respuestas que tiene que dar un objeto ante los eventos que se producen en el exterior o las guardas (condiciones de datos) que se satisfacen internamente. Típicamente, las acciones y las actividades van a ser operaciones definidas en la clase a la que pertenece el objeto, aunque en ocasiones las acciones pueden consistir en enviar un mensaje a otro objeto.

Como ya sabemos, una actividad es una operación que necesita un tiempo para completarse, y se corresponde siempre con la ejecución de un determinado método o con el objeto inactivo, esperando a que se cumplan determinadas condiciones. Cuando un objeto entra en un estado, ejecuta la actividad correspondiente hasta que ésta finalice o bien hasta que el disparo de una transición nos haga abandonar dicho estado.

Por el contrario, una acción es una operación instantánea, que idealmente no necesita tiempo para realizarse y que se asocia, por tanto, al disparo de una determinada transición. Las acciones generalmente consisten en asignar valores a los atributos del objeto o en generar eventos para que sean tratados por otro proceso (con la notación enviar: evento). Por este motivo, las acciones no suelen corresponderse con operaciones del objeto, sino posiblemente con parte del código de ciertas operaciones.

Trazas de eventos.

Los eventos son el medio que utilizan los objetos para comunicarse entre sí. Podemos representar la secuencia de eventos que se ha producido entre los objetos de un determinado sistema mediante una traza de eventos. Esta traza es un diagrama que muestra la secuencia de envíos y recepciones de eventos entre varios objetos.

Las trazas de eventos son útiles para mostrar cómo un sistema ha llegado a un escenario determinado, y se mostrarían entonces junto con el diagrama de instancias que represente ese escenario, pero también son útiles para construir el modelo dinámico del sistema, pues muestran una secuencia lógica de eventos que podemos utilizar para realizar los DE de cada clase. A partir de varias trazas de eventos podemos construir el DE de una clase.

Cambiando el punto de vista, un diagrama de estados nos permite determinar la secuencia de estados por los que pasa un objeto a partir de una traza de eventos. Si el evento recibido figura en alguna de las transiciones que salen del estado, entonces la transición se dispara y el objeto pasa al estado de llegada de la transición.

5.5.2. Composición en los DEs.

Una de las características del paradigma OO es la definición de objetos componiendo otros objetos. El DE de un objeto compuesto estará formado por la unión de los DEs de cada uno de los objetos que lo componen. Cada uno de los objetos estará en un estado determinado, por lo que el estado del objeto compuesto estará representado mediante una tupla que contiene cada uno de los estados de los componentes. Es decir, los objetos compuestos tienen estados compuestos.

Esta posibilidad nos permite describir la concurrencia, no sólo en los objetos compuestos, sino en cualquier objeto. Podemos descomponer un objeto simple en varias partes, cada una que contiene un subconjunto de sus atributos y enlaces, y realizar un DE para cada uno de esos subconjuntos. Al igual que antes, el estado del objeto vendrá representado por la composición de estos DEs. Cada uno de los componentes de un objeto modelado mediante un DE compuesto evoluciona de forma concurrente al resto.

En algunos casos, podemos necesitar mostrar la concurrencia entre las actividades que se realizan dentro de un estado. Podemos encontrarnos con un estado en el que la actividad a realizar pueda ser descompuesta en una serie de pasos concurrentes. En este caso dividiremos el estado en dos (o más) subestados concurrentes.

Ejemplo: Las operaciones Expulsar Dinero y Devolver Tarjeta del cajero automático.

La sincronización de las transiciones de salida de cada uno de los subestados se hace juntando estas transiciones para formar la transición de salida del objeto compuesto.

5.5.3. Generalización en los DEs.

Generalización de estados.

Puede ocurrir que el objeto tenga un comportamiento tan complejo que el DE que lo modele sea demasiado grande y difícil de leer. En estos casos, podemos hacer DEs anidados, en los que un estado del DE padre se corresponda con un DE hijo. En este DE hijo se detalla el estado padre en una secuencia de estados, transiciones, acciones y actividades. Esta forma de anidamiento es similar al anidamiento que se producía en los DEs del análisis estructurado.

Podemos utilizar esta posibilidad en el caso de que la actividad que se asocie a un estado pueda ser descompuesta en una serie de operaciones secuenciales. En el DE hijo representaremos cada una de estas operaciones en un nuevo estado. Las transiciones que entran y salen del estado padre deben figurar en los estados iniciales y finales del DE hijo.

Alternativamente, podemos utilizar el anidamiento de estados para representar las transiciones comunes a una serie de estados, al igual que hacíamos en el análisis estructurado. Cada estado anidado o subestado comparte las transiciones de salida del estado padre o superestado, por otra parte las transiciones que entran en el padre nos llevan al estado inicial del DE anidado.

Cuando un objeto esté en un superestado, habrá de estar necesariamente en uno y sólo en uno de los subestados correspondientes.

Generalización de eventos.

Al igual que los estados también podemos generalizar los eventos. Podemos agrupar los eventos en clases hasta conseguir una jerarquía de eventos, lo que nos permite utilizar diferentes grados de abstracción en diferentes partes del modelo.

5.5.5. Herencia de DEs.

Según hemos dicho a cada clase del modelo de objetos se asocia un DE que modela su comportamiento, pero ¿qué sucede cuando dos clases están relacionadas mediante generalización? Entre las propiedades que se heredan de la clase padre está también el comportamiento, por lo que las subclases heredan el DE de la superclase.

Es posible que la subclase añada atributos u operaciones con respecto a la superclase. Entonces podemos considerar el DE de la subclase como la composición del DE de la superclase con el/los DEs que modelen el comportamiento del objeto con respecto a los nuevos atributos, al igual que hacíamos con los objetos compuestos.

En otros casos, la especialización del DE consistirá en el refinamiento de alguno de los estados del DE de la superclase, descomponiendo este estado en el DE de la subclase. Esto se corresponde con una división más detallada del espacio de estados heredado (el conjunto de valores de los atributos heredados).

En cualquier caso existe la posibilidad de conflicto: si la subclase redefine el comportamiento de los objetos respecto a alguno de los atributos heredados. No se pueden incluir transiciones o estados nuevos en el DE heredado puesto que entonces no habría una correspondencia entre ambos DEs. Estas situaciones, en las que las clases herederas modifican tienen un comportamiento distinto al de la clase padre y no es posible establecer una correspondencia entre ambos, son bastante frecuentes en la práctica. En estos casos no podemos hablar de herencia del DE sino de una redefinición completa del mismo. Esto es una limitación del modelo que no está resuelta y que contrasta con las posibilidades de redefinición de operaciones y atributos al especializar una clase. Esta limitación puede presentarse también cuando el comportamiento relacionado con los atributos nuevos definidos en la clase hija no puede modelarse de forma independiente a los heredados, sino que requiera realizarse de forma conjunta.

5.5.6. Modelo dinámico: consejos prácticos.

  • No todas las clases necesitan un DE. Sólo haremos DEs para aquellas clases que lo necesiten. Habrá clases cuyo comportamiento sea trivial, por ejemplo aquéllas clases que cuyo comportamiento sea siempre igual, es decir, que posean un único estado.

  • Utilizar trazas de eventos como ayuda para construir el DE. Las trazas de eventos describen una secuencia lógica de eventos en el sistema. Podemos utilizarlas para construir el esqueleto del DE, empezando por la secuencia de operaciones más habitual en el sistema. Luego debemos ir ampliando para que contemple otras secuencias cada vez menos frecuentes, no olvidándonos de las secuencias de error.

  • Para definir estados, sólo hay que tener en cuenta los atributos que influyen en el comportamiento. Los estados se definen a partir de subconjuntos de valores de los atributos. Sólo consideraremos los atributos que influyen en el comportamiento (los nombres no) y agruparemos los valores de estos atributos en conjuntos de forma que los objetos que estén en un estado presenten un comportamiento común.

  • Decidir la granularidad de estados y eventos según las necesidades del modelo. Los estados se asocian a actividades, que normalmente pueden ser descompuestas en fases, con varios niveles de granularidad. Según esto podemos hacer también los DEs con distinto tamaño de grano. Escogeremos el más adecuado según las necesidades de la aplicación y el grado de detalle que le queramos dar al modelo.

  • Distinguir entre eventos y guardas. Los eventos son mensajes que utilizan los objetos para comunicarse. En los DEs los eventos que recibe un objeto aparecen en las transiciones e indican que transición se dispara cuando se recibe un evento. Las guardas son condiciones que se establecen sobre valores de los atributos del propio objeto del que estamos haciendo el DE.

  • Distinguir entre actividades y acciones. Las actividades son operaciones que tienen una duración, por lo que se representan en los estados. Las acciones son operaciones que (idealmente) se realizan instantáneamente, y se representan en las transiciones.

  • Utilizar diagramas anidados cuando una transición se aplique a varios estados. Esto nos permite reutilizar las transiciones aplicando los principios de generalización y especialización y la regla de herencia a los DEs.

En los diagramas anidados hay que tener en cuenta la consistencia, al menos de las transiciones de salida. Las transiciones de salida del estado padre deben figurar en alguno de los estados del DE hijo. Las de entrada no hace falta pues suponemos que el DE hijo comienza siempre por el estado inicial.

  • Realizar un DE compuesto si:

¡ Existen relaciones de composición entre los objetos. El DE del objeto compuesto estará formado por el conjunto de los DEs de los componentes. El estado de un objeto compuesto es una tupla, cuyos elementos son los estados de los objetos componentes.

¡ Existe concurrencia interna en el objeto. Si el objeto es concurrente (si puede o debe realizar varias acciones al mismo tiempo) podemos dividir los estados en subestados concurrentes, en cada uno de ellos se realiza una actividad.

¡ Podemos dividir el comportamiento en facetas independientes. Si el comportamiento presenta facetas que dependen de conjuntos disjuntos de atributos, podemos modelar este comportamiento mediante varios DEs, uno para cada conjunto. Estos DEs serán mucho más sencillos puesto que sólo van a manejar un subconjunto de los eventos, sin que tengamos que preocuparnos de definir transiciones para el resto.

¡ Existen relaciones de herencia entre los objetos. Si el objeto hijo define nuevos atributos, haremos un DE para definir el comportamiento según los valores de estos atributos nuevos. Si el objeto hijo descompone uno o más estados del padre, tendremos un DE anidado.

  • En caso de herencia de entre clases, el DE de la subclase no puede añadir estados o transiciones al DE padre. Como un objeto puede ser visto tanto como una instancia de la clase padre como una instancia de la clase hijo, debe existir una correspondencia entre los estados y transiciones de los DEs de ambas. Si añadimos un estado en el DE del hijo ya no existe esa correspondencia, y un objeto en ese nuevo estado, considerado como una instancia de la clase padre, estaría un estado indeterminado.

  • Comprobar la consistencia de los eventos que se generan en un DE y se utilizan en otros. Los eventos que se utilizan para disparar las transiciones de un DE deben ser generados por algún objeto. Los eventos que genera un objeto deben utilizarse en algún otro DE.

5.6. Modelo funcional.

El modelo funcional describe las computaciones que se realizan en un sistema, mostrando cómo se derivan los valores de salida a partir de los de entrada. El modelo funcional muestra cómo se realizan las operaciones del modelo de datos y las actividades acciones de los DEs.

La existencia de un modelo funcional basado en el uso de DFDs distingue OMT de otras metodologías de desarrollo orientado a objetos. Sin embargo, no podemos considerar esto como algo positivo de OMT puesto que no es fácil la adecuación del modelo de procesos del análisis estructurado al tipo de código existente en un sistema orientado a objetos. Por este motivo apenas se usa y, de hecho, escritos recientes de Rumbaugh descartan el uso de DFDs para representar el modelo funcional del sistema, optando, en su lugar, por incluir casos de uso, diagramas de interacción de objetos y especificaciones de operaciones similares a las PSPECs del análisis estructurado.

La especificación de una operación puede realizarse mediante precondiciones y postcondiciones. Una precondición indica suposiciones sobre el estado del sistema al comienzo de la operación. Una postcondición describe el estado del sistema una vez realizada la operación. Las precondiciones y postcondiciones pueden expresarse mediante algún lenguaje formal, aunque en la mayoría de los casos basta con utilizar lenguaje natural, siempre que el significado quede claro.

En general, la implementación de las operaciones puede derivarse del modelo de comportamiento durante el diseño del sistema. Sin embargo, durante el análisis, será necesario describir, al menos, las operaciones de aquéllas clases para las que no se ha realizado diagrama de estados.

La implementación de una operación puede invocar otras operaciones, pero esto es un aspecto de diseño y no de especificación. Para mostrar la colaboración entre distintos objetos a la hora de realizar una operación determinada podemos realizar un diagrama de interacción de objetos.

5.7. Relación entre los modelos.

El modelo de objetos describe la estructura de datos sobre la que operan los modelos funcional y dinámico. Las operaciones en el modelo de objetos se corresponden con las acciones y actividades del modelo dinámico y con los procesos del modelo funcional.

El modelo dinámico describe el control de los objetos. El DE describe el comportamiento de los objetos de una clase, mostrando secuencias válidas de cambios de comportamiento en las clases del modelo de objetos. Los estados son clases de equivalencia de los valores de atributos y enlaces del objeto, que normalmente se asocian a la ejecución de una determinada operación en el objeto. Los eventos aparecen también como operaciones en el modelo de objetos.

Un subestado refina los valores de atributos y enlaces que puede tener un objeto. Una jerarquía de estados de un objeto es equivalente a una jerarquía de restricciones sobre el objeto. Como los LOO no suelen permitir restricciones de valores sobre el tipo de los atributos heredados o los parámetros de las operaciones (no se puede cambiar la signatura, ni siquiera restringiéndola), el modelo dinámico es el sitio adecuado para representar estas restricciones.

En la mayoría de los LOO, las instancias no pueden cambiar la clase a la que pertenecen a lo largo de su vida, pero sí que pueden cambiar de estado. Por tanto, para modelar objetos que van a estar sujetos a restricciones cambiantes, modelaremos estas restricciones como estados en lugar de como clases.

Las jerarquías de objetos y de eventos son totalmente independientes. Los eventos sirven para intercambiar información entre objetos de clases distintas. Las transiciones se suelen representar mediante operaciones, cuyo nombre es el evento que dispara la transición.

El modelo funcional describe funciones invocadas por operaciones en el modelo de objetos o acciones y actividades en el modelo dinámico. Las funciones operan sobre los valores de datos especificados en el modelo de objetos. El modelo de objetos muestra las entidades que realizan o padecen las funciones. El modelo dinámico muestra la secuencia en la que se realizan las funciones.

En resumen:

  • Relaciones con el modelo de objetos.

El modelo funcional muestra las operaciones que se realizan en cada clase y los argumentos de estas operaciones. El modelo dinámico muestra los estados de cada objeto y las operaciones que éstos realizan al recibir eventos y cambiar de estado.

  • Relaciones con el modelo dinámico.

El modelo funcional muestra las definiciones de las acciones y actividades del modelo dinámico. El modelo de objetos muestra los objetos que sufren o realizan las acciones y actividades del modelo dinámico.

  • Relaciones con el modelo funcional.

El modelo de objetos muestra las entidades que realizan o padecen las funciones del modelo funcional. El modelo dinámico muestra la secuencia en que se realizan las funciones del modelo funcional.

5.8. Método de análisis.

El objetivo del AOO es modelar el mundo real, de forma que pueda ser entendido. Es necesario abstraer las características importantes del problema en primer lugar, dejando los detalles para más adelante. Un buen modelo de análisis debe indicar lo que hay que hacer, sin restringir cómo hay que hacerlo, evitando tomar anticipadamente decisiones de implementación.

El modelo de análisis se compone del modelo de objetos, que representa la estructura estática de la información, el modelo dinámico, que indica la secuencia de eventos, y el modelo funcional, que muestra las transformaciones de datos. No todos ellos tienen la misma importancia, y la necesidad de desarrollar cada uno de ellos depende del dominio del problema. Habrá casos en que no sea necesario realizar el modelo dinámico o el funcional. El modelo de objetos siempre es necesario si vamos a hacer AOO.

El análisis no es una actividad secuencial, sino que los modelos se construyen de forma iterativa, añadiendo nuevas características o modificando el modelo según se refinan los requisitos y también a partir del conocimiento del dominio de aplicación obtenido al construir cada uno de los modelos.

Estrictamente, podemos dividir la etapa de análisis dentro de la metodología OMT en tres fases: modelo de objetos, modelo dinámico y modelo funcional. Sin embargo, si consideramos la fase inicial de conceptualización, debemos incluir también los casos de uso.

5.8.1. Casos de uso.

Los casos de uso describen las distintas formas de utilizar el sistema, visto desde su exterior, es decir, desde el punto de vista del usuario. Para realizar los diagramas de casos de uso se puede proceder como se describe a continuación:

  • Establecer los límites del sistema. Hay que determinar qué objetos forman parte del sistema, qué objetos interactúan con él y cuáles no. Los casos de uso consideran el sistema como una caja negra, es decir, no entran a describir su estructura interna.

  • Determinar los actores que interactúan con el sistema. Un actor es un rol o papel que juega un objeto externo en su relación con el sistema. Para determinar los actores debemos observar los objetos físicos que interactúan con el sistema, que en muchos casos juegan múltiples roles. Por ejemplo, una misma persona puede ser Usuario, Operador y Administrador de un cierto sistema. Cada rol es un actor diferente.

  • Para cada actor, determinar las diferentes formas en las que usa el sistema. Por cada una de esas formas tendremos un caso de uso.

No debería haber demasiados casos de uso en un sistema. Entre 5 y 10 casos bastan normalmente para mostrar los usos principales del sistema. Si no es así, es necesario utilizar un menor nivel de detalle. En cada caso de uso se debe escoger un nivel de detalle similar.

  • Identificar el evento inicial que comienza el caso de uso.

  • Determinar la condición de terminación que finaliza el caso de uso. A menudo un caso de uso puede ser descrito con diferentes niveles de detalle.

  • Describir la situación típica en la que ocurre el caso de uso. Si hay variaciones o excepciones, es necesario describirlas también. Basta con utilizar lenguaje natural, un caso de uso no necesita ser demasiado formal.

5.8.2. Modelo de objetos.

Empezaremos a modelar el sistema realizando su modelo de objetos. Este modelo muestra la estructura estática de los datos del mundo real y las relaciones entre estos datos. El modelo de objetos precede normalmente al dinámico y al funcional porque normalmente está mejor definido en la especificación preliminar, es menos dependiente de detalles de la aplicación, es más estable respecto a la evolución de la solución y es más fácil de entender que el resto.

Los pasos a seguir son los siguientes:

Identificar objetos y clases.

Durante el proceso de desarrollo aparecen tres categorías de objetos: objetos del dominio, objetos de aplicación y objetos internos.

Los objetos del dominio son significativos desde el punto de vista del dominio del problema. Existen de forma independiente a la aplicación y tienen sentido para los expertos del dominio.

Los objetos de aplicación representan aspectos computacionales de la aplicación que son visibles para los usuarios. No existen en el espacio del problema, solo tienen sentido en el contexto de la aplicación que vamos a desarrollar para solucionarlo. Sin embargo, no dependen exclusivamente de decisiones de diseño, puesto que son visibles al usuario y no pueden ser cambiados sin alterar la especificación de la aplicación. No pueden obtenerse analizando el dominio de la aplicación, pero sí pueden ser reutilizados de aplicaciones anteriores, incluso aunque sean de diferente dominio. Los objetos de aplicación incluyen controladores, dispositivos e interfaces.

Los objetos internos son componentes de la aplicación que resultan invisibles para el usuario. Su existencia se deriva de decisiones de diseño para implementar el sistema. No deben aparecer durante el análisis. Una parte importante del diseño consiste en añadir objetos internos para hacer factible la implementación del sistema.

Por tanto, en el modelo de objetos figurarán tanto objetos del dominio como objetos de aplicación. Su construcción puede ser realizada en dos fases:

En una primera fase podemos construir un modelo que represente los objetos del dominio del problema y las relaciones que existen entre ellos. Este modelo equivale a lo que se llama modelo esencial en la terminología del análisis estructurado.

En una segunda fase podemos construir un modelo de aplicación, completando el modelo anterior con objetos de aplicación. Para esto jugarán un papel muy importante los casos de uso desarrollados durante la conceptualización del problema.

Los objetos del modelo pueden ser tanto entidades físicas (como personas, casas y máquinas) como conceptos (como órdenes de compra, reservas de asientos o trayectorias). En cualquier caso, todas las clases deben ser significativas en el dominio de aplicación. Hay que evitar definir clases que se refieren a necesidades de implementación como listas, subrutinas o el reloj del sistema. No todas las clases figuran explícitamente en la especificación preliminar, algunas están implícitas en el dominio de aplicación o son de conocimiento general.

Podemos empezar haciendo una lista de clases candidatas a partir de la especificación preliminar. Normalmente las clases se corresponden con nombres en este documento. No hay que preocuparse aún de establecer relaciones de generalización/especialización entre las clases. Esto se hace para reutilizar código y estas relaciones aparecen más claramente cuando se definan atributos y operaciones.

Una vez que tenemos una lista de clases candidatas hay que proceder a revisarla, eliminando las incorrectas, siguiendo los siguientes criterios:

  • Clases redundantes. Si dos clases representan la misma información nos quedaremos con la que tenga un nombre más significativa, eliminando la otra. (p. ej. Cliente y Usuario).

  • Clases irrelevantes. Podemos haber incluido clases que sean importantes en el dominio de aplicación, pero que sean irrelevantes en el sistema que pretendemos implementar. Esto depende mucho del problema concreto.

  • Clases demasiado generales. Las clases deben ser específicas. Deben tener unos límites claros y unos atributos y un comportamiento comunes para todas las instancias. Debemos eliminar las clases demasiado generales, normalmente creando otras más específicas. Las clases genéricas se incluirán más adelante si es necesario, al observar atributos u operaciones comunes a varias clases.

  • Atributos. Los nombres que describen propiedades de los objetos son atributos, no clases. Una de las características de un objeto es su identidad (aún cuando los valores de los atributos sean comunes), y otra muy común es su existencia independiente. Los atributos de un objeto no presentan estas dos propiedades. Si la existencia independiente de un atributo es importante, hay que modelarlo como una clase. (P. ej. podemos considerar el Despacho, como un atributo de la clase Empleado, pero esto nos impide hacer una reasignación de despachos, por lo que, si queremos implementar esta operación, deberemos considerar los despachos como objetos en lugar de como atributos).

  • Operaciones. Una clase no puede ser una operación que se aplique sobre los objetos sin tener independencia por sí misma (p. ej. en nuestro modelo de la línea telefónica la Llamada es una operación, no una clase). Sin embargo, esto depende del dominio de aplicación: en una aplicación de facturación telefónica, la Llamada será una clase que contiene atributos tales como Origen, Destino, Fecha, Hora y Número de Pasos.

  • Roles. El nombre de una clase debe depender de su naturaleza intrínseca y no del papel que juegue en el sistema. Podemos agrupar varias clases en una, si intrínsecamente son lo mismo, y luego distinguir estos roles en las asociaciones. (P. ej. La clase Persona puede jugar varios papeles (Propietario, Conductor, etc.) en relación con la clase Vehículo. En otros casos, una misma entidad física puede modelarse mediante varias clases distintas si los atributos y el comportamiento (y especialmente las instancias) son distintos dependiendo del papel que juegue en el sistema.

  • Objetos internos. No debemos incluir en el la fase de análisis clases que no se corresponden con el dominio de aplicación sino que tienen relación con la implementación del sistema.

Una vez identificadas las clases debemos empezar a preparar el diccionario de datos del sistema. Cada clase figurará como una entrada en el diccionario donde se define brevemente su significado y las funciones que realiza. El diccionario de datos también contiene entradas para las asociaciones, las operaciones y los atributos, que deben ser definidos según las vamos incorporando al modelo.

Identificar asociaciones (incluyendo las de composición) entre los objetos.

Cualquier relación entre dos o más clases debe ser modelada como una asociación. No hay que incluir en las clases punteros o atributos que se refieran a objetos de otras clases. Todas estas relaciones deben modelarse como asociaciones para que quede constancia de ellas en el modelo de objetos.

Las relaciones de composición también son asociaciones, simplemente tienen unas características particulares. Hay que distinguir entre unas y otras pero no merece la pena discutir mucho sobre ello.

Una vez identificadas las asociaciones candidatas, procederemos a revisar esta lista, eliminado algunas según los siguientes criterios:

  • Asociaciones irrelevantes y de implementación. Hay que eliminar todas las asociaciones que, a pesar de que existan en el muno real, no sean relevantes para el sistema. Lo mismo sucede con las asociaciones cuya existencia se base en la implementación de la solución. Las asociaciones del modelo de objetos deben tener existencia real y ser relevantes para la solución del problema.

  • Acciones. Las asociaciones deben describir relaciones estructurales entre las clases. Existen otros tipos de relaciones, (por ejemplo cuando un objeto recibe otro como parámetro en un mensaje que invoca una acción), que no figuran normalmente como relaciones en el modelo de objetos.

  • Asociaciones no binarias. La mayor parte de las relaciones entre más de dos clases pueden ser expresadas mediante asociaciones binarias o con atributos (si uno de los términos no tiene existencia propia sino siempre ligada a la asociación), pero en algunos casos no podemos hacer esto sin perder información. Hasta el momento no se a mostrado como necesaria ninguna asociación entre cuatro o más clases.

  • Asociaciones derivadas. Hay que eliminar las asociaciones que puedan ser expresadas a partir de otras (p. ej. la asociación Abuelo). La existencia de caminos múltiples entre dos clases suele indicar que existen asociaciones derivadas que pueden ser eliminadas, pero en algunos casos los caminos múltiples son necesarios.

Una vez revisada la lista, procederemos a completar el modelo de objetos, indicando para cada asociación que lo necesite:

  • Roles. Los roles o papeles son muy útiles cuando hay asociaciones entre la misma clase o hay varias asociaciones entre un par de clases. El rol describe el papel que juega un objeto en la relación desde el punto de vista de la otra clase. (P. ej. Persona (empleado) trabaja para (contratante) Empresa.

  • Calificadores. Normalmente los nombres sirven para identificar los objetos dentro de un contexto. De esta forma, un atributo puede servir para identificar entre las múltiples instancias conectadas al extremo M de una asociación, reduciendo así la multiplicidad de la relación.

  • Multiplicidad. Es necesario especificar la multiplicidad, pero no hay que obsesionarse mucho pues cambia con frecuencia a lo largo del análisis. Una vez que el modelo esté completo hay que revisar las conexiones con multiplicidad 1 (que suelen ser opcionales) y las de multiplicidad M, para ver si realmente son necesarias.

  • Ordenación y otras restricciones.

Identificar atributos y operaciones.

El siguiente paso es identificar los atributos y operaciones de cada clase y de los enlaces que los contengan. Los atributos describen propiedades de los objetos, tales como peso, color o edad, pero no son objetos. Cualquier relación entre objetos debe ser modelada como una asociación, no como un atributo de los objetos relacionados. Tampoco hay que incluir como atributos de los objetos los calificadores de las asociaciones ni los atributos de los enlaces.

Con frecuencia los atributos no figuran en la especificación preliminar. Lo normal es partir de un conjunto básico de atributos para cada objeto e ir añadiendo otros según los vayamos necesitando.

Organizar y simplificar las clases mediante relaciones de generalización y especialización.

El paso siguiente es organizar las clases en jerarquías de forma que se puedan abstraer las características comunes. Esto puede hacerse en dos direcciones:

  • Hacia arriba (generalización), abstrayendo propiedades (atributos y relaciones) comunes a un grupo de clases en una superclase que las generalice. Muchas relaciones de generalización se corresponden con clasificaciones (taxonomías) de los objetos en el mundo real.

  • Hacia abajo (especialización), refinando las clases existentes en subclases especializadas. Estas relaciones de especialización suelen aparecer en la especificación preliminar en forma de nombres adjetivados: lámpara incandescente, lampara fluorescente, etc.

Aunque la herencia facilita la reutilización de código, hay que evitar abusar demasiado de estas relaciones. Aplicaremos la especialización sólo cuando sea necesario, es decir, cuando la distinción entre dos clases especializadas sea significativa para el problema. Esto sucederá cuando ambas clases tengan atributos o operaciones distintos.

Verificar los caminos de acceso.

A continuación hay que comprobar los caminos de acceso en el modelo de objetos. Se trata de comprobar si todas las asociaciones necesarias están presentes en el diagrama, de forma que se pueda hacer un recorrido entre los objetos relacionados. También hay que comprobar la multiplicidad: para relaciones con multiplicidad M, ¿es necesario acceder a las instancias relacionadas de forma individualizada? ¿existe algún mecanismo para hacerlo?, ¿existe un camino para contestar todas las preguntas útiles acerca del problema.? (p. ej. ¿cuáles son las casas de una persona?, ¿a quién le ha comprado esta persona cada casa?, ¿cuándo se realizó la escritura?).

Refinar el modelo iterativamente.

Es muy difícil que el modelo de objetos nos salga bien a la primera. El desarrollo de software sigue normalmente un proceso iterativo: podemos encontrar errores o mejoras en nuestro modelo de objetos, no sólo mientras lo estamos haciendo, sino al hacer el modelo funcional, el dinámico o incluso en las fases de diseño o implementación. Nuestro objetivo es encontrar los errores lo antes posible, especialmente antes de entregar el software al cliente (pérdida de imagen) y antes de implementar los programas (pérdida de tiempo en codificación y pruebas). Cuanto antes encontremos los errores más sencillo y baratos será corregirlos. Por ello hay que tener especial cuidado en la fase de análisis, revisando el modelo cuantas veces sea necesario, evitando especialmente la disparidad con los modelos dinámico y funcional.

5.8.3. Modelo dinámico.

El modelo dinámico muestra el comportamiento de los objetos del modelo de objetos. Podemos empezar estableciendo una lista de los eventos que afectan al sistema, y establecer una o varias trazas de eventos que muestren secuencias normales de estos eventos. Luego estableceremos las secuencias de eventos permitidas para cada clase de objetos, a partir de las cuales podemos realizar los DEs.

  • Establecer una lista de posibles eventos. Para ello partimos, como siempre, de la especificación preliminar. Hay que identificar también el objeto que emite el evento (algunos eventos provienen del entorno del sistema), el que lo recibe, y los parámetros que pudiese tener. Podemos agrupar los eventos en clases, especialmente cuando tienen parámetros o para poder utilizarlos con diferentes grados de abstracción.

  • Eliminar de la lista de eventos las operaciones que no afecten al estado de un objeto. Los objetos reciben mensajes indicando que deben realizar alguna de las operaciones que tienen definidas, pero muchas de estas operaciones no cambiarán el estado del objeto (el objeto se comportará igual después de realizar la operación), por tanto no consideraremos estas órdenes o peticiones como eventos.

  • Realizar varias trazas de eventos. En cada traza mostraremos una secuencia lógica de eventos junto con los objetos que los emiten y reciben. Podemos empezar haciendo trazas de los casos más habituales de funcionamiento del sistema, luego haremos trazas para situaciones menos corrientes pero igualmente válidas y acabaremos haciendo trazas para determinar el comportamiento del sistema ante situaciones erróneas. El control de errores suele ser la parte más difícil del modelo dinámico de una sistema interactivo. Hay que prever todas las situaciones posibles (incluyendo timeouts para las comunicaciones o las peticiones de datos al usuario) y permitir la corrección de cualquier entrada de datos, definiendo claramente mecanismos de vuelta atrás.

  • Construir un DE para cada clase de objetos que presente estados distintos. Sólo consideraremos los objetos que puedan presentar varios estados, es decir, que se comporten de manera distinta según valores distintos de sus atributos. Para cada una de estas clases iremos tomando las trazas donde aparece, empezando de las más habituales a las más específicas. Cada traza se corresponderá con una secuencia de transiciones en el DE. Cada vez que reciba un evento, un objeto cambiará (posiblemente) de estado, estableciendo un valor nuevo para alguno de sus atributos. Revisaremos cada DE para ver si esta completo (si se han considerado todas las transiciones) y para determinar si los estados finales son efectivamente tales.

  • Verificar la consistencia de los eventos entre los diferentes DEs. Hay que verificar la completitud y consistencia de los eventos a nivel de todo el sistema. Los eventos que emite un objeto deben ser recibidos por algún otro. Podemos completar el modelo dinámico dibujando uno o varios diagramas de interacción de objetos, que nos muestren las relaciones entre las distintas clases del sistema basadas en intercambio de eventos.

5.8.4. Modelo funcional.

El modelo funcional muestra cómo se calculan valores, independientemente de cuándo se realizan esos cálculos o de la estructura de los objetos que almacenan esos valores. Lo que muestra el modelo funcional es las relaciones de dependencia de datos y dependencia funcional.

Normalmente, la aplicación del paradigma orientado a objetos lleva a una mayor fragmentación del código que los métodos estructurados: los métodos tienen una implementación breve, basada normalmente en la llamada a otros métodos de objetos relacionados. Por este motivo, podemos describir la mayoría de los métodos como primitivas de proceso, o mediante diagramas de interacción, siendo raro el caso en el sea útil describir una determinada operación mediante un DFD.

El DE de cada clase contiene la mayor parte de la información necesaria para realizar el modelo funcional. Las acciones y actividades asociadas al disparo de una transición se corresponden con la especificación de la operación que figuran como evento en dicha transición. En caso de que un mismo evento figure en varias transiciones, la especificación contendrá las estructuras de control que permitan distinguir entre los diferentes estados.

 

reintegro (cantidad)

if saldo > 0

then

saldo = saldo - cantidad

else

error("En números rojos");

Si la especificación de una operación contiene invocaciones de operaciones (mediante envío de eventos) a otras clases, puede especificarse mediante diagramas de interacción. Por el contrario, si se trata de una operación exclusivamente interna, o si no se han realizado DE de la clase, la operación se puede especificar mediante una primitiva de proceso. Esta descripción puede hacerse en lenguaje natural, pseudocódigo, por medio de ecuaciones matemáticas o de tablas. La desventaja de hacerlo en lenguaje natural es que la ambigüedad es mayor, pudiendo presentarse problemas a la hora de implementar y que es más difícil comprobar su consistencia. Aunque utilicemos un algoritmo (pseudocódigo) para describir un proceso, el objetivo es especificar qué hace el proceso y no cómo lo hace. La elección definitiva del algoritmo depende de consideraciones adicionales que se establecen en las fases de diseño y de implementación.

La especificación de las operaciones debe incluir también cualquier restricción que se deba establecer sobre los datos del sistema, (por ejemplo, precondiciones y postcondiciones de los procesos), así como criterios de optimización que deban tenerse en cuenta en el diseño y la optimización.

5.8.5. Modelo de aplicación.

Una vez realizado el modelo del dominio, donde nos habremos centrado fundamentalmente en los objetos del dominio de aplicación, podemos completarlo, convirtiéndolo en un modelo de aplicación. Para ello nos serán de gran utilidad los casos de uso desarrollados junto con la especificación inicial.

En primer lugar hemos de determinar los límites del sistema, identificando lo que es parte del mismo y lo que son actores externos. Es posible que algunos objetos que aparecen en el modelo del dominio no formen realmente parte de la aplicación. Para determinarlo, debemos observar si es necesario guardar información sobre estos objetos o si vamos a implementar las operaciones que aparecen en ellos.

Por otro lado, el examen de los casos de uso nos permitirá determinar cuál es el acceso necesario para cada clase del dominio. Se pueden construir una o más vistas de cada clase del dominio para proporcionar estas distintas formas de acceso. Estas vistas deben añadirse al modelo de objetos, definiendo la traducción entre objetos del dominio y vistas.

Debemos identificar cuales son los eventos que se intercambian entre los actores y el sistema. Los periodos de tiempo entre eventos se definirán como estados. Incluiremos objetos controladores para controlar la secuencia de eventos en cada vista. Esto nos permitirá separar la relación estática entre objetos del dominio y vistas de la dinámica de las vistas.

A partir de los casos de uso también podremos determinar cuáles serán los comandos del sistema. Estos comandos serán peticiones que realizan los actores para que el sistema realice una determinada acción. Los comandos del sistema deben añadirse al modelo funcional como operaciones. Si no es posible asignar estas operaciones a ninguna de las clases existentes, la asignaremos a un controlador.

Por último debemos determinar las interfaces externas del sistema, incluyendo las interfaces con dispositivos externos, otros sistemas, etc. Es conveniente rodear los objetos de la aplicación de objetos interfaz que los aíslen y eviten dependencias de la aplicación respecto a estos sistemas externos.

5.8.6. Refinar el modelo.

Una vez que hemos desarrollado el modelo del sistema, nos quedan aún una serie de cosas por hacer:

Completar la lista de operaciones.

La primera de ellas es completar la lista de operaciones, dado que normalmente no es posible hacerlo al desarrollar el modelo de objetos, sino que van apareciendo a lo largo del análisis. Podemos clasificar las operaciones de los objetos en los siguientes grupos:

  • Operaciones implícitas sobre objetos. Normalmente, cualquier sistema debe ser capaz de crear, destruir y copiar instancias de las clases que define. Algunas de estas operaciones están, directa o indirectamente, descritas en la especificación preliminar, pero la mayor parte de las veces están implícitas. Los LOO suelen incluir primitivas de creación, destrucción y copia de las instancias de una clase.

  • Operaciones implícitas sobre atributos. Existe otro grupo de operaciones implícitas: las encargadas de consultar o asignar el valor de cada uno de los atributos de un objeto. Así mismo, deben existir operaciones que recorran los enlaces que una instancia tenga con otras. En la descripciones de primitivas de proceso podemos utilizar la notación siguiente, para referirnos a estas operaciones:

clase.atributo

operación de consulta que devuelve el valor del atributo.

clase.atributo := valor

operación de asignación.

clase.asociación

atributo que apunta al objeto asociado.

clase.asociación[i]

id. para asociaciones múltiples y ordenadas.

clase.asociación[calificador]

id. para asociaciones calificadas.

  • Operaciones invocadas por eventos. La recepción de un evento trae consigo la ejecución de una serie de operaciones (acciones y actividades) en el objeto que recibe el mensaje. Es habitual incluir en la clase receptora operaciones con mismo nombre que el evento que las desencadena, en las que se incluyen estas acciones y actividades.

  • Operaciones invocadas por acciones y actividades. Por el contrario, en algunos casos puede ser conveniente representar las propias acciones y/o actividades como operaciones de las clases. Se tratará en estos casos de operaciones auxiliares que se invocan a la recepción de los eventos correspondientes.

Una vez que hemos completado la lista de operaciones de cada clase, debemos comprobar estas listas con vistas a simplificar operaciones redundantes o a establecer relaciones de generalización entre clases que tengan una serie de operaciones comunes.

Comprobar la consistencia entre los modelos.

El proceso de análisis no es una actividad secuencial, sino que según vamos desarrollando un modelo surgen modificaciones de los anteriores. Una vez que tenemos los tres modelos hay que comprobar la consistencia, para ver si alguna de estas modificaciones se nos ha pasado por alto. Para comprobar la consistencia nos basaremos en las relaciones entre los modelos de las que ya hemos hablado.

Aunque el primer modelo que realicemos sea consistente, rara vez será correcto. Demos revisarlo para ver si se nos ha olvidado algo de lo establecido en la especificación preliminar o si notamos algo extraño.

Comprobar el modelo con el cliente.

Una vez que nosotros hemos dado el visto bueno al análisis, el cliente debe hacer lo mismo. En primer lugar debemos mostrarle los resultados del análisis para ver si son acordes con sus necesidades, o si hemos cometido algún error o se nos ha pasado por alto algún detalle. También debemos discutir con el las modificaciones que se hayan realizado con respecto a lo establecido en la especificación preliminar, para ver si las suposiciones que hemos hecho son correctas.

Deficiencias del análisis estructurado.

  • Descomposición funcional. Requiere traducir el sistema a una serie de funciones y subfunciones.

  • Flujo de datos. Es un modelo informático, no nuestra forma habitual de pensar.

  • Modelo de datos. La relación con el modelo de procesos es débil. Pueden dar visiones muy distintas del mismo problema.

Ventajas del análisis orientado a objetos.

  • Dominio del problema. Representa el sistema en términos del mundo real, en vez de en términos informáticos.

  • Comunicación. Usa conceptos más simples. La comunicación con el cliente es más fácil.

  • Consistencia. Reduce la distancia entre el modelo de procesos y el de datos.

  • Expresión de características comunes. Evita la duplicación de características comunes a varios elementos.

  • Resistencia al cambio. Al ser más próximo al sistema real es más estable frente a cambios en los requisitos.

  • Reutilización. Favorece la reutilización, tanto interna como externa.

Características del enfoque orientado a objetos.

Identidad.

  • Los elementos del dominio del problema se organizan en entidades discretas y distinguibles llamadas objetos.

  • Los objetos encapsulan atributos (datos) y operaciones.

  • Cada objeto tiene identidad propia, aunque los valores de sus atributos coincidan con los de otro.

Clasificación.

  • Los objetos con propiedades comunes se agrupan en clases.

  • Las clases son abstracciones de características comunes a una serie de objetos.

  • Las clases son arbitrarias: dependen del dominio del problema.

  • Cada uno de los objetos agrupados en una clase se llama instancia.

  • Las instancias de una clase comparten atributos, operaciones y comportamiento pero tienen valores distintos en los atributos.

Polimorfismo.

  • Una misma operación puede realizarse de formas distintas en clases distintas. La semántica es común pero la implementación varía en cada clase.

  • La implementación de una operación en una clase se denomina método.

Herencia.

  • Es una relación jerárquica entre clases con características comunes.

  • La clase padre define características comunes a todas las hijas.

  • Cada clase hija hereda las características del padre y las amplia o refina.

Elementos del modelo de objetos

Instancias. Cada uno de los objetos individuales.

Clases. Abstracción de objetos con propiedades comunes.

Atributos. Datos que caracterizan las instancias de una clase.

Operaciones. Funciones que pueden realizar las instancias.

Relaciones. Se establecen entre clases.

Asociación. Relación de uso en general.

Multiplicidad. Número de instancias que intervienen en la relación.

Atributos. Algunos atributos pueden depender de la asociación.

Calificación. Limita la multiplicidad de las asociaciones.

Roles. Indican los papeles de las clases en las relaciones.

Restricciones y ordenación.

Composición. Relaciones todo/parte.

Generalización. Relaciones padre/hijo.

Redefinición. Modificación de las propiedades heredadas.

Enlaces. Instancias de una relación. Relaciona instancias.

Modelo de objetos: consejos prácticos.

  • No lanzarse a dibujar clases y asociaciones sin sentido.

  • Intentar que el modelo sea simple, evitando complicaciones innecesarias.

  • Los nombres de objetos, asociaciones, atributos y operaciones deben ser significativos.

  • No incluir en los objetos punteros a otros objetos.

  • Utilizar, si es posible, asociaciones binarias.

  • Dejar la definición de la multiplicidad para cuando se tenga un mejor conocimiento del problema.

  • No incluir los atributos de las asociaciones en las clases.

  • Utilizar preferentemente asociaciones cualificadas en vez de ternarias o con atributos.

  • Evitar las jerarquías de composición o generalización de muchos niveles.

  • Revisar el modelo hasta que sea satisfactorio.

  • Documentar el modelo.

  • Utilizar sólo los elementos necesarios.

Modelo dinámico.

  • Estado de un objeto. Conjunto de valores de los atributos y enlaces que tiene un objeto en un momento determinado.

  • Diagrama de transición de estados. Diagrama que muestra la secuencia de estados, eventos y acciones de un objeto.

  • Modelo dinámico de un sistema. Conjunto de DEs de las clase de objetos del sistema.

  • Eventos. Señales mediante las que se comunican los objetos. Pueden ser señales lógicas o contener atributos.

  • Estado. Abstracción de los estados de un objeto en el que éste presenta determinado comportamiento. Engloba un conjunto de valores de los atributos y enlaces (un conjunto de estados del objeto).

  • Trazas de eventos. Diagrama que muestra la secuencia de envíos y recepciones de eventos entre varios objetos.

  • Guarda. Condición de datos que debe cumplir un objeto para que se dispare una transición al recibir un determinado evento. (Notación: [Guarda] ).

  • Actividad. Operación que necesita un tiempo para ejecutarse. Se representa en los estados. (Notación: Hacer: Actividad)

  • Acción. Operación que se realiza (idealmente) de forma instantánea. Se representa en las transiciones. (Notación: Evento [Guarda] / Acción).

Modelo dinámico: consejos prácticos.

  • No todas las clases necesitan un DE.

  • Utilizar trazas de eventos como ayuda para construir el DE.

  • Para definir estados, sólo hay que tener en cuenta los atributos que influyen en el comportamiento.

  • Decidir la granularidad de estados y eventos según las necesidades del modelo

  • Distinguir entre eventos y guardas.

  • Distinguir entre actividades y acciones.

  • Utilizar diagramas anidados cuando una transición se aplique a varios estados.

  • Realizar un DE compuesto si:

¡ Existen relaciones de composición entre los objetos.

¡ Existe concurrencia interna en el objeto.

¡ Podemos dividir el comportamiento en facetas independientes.

¡ Existen relaciones de herencia entre los objetos.

  • En caso de herencia de entre clases, el DE de la subclase no puede añadir estados o transiciones al DE padre.

  • Comprobar la consistencia de los eventos que se generan en un DE y se utilizan en otros.

Modelo de objetos I

Pasos a seguir.

  • Identificar objetos y clases.

  • Preparar un diccionario de datos.

  • Identificar asociaciones (incluyendo las de composición) entre los objetos.

  • Identificar atributos y operaciones.

  • Organizar y simplificar las clases mediante relaciones de generalización y especialización.

  • Verificar los caminos de acceso.

  • Refinar el modelo iterativamente.

Eliminar de la lista de clases candidatas:

  • Clases redundantes.

  • Clases irrelevantes.

  • Clases demasiado generales.

  • Atributos.

  • Operaciones.

  • Roles.

  • Construcciones de implementación.

Modelo de objetos II

Eliminar de la lista de asociaciones candidatas:

  • Asociaciones irrelevantes y de implementación.

  • Acciones.

  • Asociaciones no binarias.

  • Asociaciones derivadas.

Completar las asociaciones indicando:

  • Roles.

  • Calificadores.

  • Multiplicidad.

  • Ordenación.

Modelo dinámico. Pasos a seguir:

  • Establecer una lista de posibles eventos.

  • Eliminar de la lista de eventos las operaciones que no afecten al estado de un objeto.

  • Realizar varias trazas de eventos.

  • Construir un DE para cada clase de objetos que presente estados distintos, incorporando una a una las trazas de eventos.

  • Verificar la consistencia de los eventos entre los diferentes DEs: construir un diagrama de flujo de eventos.

Modelo funcional. Pasos a seguir.

  • Identificar datos de entrada y salida.

  • Hacer DFDs para mostrar la dependencia funcional.

  • Describir las primitivas de proceso.

Refinar los modelos.

Completar la lista de operaciones.

  • Operaciones sobre objetos: creación, destrucción y copia.

  • Operaciones sobre atributos: consulta, actualización acceso a los objetos relacionados

clase.atributo devuelve el valor del atributo.

clase.atributo := valor asigna valor al atributo.

clase.asociación devuelve al objeto asociado.

clase.asociación[i] id. para asociaciones múltiples.

clase.asociación[calificador] id. para asociaciones calificadas.

  • Operaciones invocadas por eventos.

  • Operaciones invocadas por acciones y actividades.

Comprobar la consistencia entre los modelos.

Comprobar el modelo con el cliente.

Ejercicio 1.

Realizar el modelo de objetos de un sistema de ficheros, basándose en las siguientes clases identificadas:

  • Sistema de ficheros.

  • Fichero.

  • Directorio.

  • Nombre de fichero.

  • Fichero ASCII.

  • Fichero ejecutable.

  • Fichero de Directorio.

  • Disco.

  • Drive.

  • Pista.

  • Sector.

Ejercicio 2.

El sistema de control de la mayoría de los electrodomésticos consta de los siguientes elementos:

  • Un botón, que debe mantenerse pulsado para que funcione el electrodoméstico.

  • Un motor, con dos contactos: START y RUN.

  • Un sensor que detecta cuando está funcionando el motor.

  • Un sensor de sobrecalentamiento.

Para arrancar el motor hay que aplicar corriente en los dos contactos (START y RUN) a la vez. Una vez que el motor esta en marcha, basta con mantener la corriente en el contacto RUN.

Si el motor se calienta en exceso (TEMP > TMAX), bien porque esté sobrecargado o bien porque no se consiga arrancar, se desconecta automáticamente, y no puede volver a conectarse hasta que se enfríe (TEMP < TMIN).

  • Realizar el DE de un electrodoméstico como el descrito.

  • Modificar el DE, generalizando algunos de sus estados de forma que se evite la repetición de transiciones comunes.

  • Modificar el modelo del sistema, suponiendo que consta de dos interruptores: On y Off. Una vez pulsado On el sistema se pone en marcha hasta que se pulse Off. Si ambos están pulsados al mismo tiempo, el motor debe estar parado. Si estando pulsados ambos, soltamos primero Off, el sistema debe ponerse en marcha.

Ejercicio 3.

Realizar el análisis de un editor de diagramas. Los diagramas pueden constar de varias hojas, cada una de ellas formada por cajas de tamaño variable conectadas mediante enlaces. Cada caja irá etiquetada con un nombre. Los enlaces son secuencias de segmentos rectos que conectan dos cajas. Cada segmento viene especificado por dos puntos. Dos segmentos consecutivos comparten un punto en común.

Las funciones que debe incorporar el editor son las habituales:

  • Cargar o salvar el diagrama en un fichero.

  • Añadir o borrar páginas del diagrama.

  • Seleccionar o deseleccionar cualquiera de los elementos (un elemento activo se representará más brillante en la pantalla).

  • Copiar los elementos seleccionados al buffer. Los enlaces entre cajas seleccionadas y no seleccionadas no se copian.

  • Borrar los elementos seleccionados. Los enlaces entre cajas seleccionadas y no seleccionadas se borra.

  • Vaciar el buffer.

  • Copiar el contenido del buffer sobre alguna hoja del diagrama, para lo cual se indicará el desplazamiento que se debe aplicar a las posiciones relativas de los elementos del buffer.

  • Crear cajas y enlaces.

Sólo vamos a realizar el análisis del núcleo del editor, no vamos a modelar el ratón, el teclado, ni la representación de los diagramas en la pantalla. Supondremos que los eventos se envían a los objetos del diagrama desde el entorno del sistema, solicitando la ejecución de alguna operación.


Ejemplo de Análisis Orientado a Objetos

Requisitos

Explican lo que se desea que haga el sistema, ya sea en lenguaje natural, o en forma de casos de uso a la Jacobson.

Ejemplo:

Se desea diseñar el software necesario para una red bancaria provista de cajeros automáticos (ATM, automatic teller machines), que serán compartidos por un consorcio de bancos. Cada banco dispone de su propio ordenador, provisto de software propio, que lleva la información sobre sus cuentas y procesa las transacciones que actúan sobre dichas cuentas. A este ordenador están conectadas las estaciones de cajero, que son propiedad del banco y en las que operan cajeros humanos, que pueden crear cuentas e introducir transacciones sobre ellas.

Los cajeros automáticos aceptan tarjetas de crédito, interaccionan con el usuario, se comunican con un ordenador central para llevar a cabo las transacciones, entregan dinero en efectivo al usuario e imprimen recibos. El sistema llevará correctamente el registro de las transacciones efectuadas, cumplirá características aceptables de seguridad y manejará correctamente accesos concurrentes a la misma cuenta.

El coste de desarrollo de la parte compartida del sistema se dividirá entre los bancos que forman parte del consorcio en función del número de clientes provistos de tarjetas de crédito.

Expresar los requisitos como Casos de Uso

Preparar escenarios detallados. Primero los normales. Después se añaden los problemas que pueden surgir. En el ejemplo de los cajeros automáticos:

  • Escenario normal:

    • El cajero automático pide al cliente que inserte la tarjeta de crédito.

    • El cliente inserta la tarjeta de crédito.

    • El cajero automático acepta la tarjeta de crédito y lee el número de tarjeta y el código del banco.

    • El cajero automático pide la contraseña al cliente.

    • El cliente teclea "1234".

    • El cajero automático envía el número de tarjeta, el código del banco y la contraseña al consorcio.

    • El consorcio envía el número de tarjeta y la contraseña al banco.

    • El banco notifica la aceptación al consorcio.

    • El consorcio notifica la aceptación al cajero automático.

    • El cajero automático pide al cliente que elija el tipo de transacción: retirada de fondos, depósito, transferencia, información.

    • El cliente selecciona retirada de fondos.

    • El cajero automático pide al cliente que teclee la cantidad.

    • El cliente teclea 25000.

    • El cajero automático comprueba que la cantidad está dentro de los límites generales.

    • El cajero automático genera una transacción y la envía al consorcio.

    • El consorcio pasa la transacción al banco.

    • El banco aprueba la transacción.

    • El banco actualiza la cuenta.

    • El banco envía al consorcio la notificación de aceptación y el nuevo saldo de la cuenta.

    • El consorcio envía al cajero automático la notificación de aceptación y el nuevo saldo de la cuenta.

    • El cajero automático entrega el dinero al cliente.

    • El cliente toma el dinero.

    • El cajero automático pregunta al cliente si quiere un recibo.

    • El cliente contesta SI.

    • El cajero automático imprime un recibo y pide al cliente que lo tome.

    • El cliente toma el recibo.

    • El cajero automático pregunta al cliente si quiere hacer otra operación.

    • El cliente contesta NO.

    • El cajero automático expulsa la tarjeta de crédito e indica al cliente que la tome.

    • El cliente toma la tarjeta de crédito.

    • El cajero automático vuelve a la situación inicial.

  • Escenario con problemas:

    • El cajero automático pide al cliente que inserte la tarjeta de crédito.

    • El cliente inserta la tarjeta de crédito.

    • El cajero automático acepta la tarjeta de crédito y lee el número de tarjeta y el código del banco.

    • El cajero automático pide la contraseña al cliente.

    • El cliente teclea "9999".

    • El cajero automático envía el número de tarjeta, el código del banco y la contraseña al consorcio.

    • El consorcio envía el número de tarjeta y la contraseña al banco.

    • El banco notifica el rechazo al consorcio.

    • El consorcio notifica el rechazo al cajero automático.

    • El cajero automático notifica el rechazo al cliente y pide que teclee de nuevo la contraseña.

    • El cliente teclea "1234".

    • El cajero automático envía el número de tarjeta, el código del banco y la contraseña al consorcio.

    • El consorcio envía el número de tarjeta y la contraseña al banco.

    • El banco notifica la aceptación al consorcio.

    • El consorcio notifica la aceptación al cajero automático.

    • El cajero automático pide al cliente que elija el tipo de transacción: retirada de fondos, depósito, transferencia, información.

    • El cliente selecciona retirada de fondos.

    • El cajero automático pide al cliente que teclee la cantidad.

    • El cliente teclea CANCELAR.

    • El cajero automático expulsa la tarjeta de crédito e indica al cliente que la tome.

    • El cliente toma la tarjeta de crédito.

    • El cajero automático vuelve a la situación inicial.

Modelo de objetos

Consta de los siguientes pasos:

  • Identificar objetos y clases

  • Identificar y depurar relaciones

  • Identificar atributos de objetos y relaciones

  • Añadir herencia

  • Comprobar los casos de uso (iterar)

  • Modularizar

  • Añadir y simplificar métodos

Identificar objetos y clases

Consta de los siguientes pasos:

  • Seleccionar nombres en los requisitos

  • Añadir clases adicionales procedentes de nuestro conocimiento del tema

  • Eliminar redundancias

  • Eliminar clases irrelevantes

  • Eliminar clases vagas

  • Separar atributos

  • Separar métodos

  • Eliminar objetos de diseño

Resultado: Preparar diccionario de clases

En el ejemplo de los cajeros automáticos:

  • Seleccionar nombres en los requisitos

    Los nombres extraídos de los requisitos en lenguaje natural del sistema de cajeros automáticos son los siguientes (23):

    Software, Red bancaria, Cajero automático, Consorcio de bancos, Banco, Ordenador del banco, Cuenta bancaria, Información sobre la cuenta, Transacción, Estaciones de cajero, Cajero humano, Tarjeta de crédito, Usuario, Ordenador central, Dinero en efectivo, Recibo, Sistema, Registro de transacciones, Características de seguridad, Acceso a la cuenta, Coste de desarrollo, Parte compartida, Cliente.

  • Añadir clases adicionales procedentes de nuestro conocimiento del tema

    Podemos añadir la clase Línea de comunicaciones.

  • Eliminar redundancias

    Cliente y Usuario son la misma clase. Nos quedamos con Cliente por adaptarse mejor al concepto.

  • Eliminar clases irrelevantes

    Coste de desarrollo no tiene nada que ver con el problema, queda fuera del sistema.

  • Eliminar clases vagas

    Sistema, Características de seguridad, Red bancaria y Parte compartida pueden considerarse vagas.

  • Separar atributos

    Los atributos definen datos asociados a un objeto, en lugar de objetos. Aunque la separación no es clara (los atributos pueden ser objetos embebidos) en algunos casos se pueden distinguir. En el ejemplo, pueden considerarse atributos Información sobre la cuenta, (atributo de Cuenta bancaria), Dinero en efectivo y Recibo (atributos de Cajero automático).

  • Separar métodos

    Algunos nombres (por ejemplo, Llamada telefónica) definen realmente operaciones o eventos.

  • Eliminar objetos de diseño

    Todas las clases que corresponden más a la solución del problema que a la situación real, deben considerarse objetos de diseño y eliminarse en la fase del análisis. En el ejemplo, eliminaremos Registro de transacciones, Línea de comunicaciones, Acceso a la cuenta y Software.

Resultado. Del análisis anterior, resultan seleccionadas las siguientes clases (11):

Cajero automático, Consorcio de bancos, Banco, Ordenador del banco, Cuenta bancaria, Transacción, Estaciones de cajero, Cajero humano, Tarjeta de crédito, Ordenador central, Cliente.

El diccionario de clases contiene la definición detallada de todas estas clases en lenguaje natural. Ejemplo:

  • Cajero automático: Terminal remoto que permite a los clientes realizar transacciones utilizando tarjetas de crédito para identificarse. El cajero automático interacciona con el cliente para identificar la transacción deseada y sus datos asociados, envía esta información al ordenador central para su validación y proceso, y entrega al usuario dinero en efectivo y un recibo. Suponemos que el cajero automático no opera cuando está desconectado de la red.

  • Consorcio de bancos: Conjunto organizado de bancos que lleva la gestión de los cajeros automáticos. Suponemos que sólo se gestionan transacciones para los bancos que pertenecen al consorcio.

  • Banco: Institución financiera que maneja las cuentas bancarias de sus clientes y emite tarjetas de crédito que facilitan el acceso a dichas cuentas a través de la red de cajeros automáticos.

Identificar y depurar relaciones

Consta de los siguientes pasos:

  • Seleccionar verbos relacionales en los requisitos

  • Añadir relaciones adicionales procedentes de nuestro conocimiento del tema

  • Eliminar relaciones de diseño o entre clases eliminadas

  • Eliminar eventos transitorios

  • Reducir relaciones ternarias

  • Eliminar relaciones redundantes o derivadas

  • Añadir relaciones olvidadas

  • Definir la multiplicidad de cada relación

En el ejemplo de los cajeros automáticos:

  • Seleccionar verbos relacionales en los requisitos

    1. Una Red bancaria está provista de Cajeros automáticos.

    2. El Consorcio de bancos comparte los Cajeros automáticos.

    3. Cada Banco dispone de un Ordenador del banco.

    4. El Ordenador del banco dispone de Software.

    5. El Ordenador del banco lleva la información sobre las Cuentas bancarias.

    6. El Ordenador del banco procesa Transacciones.

    7. Una Transacción actúa sobre una Cuenta bancaria.

    8. Las Estaciones de cajero están conectadas al Ordenador del banco.

    9. Las Estaciones de cajero son propiedad del Banco.

    10. El Cajero humano opera en la Estación de cajero.

    11. El Cajero humano crea Cuentas bancarias.

    12. El Cajero humano introduce Transacciones sobre las Cuentas bancarias.

    13. Los Cajeros automáticos aceptan Tarjetas de crédito.

    14. Los Cajeros automáticos interaccionan con el Usuario.

    15. Los Cajeros automáticos comunican con el Ordenador central.

    16. El Ordenador central lleva a cabo las Transacciones.

    17. Los Cajeros automáticos entregan Dinero en efectivo al Usuario.

    18. Los Cajeros automáticos imprimen Recibos.

    19. El Sistema lleva el Registro de las transacciones.

    20. El Sistema cumple Características de seguridad.

    21. El Sistema maneja Accesos concurrentes a la Cuenta bancaria.

    22. El Coste de desarrollo se divide entre los Bancos.

    23. Los Bancos forman parte del Consorcio.

    24. Los Clientes están provistos de Tarjetas de crédito.

      Relaciones adicionales implícitas en el texto:

    25. Las Cuentas bancarias están en los Bancos.

    26. El Ordenador central pertenece al Consorcio.

    27. Los Bancos tienen Clientes.

  • Añadir relaciones adicionales procedentes de nuestro conocimiento del tema

    • 28. Las Tarjetas de crédito están asociadas a las Cuentas bancarias .

    • 29. Los Cajeros humanos son empleados de los Bancos.

  • Eliminar relaciones de diseño o entre clases eliminadas

    Eliminamos las relaciones números 1, 4, 17, 18, 19, 20, 21, 22.

  • Eliminar eventos transitorios

    Son sucesos que pertenecen al modelo dinámico y no constituyen relaciones estructurales (estáticas) entre los objetos.

    Eliminamos las relaciones números 13 y 14. Otras veces conviene reformularlas, como en el caso de la número 16, el Ordenador central lleva a cabo las Transacciones, que debería sustituirse por:

    16 a. El Ordenador central se comunica con el Banco.

  • Reducir relaciones ternarias

    Son relaciones entre tres o más clases. Muchas veces es posible descomponerlas en varias relaciones binarias (entre dos clases). Por ejemplo, la relación número 12 (El Cajero humano introduce Transacciones sobre las Cuentas bancarias) puede descomponerse en:

    • 12a. El Cajero humano introduce Transacciones

    • 12b. Las Transacciones actúan sobre las Cuentas bancarias.

    De igual modo, la número 17 puede descomponerse así:

    • 17a. Los Cajeros automáticos entregan Dinero en efectivo.

    • 17b. El Usuario recoge el Dinero en efectivo.

  • Eliminar relaciones redundantes o derivadas

    Por ejemplo, la relación número 2 es una combinación de las relaciones número 15 y 26. Hay que tener cuidado, sin embargo, de no eliminar relaciones aparentemente redundantes, pero que en realidad son necesarias (por ejemplo, si la multiplicidad es distinta).

  • Añadir relaciones olvidadas

    Por ejemplo:

    • 30. Los Clientes tienen Cuentas.

    • 31. Las Transacciones son autorizadas por la Tarjeta de crédito.

    • 32. Las Transacciones pueden introducirse en una Estación de cajero.

  • Definir la multiplicidad de cada asociación

    • Un Banco puede contener muchas Cuentas.

    • Un Cliente puede tener muchas Cuentas.

    • Un Cliente puede tener muchas Tarjetas de crédito.

    • Un Banco emplea muchos Cajeros.

    • Un Banco tiene un solo Ordenador del banco.

    • El Ordenador central se comunica con muchos Ordenadores del banco.

    • Etc.

    El resultado de estas operaciones es un esqueleto del modelo de clases sin herencia.

Identificar atributos de objetos y relaciones

Consta de los siguientes pasos:

  • Distinguir los objetos de los atributos

  • Distinguir entre los atributos de objetos y de relaciones

  • El identificador del objeto es siempre un atributo implícito

  • Eliminar atributos privados (de diseño)

  • Eliminar atributos de detalle fino

  • Localizar atributos discordantes (dividir la clase)

En el ejemplo de los cajeros automáticos:

  • Atributos de los objetos

    • Del Banco: Nombre.

    • De la Cuenta: Saldo, Límite de crédito, Tipo de cuenta.

    • Del Cliente: Nombre, Dirección.

    • Del Cajero: Nombre.

    • De una Transacción del cajero: Tipo, Fecha y hora, Cantidad.

    • Del Cajero automático: Efectivo disponible, Cantidad entregada.

    • De una Transacción remota: Tipo, Fecha y hora, Cantidad.

    • De la Tarjeta de crédito: Clave, Código del banco, Código de la tarjeta.

  • Atributos de las relaciones

    • 8 y 9: Código de la estación de cajero.

    • 15: Código del cajero automático.

    • 16a: Código del banco.

    • 23: Código del banco.

    • 25: Código de la cuenta.

    • 29: Código de empleado.

Añadir herencia

Introducimos clases nuevas (virtuales) que contienen información común a dos o más clases preexistentes. Procurar evitar la herencia múltiple, a menos que sea estrictamente necesaria.

Resultado: Primer diagrama de clases

En el ejemplo de los cajeros automáticos:

  • La clase Estación de entrada será superclase de Cajero automático y de Estación de cajero.

  • La clase Transacción será superclase de Transacción de cajero y de Transacción remota.

  • Podrían refinarse los tipos de cuentas.

Comprobar los casos de uso (iterar)

Para localizar fallos que deben corregirse fijarse en:

  • Asimetrías en las relaciones: añadir clases nuevas para equilibrarlas.

  • Atributos muy dispares: descomponer una clase en dos.

  • Dificultades en la formación de superclases: descomponer una clase en dos. Una de sus partes puede ajustar mejor.

  • Operaciones sin objetivo: añadir clase.

  • Relaciones duplicadas: crear superclase.

  • Conversión de relaciones en clases: por ejemplo, clase Empleado.

  • Operaciones que no encuentran camino para realizarse: añadir relaciones.

  • Relaciones redundantes: eliminarlas.

  • Relaciones demasiado detalladas o demasiado vagas: subirlas a una superclase o bajarlas a una subclase.

  • Clases sin atributos, sin métodos o sin relaciones: eliminarlas.

  • Relaciones que nadie atraviesa: eliminarlas.

  • Atributos de clase necesarios en un acceso: pasarlos a atributos de relación.

En el ejemplo de los cajeros automáticos:

  • Tarjeta de crédito desempeña dos roles: la tarjeta física, que se introduce y que permite al cajero automático conectarse con el banco, con información sobre el mundo real (banco, número de la tarjeta) y las autorizaciones concedidas por éste, que sólo son números en la memoria de un ordenador y se pueden cambiar con facilidad (contraseña, límite de crédito). Se puede descomponer en Tarjeta de crédito y Autorización de la tarjeta. Una sola autorización puede afectar a más de una tarjeta física. Una misma autorización puede permitir acceder a más de una cuenta (y viceversa).

  • Introducimos la clase Actualización de cuenta para refinar el concepto de Transacción. Una misma transacción puede estar compuesta de varias actualizaciones de cuenta (por ejemplo, transferencia entre cuentas son dos actualizaciones).

  • No hay distinción significativa entre Banco y Ordenador del banco, por una parte, y entre Consorcio y Oredenador central, por otra. Fusionamos esas clases.

Modularizar

Agrupar clases en módulos.

En el ejemplo de los cajeros automáticos. Posibles módulos:

  • Cajeros en general: Cajero, Estación de cajero, Cajero automático, Estación de entrada.

  • Cuentas en general: Cuenta, Tarjeta de crédito, Autorización, Cliente, Transacción, Transacción de cajero, Transacción remota.

  • Bancos: Banco, Consorcio.

Añadir y simplificar métodos

  • Todos los atributos se suponen accesibles.

  • Añadir métodos que permitan navegar de un objeto a otro.

Modelo dinámico

Consta de los siguientes pasos:

  • Identificar sucesos

  • Construir diagramas de estados

  • Comprobar consistencia (iterar)

  • Añadir métodos

Identificar sucesos

Los sucesos se extraen de los casos de uso (escenarios). Pueden ser de los siguientes tipos:

  • Señales

  • Entradas

  • Decisiones

  • Interrupciones

  • Transiciones

  • Acciones externas

  • Condiciones de error

Resultados: Diagramas de secuencia (trazas de eventos) y diagramas de colaboración (diagramas de flujo de eventos).

Los casos de uso (escenarios) se convierten en diagramas de secuencia. Estas se compactan en diagramas de colaboración.

En el ejemplo de los cajeros automáticos:

El cliente introduce la contraseña define un evento de entrada que el objeto Cliente envía al objeto Cajero automático. El cajero automático entrega el dinero al cliente es un evento que el objeto Cajero automático envía al objeto Cliente.

Agrupar los eventos equivalentes: El cliente introduce la contraseña es el mismo evento independientemente de la contraseña introducida. El cajero automático entrega el dinero al cliente es el mismo evento independientemente de la cantidad entregada.

No agrupar los eventos no equivalentes: El banco autoriza la transacción es distinto evento que El banco rechaza la transacción.

Construir diagramas de estados

Uno por clase.

En el ejemplo de los cajeros automáticos centrarse en las clases dinámicas, que cambian de estado:

  • Cajero automático

  • Banco

  • Consorcio

  • Estación de cajero

No hace falta construir diagramas de estado de las clases pasivas, que no cambian de estado de modo significativo:

  • Tarjeta de crédito

  • Transacción

  • Cuenta

Tampoco hace falta considerar a fondo los objetos externos, que no forman parte del sistema informático:

  • Cliente

  • Cajero humano

Añadir métodos

Los eventos son métodos. Es preciso decidir de qué clase de objetos.

Las acciones y actividades realizadas en los estados son métodos.

Modelo funcional

Consta de los siguientes pasos:

  • Identificar valores de entrada/salida

  • Construir diagramas de flujo de actividad

  • Describir funciones

  • Identificar restricciones y dependencias funcionales entre objetos

  • Definir criterios de optimización (iterar)

  • Añadir métodos

Identificar valores de entrada/salida

Son los que pasan información desde los objetos externos al sistema de software propiamente dicho.

En el ejemplo de los cajeros automáticos son objetos externos:

  • Cliente

  • Tarjeta de crédito

  • Cajero humano

Los valores de entrada/salida serán:

  • Del cliente al cajero automático: contraseña, tipo de transacción, tipo de cuenta, cantidad solicitada.

  • De la tarjeta de crédito al cajero automático: código del banco, código de la tarjeta.

  • Del cajero automático al cliente: dinero en efectivo, recibo, mensajes.

Construir diagramas de flujo de actividad

Relacionan los valores de entrada con los de salida. Suele dividirse en varias capas o niveles.

En el ejemplo de los cajeros automáticos:

  • Nivel superior: relaciona el cliente, la tarjeta de crédito y la cuenta.

  • Nivel intermedio: expande la operación "realizar transacción", incluida en el nivel superior.

Describir funciones

Descripción de cada una de las funciones de nivel mínimo que aparecen en los diagramas de flujo de actividad. La descripción puede ser:

  • En lenguaje natural

  • Un modelo matemático

  • Pseudocódigo

  • Tablas de decisión

  • Etc.

En el ejemplo de los cajeros automáticos:

Descripción de la función "actualizar cuenta":

  actualizar cuenta (cuenta, cantidad, tipo de transacción)
  -> efectivo, recibo, mensaje
    Si es una retirada de efectivo:
      Si la cantidad a retirar excede el saldo,
        rechazar la transacción y no entregar dinero
      En caso contrario:
        Restar la cantidad del saldo y entregar dinero
    Si es un depósito:
      Aumentar el saldo de la cuenta y no entragar dinero
    Si es una petición de información:
      Escribir saldo y no entregar dinero
    En cualquier caso:
      El recibo incluye:
        - número del cajero automático
        - fecha y hora
        - número de la cuenta
        - tipo de transacción
        - cantidad movida
        - nuevo saldo

Identificar restricciones y dependencias funcionales entre objetos

En el ejemplo de los cajeros automáticos:

  • El saldo de una cuenta no puede ser negativo

    o bien:

  • El saldo de una cuenta, si es negativo, no puede rebasar el límite de crédito.

Definir criterios de optimización (iterar)

En el ejemplo de los cajeros automáticos:

  • Minimizar el número de mensajes enviados entre localidades diferentes.

  • Minimizar el tiempo de bloqueo de una cuenta.

  • Extremadamente urgente: minimizar el tiempo de bloqueo de un banco entero.

Añadir métodos

Las funciones del modelo funcional pueden ser simples transferencias de información, o corresponder a un método de algún objeto (operaciones interesantes). En este caso hay que asignarlos y añadirlos al modelo de objetos.

En el ejemplo de los cajeros automáticos, son interesantes:

  • Comprobar contraseña (método de Autorización de la tarjeta).

  • Actualizar cuenta (método de la clase Cuenta).

Se añadirán otros métodos, no relacionados con ninguna de las cuestiones anteriores, procedentes de nuestro conocimiento del tema:

AVIZORA
TEL: +54 (3492) 452494 / ARGENTINA - Web master: webmaster@avizora.com - Copyright © 2001 m. Avizora.com