Sunteți pe pagina 1din 20

DESCOMPOSICIÓN MODULAR DEL PROYECTO INTEGRAL DEL SEMESTRE.

Ámbito de desarrollo: Laboratorio

Competencia de la práctica:

Identificar la importancia de la descomposición modular para el desarrollo de software por


medio del uso de herramientas con diferentes enfoques que permitan realizar la
descomposición modular del proyecto integral del semestre. Tomar decisiones técnicas
relacionadas con la arquitectura del software.

1. Introducción

En ésta práctica el estudiante se dedica a completar la descomposición modular del


proyecto integral del semestre, retomando el diagrama de clases previamente obtenido en
el modelo de análisis. Considerando la falta de experiencia del alumno en el desarrollo de
software se propone aplicar una herramienta de la filosofía orientada a objetos que es el
diseño por responsabilidades y una herramienta del enfoque estructurado,
específicamente el diseño de diagrama de menús, para lograr la descomposición modular
del proyecto en desarrollo.
En la materia anterior fundamentos de ingeniería de software, ya se diseñaron las tarjetas
de clase en la práctica 4.1. (P4.1) Se elaboró una tarjeta para cada clase en el sistema,
donde las tarjetas incluían únicamente entradas para el nombre de la clase, módulo al que
pertenecen y estereotipo correspondiente. Como se puede observar, las tarjetas de clase
tenían información muy limitada, en esta práctica continuamos con el diseño, poco a poco
las tarjetas de clases se extenderán hasta alcanzar los métodos y atributos detallados
ahora se procede a identificar las responsabilidades de cada clase.

2. Fundamento teórico

La información teórica que se propone para esta práctica está organizada de la siguiente
manera:
Primero de trata el concepto de arquitectura en el tema de proceso de software,
posteriormente se presenta desde la perspectiva de las estrategias de diseño, continua
con el tema modelo de diseño para realizar la practica usando la herramienta del enfoque
orientado a objetos basada en responsabilidades y finalmente se maneja la información
teórica del enfoque estructurado para completar la práctica con el diseño del diagrama de
menús del enfoque estructurado.

Proceso de software.1
1
Weitzenfeld, Alfredo. (2008). Ingeniería de Software Orientada a Objetos con UML, Java e Internet. México D.F.:
Un proceso define quién hace qué, cuándo y cómo para alcanzar cierto objetivo. En el
caso de desarrollo de software, se requieren procesos especializados que abarquen desde
la creación hasta la administración de un sistema de software.

Modelo de proceso.

Un modelo de proceso define cómo solucionar la problemática del desarrollo de sistemas


de software. Para desarrollar el software se requiere resolver ciertas fases de su proceso,
las cuales se conocen en su conjunto como el ciclo de vida del desarrollo de software.

Una creencia común, aunque equivocada, es la existencia de un solo modelo de proceso


aplicable a cualquier proyecto, pues el modelo de proceso depende del tipo particular de
proyecto, por ejemplo:

Primer proyecto de su tipo


Segundo proyecto de su tipo
Variación de un proyecto
Proyecto de reescritura de legado (legacy)
Proyecto de creación de software reutilizable
Proyecto de mejora de sistema o mantenimiento

Dada la variedad de tipos de proyectos, es necesario considerar los diferentes


componentes de un modelo de procesos. Estos componentes principalmente son: la
arquitectura, la actividad, los métodos y las metodologías, la estrategia y las herramientas
para la administración del software. Las cuales se describen a continuación:

Arquitectura
Una arquitectura de software define la estructura general de un sistema y varía de acuerdo
con el tipo de sistema a desarrollarse. Así, puede estar basada en elementos sencillos o
componentes prefabricados de mayor tamaño, y se especifica de acuerdo con los
diferentes tipos de sistemas. A continuación, se dan algunos ejemplos de familias de
sistemas:
Transformación en lote (batch).
Transformación continua.
Sistemas interactivos.
Simulación dinámica.
Sistemas de tiempo real.
Administración de transacciones.

Además de depender del tipo de sistema a desarrollar, la selección de una arquitectura

Thompson. p. 357,358,359,360.
afecta aspectos como la extensibilidad del sistema. Por lo tanto, la arquitectura debe ser
escogida de manera que minimice los efectos de cambios futuros en el sistema. Para ello
existen ciertas heurísticas que muestran la tendencia a cambios en varios elementos de un
sistema como se muestra en la figura 1 las interfaces representan los elementos gráficos,
la funcionalidad son las reglas del negocio, los datos y funciones son los elementos
internos de los objetos, correspondientes a las estructuras básicas de la orientación a
objetos, mientras que la información representa el dominio del problema en una
aplicación.

Para efectos del tema, solo analizaremos este componente de un modelo de procesos.

Probabilidad de cambios futuros en el software


de acuerdo con el tipo de elemento de diseño.

Elemento Probabilidad de cambio


Interfaces Alto
Funcionalidad Alto
Datos Medio
Funciones Medio
Objetos Bajo
Información Bajo

Figura 1. Probabilidad de cambios futuros en el software de acuerdo con el tipo de elemento de


diseño.

Esta tabla resalta dos aspectos del desarrollo del software:

i. La arquitectura del sistema debe distinguir entre elementos con mayor o menor
probabilidad de cambios y
ii. El desarrollo de software debe considerar un modelo de proceso, donde
aquellos elementos de mayor probabilidad de cambio y no arrastren a los más
estables.

Estrategias de diseño.2

Antes de resolver el diseño es necesario tomar decisiones generales sobre las estrategias
de diseño a seguir. Algunas de las decisiones a tomar se presentan a continuación y se
relacionan con aspectos que incluyen la arquitectura, robustez, reúso y extensibilidad del
sistema.

Daremos énfasis en el aspecto Arquitectura para este tema.

Arquitectura

El término arquitectura se refiere, en este caso, a la organización de las clases dentro del
sistema. Durante el modelo de análisis se generó una arquitectura de clases para el
sistema y se definió la funcionalidad conceptual ofrecida por las distintas clases dentro de
la arquitectura. Durante el diseño debe detallarse esta arquitectura, pudiéndose cambiar
los aspectos considerados inicialmente, como fue la funcionalidad asignada a cada clase,
e incluso las propias clases, como hemos mencionado antes.
El conocimiento y funcionalidad asignada a cada clase se ve como la “inteligencia” de cada
clase dentro del sistema. En otras palabras, algunas clases se ven más inteligentes que
otras según el conocimiento y control que tengan sobre las demás clases. Por ejemplo,
colecciones de objetos tales como listas o arreglos no se consideran inteligentes, ya que
se emplean para obtener información acerca de las clases que almacenan, pero tienen
relativamente poco impacto sobres éstas u otras clases dentro del sistema. Por otro lado,
un manejador de interface de usuario requiere mayor inteligencia, pues debe administrar
la interacción con el usuario, ya que maneja los eventos y las pantallas. Una clase aún más
inteligente, es el controlador o manejador de la lógica completa de la aplicación, ya que es
responsable de administrar los manejadores de borde y relacionar su funcionalidad con el
resto del sistema. Como parte de la arquitectura de diseño se decide cómo distribuir la
inteligencia entre las clases y qué aspectos de la inteligencia del sistema se debe asignar a
cada una de ellas. Para ello existen tres alternativas posibles:

Un primer enfoque es minimizar el número de clases inteligentes. En el caso más extremo,


solo un objeto tendría conocimiento sobre todo el sistema. Los demás objetos tendrían un
mínimo de inteligencia y el objeto inteligente servirá como controlador de los demás.

Ventaja:
Solo se requeriría comprender el flujo de control dentro del objeto principal para entender

2
Weitzenfeld, Alfredo. (2008). Ingeniería de Software Orientada a Objetos con UML, Java e Internet. México D.F.:
Thompson. p. 358, 359.
toda la aplicación.

Sin embargo, se vuelve más completa la extensibilidad del sistema, ya que cualquier
cambio en el flujo de control se llevaría a cabo en un mismo objeto y afectaría
potencialmente la lógica de toda la aplicación. De cierta manera, esto se considera como
la “estructuración” del programa, en otras palabras, se transforma la orientación a objetos
a programación estructurada, desde toda la aplicación consta de un solo “objeto”.

Un segundo enfoque es distribuir la inteligencia del sistema lo más homogéneo posible,


diseñando todas las clases con inteligencia familiar. Este enfoque se aproxima más con el
espíritu de la orientación a objetos. Sin embargo, una distribución perfectamente
homogénea es una tarea casi imposible, ya que los objetos varían en sus
responsabilidades, su razón de ser depende de la aplicación. Por otro lado, la distribución
de la inteligencia del sistema de manera homogénea entre los objetos permite que cada
objeto sepa menos cosas. Esto produce objetos más pequeños y más fáciles de
comprender. La desventaja es que la inteligencia del sistema va de la mano con la
especialización de las clases. Si todas las clases son “inteligentes”, esto significará que
éstas serán muy especializadas, dificultándola la extensibilidad del sistema que requiere
generalizar más las clases.

El tercer enfoque es encontrar un balance entre los dos primeros. La idea es


homogeneizar la inteligencia del sistema solo entre ciertas clases, como las de control. El
resto de las clases, entidad y borde, serán tontas, generalmente sobreviviendo a
modificaciones en el sistema y manteniendo la lógica introducida durante el modelo de
requisitos y el modelo de análisis posterior para lograr una mayor robustez del sistema.

Modelo de diseño.

El modelo de diseño es un refinamiento y formalización del modelo de análisis, donde se


toman en cuenta las consecuencias del ambiente de implementación. El resultado del
modelo de diseño son especificaciones muy detalladas de todos los objetos, incluyendo
sus operaciones y atributos. El modelo del diseño se basa en el diseño por
responsabilidades.

Durante el diseño se ve si los resultados anteriores obtenidos en el análisis son


apropiados para la implementación. Si se descubren aspectos que no están claros en
algunos de los modelos anteriores, éstos se aclaran, posiblemente regresando a etapas
anteriores.
El modelo de diseño se considera como una formalización del espacio de análisis,
extendiéndolo para incluir una dimensión adicional que corresponde al ambiente de
implementación como se ve en la figura 2:
Figura 2. Dimensión ambiente de implementación como un nuevo eje de desarrollo

Esta nueva dimensión, correspondiente al ambiente de implementación, se considera al


mismo tiempo que se refina el modelo. La meta es refinarlo hasta que sea fácil escribir el
código fuente.

Se considera por separado los dos aspectos principales del modelo de diseño: el diseño
de objetos y el diseño de sistema.

Diseño de Objetos

El diseño de objetos es un proceso para añadir detalles al análisis y tomar decisiones junto
con el diseño del sistema, es decir, al ambiente de implementación, de manera que se
logre una especificación detallada antes de comenzar la implementación final. Algunos de
los aspectos a resolver por el diseño de objetos es determinar cómo las clases, atributos y
asociaciones del modelo de análisis deben implementarse en estructuras de datos
específicas. También es necesario determinar si es necesario incluir nuevas clases en el
modelo del diseño, para las cuales no se tiene ninguna representación en el modelo de
análisis, o si se requiere modificar o eliminar clases identificadas durante el modelo de
análisis. Se debe agregar herencia para incrementar el re uso del sistema. También es
necesario determinar los algoritmos para implementar las operaciones, así como todos los
aspectos de optimización.

Para diseñar un objeto se seguirá el diseño por responsabilidades (RDD- Responsability–


Driven Design). Este diseño se basa en un modelo cliente-servidor, dónde las clases se
ven como clientes cuando generan alguna petición hacia alguna clase, y como servidores
cuando reciben peticiones de otra clase. De tal manera una misma clase en distintos
momentos se ve como cliente o servidor.

Especificación de las tarjetas de clase

Las tarjetas de clase (también llamadas tarjetas CRC: Clase-Responsabilidad-


Colaboración) permiten al diseñador visualizar las diferentes clases de manera
independiente y detallada. La figura 3 se muestra a continuación:

Figura 3. Imagen de una tarjeta de clase.

Encabezado: contiene el nombre de la clase, una descripción de la clase (similar a la


escrita en el diccionario de clases del análisis), el módulo al que pertenece la clase, el
estereotipo de la clase (borde, entidad o control), las propiedades de la clase (abstracta o
concreta), una lista de superclases, una lista de subclases y una lista de atributos.

Dos columnas debajo del encabezado, corresponden a las responsabilidades (a la


izquierda) y colaboraciones (a la derecha) de la clase. En la columna izquierda, además de
responsabilidades, se incluirá información sobre los contratos.

Originalmente, detrás de cada tarjeta se agregaba una descripción corta del propósito de
cada clase, algo que se hará a través del diccionario de clases. Además se incluyen
algunos datos adicionales al esquema original CRC.

Como ejemplo, se considera la clase InterfaceUsuario, una de las clases identificadas


durante el modelo de análisis para el ejemplo del sistema de reservaciones de vuelos. La
tarjeta de clase sería:
Figura 4. Tarjeta de clase para la clase InterfaceUsuario.

Uno de los esfuerzos más grandes del desarrollo, es la especificación del comportamiento
de cada una de las clases del sistema. A diferencia de la estructura interna de una clase,
representada mediante sus atributos, los comportamientos corresponden a las
operaciones y métodos de las clases.

En general, el comportamiento de las clases no debe descomponerse directamente en


operaciones, sino seguir un procedimiento más natural comenzando con una descripción
verbal de las responsabilidades o roles que tiene cada clase dentro del sistema.
Obviamente cada objeto instanciado de una misma clase tendrá responsabilidades
similares a las descritas por la clase. Las responsabilidades ofrecidas por un objeto
corresponden a los servicios apoyados por este. A partir de estas responsabilidades, a la
larga se podrá determinar las operaciones que cada objeto debe tener e incluso el
conocimiento que posee el objeto.

Las responsabilidades se identifican a partir de los casos de uso generados durante el


modelo de análisis. Para ello, se revisa el modelo de casos de uso, haciendo una lista o
subrayado todas las frases descritas para determinar cuales representan las acciones que
debe ejecutar algún objeto dentro del sistema. Una de las decisiones más importantes
durante la identificación de responsabilidades es a qué clase o clases se les debe asignar.
Para ello se examina el contexto en el cual se identificaron las responsabilidades.

Se asignan responsabilidades a las clases que almacenan la información más relacionada


con la responsabilidad. En otras palabras, si un objeto requiere cierta información, es
lógico asignarle la responsabilidad de mantener esa información. Si la información
cambia, no será necesario enviar mensajes de actualización a otros objetos. Esto también
significa que la responsabilidad de mantener la información no se comparte. Compartir
información implica una duplicidad que da lugar a inconsistencias. Si más de un objeto
tiene responsabilidad sobre la misma información, se reasigna la responsabilidad a un
solo objeto. También puede ocurrir que cierta responsabilidad agrupe varias
responsabilidades. En tal caso, se divide o comparte la responsabilidad entre dos o más
objetos. Si se vuelve difícil decidir a quién se debe de asignar una responsabilidad, se
experimenta con diversas alternativas, con la ventaja que, durante las primeras etapas del
diseño, este proceso no es muy costoso. Será mucho más difícil y tomará más tiempo
hacerlo, después de haber implementado el sistema completo.

En cuanto a la especificación de las responsabilidades, se describen las responsabilidades


en términos generales, para luego encontrar más fácilmente responsabilidades
compartidas entre clases. Por tanto, es necesario considerar aspectos específicos de las
responsabilidades, como nombres particulares o incluso parámetros. Otra condición, es
asegurarse que los ciclos de responsabilidades y colaboraciones entre clases no sean
interrumpidos y mantengan siempre una correspondencia con la arquitectura establecida
durante el análisis.

Consideremos el sistema de reservaciones de vuelo. Dado que el diseño de un sistema es


por lo general bastante más elaborado que el análisis se procede con la descripción de los
aspectos más relevantes del sistema y abarcando requisitos parciales. Para ello se hará un
diseño basado en el caso de uso: ValidarUsuario.

VALIDAR USUARIO

En el modelo de análisis el flujo principal del caso de uso era el siguiente:

El ManejadorPrincipal solicita desplegar DesplegarPantallaPrincipal a la InterfaceUsuario.


La InterfaceUsuariodespliega la PantallaPrincipal. La PantallaPrincipal se despliega.
El usuario puede seleccionar entre las siguientes opciones: “Registrarse por primera
vez”,”OK” y “Salir”.
Si la actividad seleccionada es “Registrarse por primera vez”, la PantallaPrincipal envía el
evento “RegistrarsePorPrimeraVez” a la InterfaceUsuario. La InterfaceUsuario envía el
evento “Registrarse por primera vez” al ManejadorPrincipal. El ManejadorPrincipal solicita
CrearRegistroUsuario al ManejadorRegistroUsuario. Se ejecuta el caso de uso Registrar
Usuario. Subflujo Crear Registro Usuario (S-1).
Si la actividad seleccionada es “OK”, se valida el registro de usuario mediante un login y un
password insertados por el Usuario en la PantallaPrincipal. La PantallaPrincipal envía el
evento “OK” a la InterfaceUsuario. La InterfaceUsuario envía el evento “OK” al
ManejadorPrincipal. El ManejadorPrincipal solicita ValidarRegistroUsuario al
ManejadorRegistroUsuario. ElManejadorRegistroUsuario solicita ValidarRegistroUsuario a
la InterfaceBaseDatosRegistro. LaInterfaceBaseDatosRegistro solicita
ValidarRegistroUsuario a la BaseDatosRegistro. LaBaseDatosRegistro valida al usuario y
devuelve el “OK” a la InterfaceBaseDatosRegistro. LaInterfaceBaseDatosRegistro devuelve el
“OK” al ManejadorRegistroUsuario. El ManejadorRegistroUsuario devuelve el “OK” al
ManejadorPrincipal. Una vez validado el usuario (E-1), el ManejadorPrincipal solicita
OfrecerServicios al ManejadorServicios. Se continúa con el caso de uso Ofrecer Servicios.

Si la actividad seleccionada es “Salir” la PantallaPrincipal envía el evento “Salir” a la


InterfaceUsuario. La InterfaceUsuario envía el evento “Salir” a la ManejadorPrincipal. El
ManejadorPrincipal sale del sistema.

Se toma cada una de las frases que describen el flujo y se analizan para decidir qué
responsabilidad representa y a qué clase se le asigna:

1. El ManejadorPrincipal solicita desplegar DesplegarPantallaPrincipal a la


InterfaceUsuario.

La primera pregunta es “cuál es la responsabilidad”. La responsabilidad que se identifica


aquí es “solicita desplegar DesplegarPantallaPrincipal”. La siguiente pregunta es “a quién
se le asigna la responsabilidad” existen dos opciones: asignar “solicita desplegar
DesplegarPantallaPrincipal” al ManejadorPrincipal o asignar “desplegar
DesplegarPantallaPrincipal” a la InterfaceUsuario. Para simplificar esta decisión y
asegurarse, al menos en esta etapa de no perder información, se tomará una decisión
“salomónica”, asignando dos responsabilidades, una a cada clase. Esto es muy importante,
ya que se asegura comenzar con un buen número de responsabilidades que luego se
reorganizarán durante el transcurso del diseño. Es importante resaltar que, dado que
muchas responsabilidades pueden darse de manera duplicada, se debe de evitar revisando
las frases que generan duplicaciones. Por tanto, la responsabilidad inicial de “solicita
desplegar DesplegarPantallaPrincipal” se asignará al ManejadorPrincipal. Definiendo la
responsabilidad de manera completa como “Solicita desplegarPantallaPrincipal a la
InterfaceUsuario”. Como se verá con la segunda frase, la responsabilidad de
desplegarPantallaPrincipal se asignará de manera adecuada a la InterfaceUsuario, por lo
que no será necesario hacerlo en este momento. Sin embargo, siempre se revisa que en la
frase siempre exista la responsabilidad complementaria para la segunda clase. El objetivo
esencial es asegurarse de asignar responsabilidades a las diferentes clases, de manera
que no se rompa con el flujo de colaboraciones, algo que debe tratarse con sumo cuidado
para resolver cuanto antes el problema general de asignación de servicios. También se
debe recordar que habrá varias etapas dentro de la actividad de diseño donde se podrá
afinar la asignación de responsabilidades.

2. La InterfaceUsuario despliega la PantallaPrincipal.

De manera análoga a la oración anterior, la responsabilidad que se identifica es “ despliega


laPantallaPrincipal” y la asignamos a InterfaceUsuario utilizando la misma lógica anterior.
Observe que esta responsabilidad corresponde al servicio solicitado por
ManejadorPrincipal en la oración anterior. Esto resalta el hecho de que las
responsabilidades se están asignando de manera correcta y sin romper el flujo de
colaboraciones.

3. La PantallaPrincipal se despliega.

Esta responsabilidad se asigna a la única clase participante que es PantallaPrincipal. Note


también que esta responsabilidad, “despliega ”, corresponde al servicio de despliegue de la
PantallaPrincipal referido en la oración anterior.

4. El usuario puede seleccionar entre las siguientes opciones: “Registrarse por primera
vez”,”OK” y “Salir”.

En general, los actores no son parte de la arquitectura del sistema, por lo que no se les
asigna ninguna responsabilidad.

5. Si la actividad seleccionada es “Registrarse por primera vez”, la PantallaPrincipal envía


el evento “Registrarse Por Primera Vez” a la InterfaceUsuario

6. De manera análoga a las asignaciones anteriores, la responsabilidad “envía el evento


“Registrarse por primera vez” a la InterfaceUsuario se asigna a la PantallaPrincipal. Dado
que en la siguiente frase la InterfaceUsuario envía a su vez el evento a otra clase, no se
agrega ninguna responsabilidad adicional a esta última clase.

7. La InterfaceUsuario envía el evento “Registrarse por primera vez” al ManejadorPrincipal.

De manera similar, la responsabilidad “envía el evento “Registrarse por primera vez” al


ManejadorPrincipal” se asigna a la InterfaceUsuario. Regresando ala discusión original de
la asignación de responsabilidades a ambas clases, Se observa que la siguiente frase no
asigna una responsabilidad de “recibir evento” a la clase ManejadorPrincipal. Por tal
motivo, se hará una segunda asignación de responsabilidad, que se llama “maneja el
evento “Registrarse por primera vez” y se asignará al ManejadorPrincipal.

8. El ManejadorPrincipal solicita CrearRegistroUsuario al ManejadorRegistroUsuario.

La responsabilidad “solicita CrearRegistroUsuarioal ManejadorRegistroUsuario” se asigna


al ManejadorPrincipal. Adicionalmente se asigna la responsabilidad CrearRegistroUsuario
al ManejadorRegistroUsuario, ya que más adelante se verá que, en el caso de uso
Registrar Usuario, subflujo Crear Registro Usuario (S-1), no se continúa con una frase que
defina la misma responsabilidad complementaria.

9. Se ejecuta el caso de uso Registrar Usuario, subflujo Crear Registro Usuario (S-1).
Esta frase no genera ninguna responsabilidad, solo una ramificación en el flujo del caso de
uso.

10. Si la actividad seleccionada es “OK”, se valida el registro de usuario mediante un login


y un password insertados por el Usuario en la PantallaPrincipal.

No se incluyen oraciones que describan responsabilidades para actores, ya que no


agregan responsabilidades.

11. La PantallaPrincipal envía el evento “OK” a la InterfaceUsuario.

La responsabilidad es “envía el evento “OK” a la InterfaceUsuario” y se asigna a


PantallaPrincipal.

12. La InterfaceUsuario envía el evento “OK” al ManejadorPrincipal.

La responsabilidad es “envía el evento “OK” al ManejadorPrincipal” y se asigna a la


InterfaceUsuario. Adicionalmente, la responsabilidad “maneja el evento “OK” y se asigna al
ManejadorPrincipal.

13. El ManejadorPrincipal solicita ValidarRegistroUsuario al ManejadorRegistroUsuario.

La responsabilidad es “solicita ValidarRegistroUsuario al ManejadorRegistroUsuario” y se


asigna a ManejadorPrincipal.

14. El ManejadorRegistroUsuario solicita ValidarRegistroUsuario a la


InterfaceBaseDatosRegistro.

La responsabilidad “solicita ValidarRegistroUsuario a la InterfaeBaseDatosRegistro” se


asigna a ManejadorRegistro Usuario.

15. La InterfaceBaseDatosRegistro solicita ValidarRegistroUsuario a la BaseDatosRegistro.

La responsabilidad es “solicita ValidarRegistroUsuario a la BaseDatosRegistro y se asigna a


InterfaceBaseDatosRegistro.

16. La Base de DatosRegistro valida al usuario y devuelve el “OK” a la


InterfaceBaseDatosRegistro.

Esta frase no agrega responsabilidades, ya que comprende un actor externo al sistema


junto con un evento de devolución.
17.La InterfaceBaseDatosRegistro devuelve el “OK” al ManejadorRegistroUsuario.

Esta frase no agrega responsabilidades, pues describe un evento de devolución

18. El ManejadorRegistroUsuario devuelve el “OK” al ManejadorPrincipal


Nuevamente, esta frase no agrega responsabilidades, pues describe un evento de
devolución.

19. Una vez validado el usuario (E-1), el ManejadorPrincipal solicita OfrecerServicios al


ManejadorServicios.

La responsabilidad es “solicita OfrecerServicios al ManejadorServicios”, la cual se asigna al


ManejadorPrincipal. Adicionalmente, se asigna la responsabilidad “OfrecerServicio” a la
clase ManejadorServicio para asegurarse que exista una responsabilidad complementaria
en esta última clase.

20. Se continúa con el caso de uso Ofrecer Servicios.

Esta es una frase que describe continuación entre casos de uso y no agrega ninguna
responsabilidad.

21. Si la actividad seleccionada es “Salir” la PantallaPrincipal envía el evento “Salir” a la


InterfaceUsuario.
La responsabilidad “envía el evento “Salir” se asigna a la InterfaceUsuario y a la Pantalla
Principal.

22. La InterfaceUsuario envía el evento “Salir” alManejadorPrincipal.

Se asigna la responsabilidad “envía el evento “Salir” al ManejadorPrincipal a la


InterfaceUsuario. Adicionalmente la responsabilidad “maneja el evento “Salir” se asigna al
ManejadorPrincipal.

23. El ManejadorPrincipal sale del sistema.

Se asigna la responsabilidad “sale del sistema” al ManejadorPrincipal.

A partir de estas frases, se obtienen las primeras responsabilidades y se insertan en las


tarjetas de clase correspondientes para lograr una versión preliminar de las tarjetas de
clase. En general, las tarjetas tienen la ventaja de forzar a la brevedad, de tal manera que
las responsabilidades se listan lo más compacto posible. En las siguientes tablas se
asignará las responsabilidades a las distintas clases.
En la figura 5 se muestran las responsabilidades ya identificadas para la clase
ManejadorPrincipal. Observe que se añade entre paréntesis el índice de la frase de la que
provienen en la descripción de los casos de uso.

Figura 5. Muestra las responsabilidades para la clase ManejadorPrincipal

La siguiente tabla muestra las responsabilidades identificadas hasta el momento para la


clase ManejadorServicio.

Figura 6. Muestra las responsabilidades para la clase ManejadorServicio hasta ahora

De esta manera se repite el proceso para cada uno de los casos de uso que componen la
descripción del problema, se van identificando las responsabilidades que se asignarán a
cada una de las clases identificadas en el sistema.
Considerando el enfoque estructurado es importante atender la siguiente información.

Descomposición modular.3

La modularidad  es  un  concepto fundamental a la hora de realizar el diseño de una


aplicación, de  hecho hoy en día la mayor parte de las metodologías de diseño  son 
modulares. Por tanto vamos a profundizar en el concepto de módulo.

El diseño modular propone dividir el sistema en partes diferenciadas y definir sus


interfaces. Sus ventajas: claridad, reducción de costos y reutilización

Los pasos a seguir son:


1. Identificar los módulos
2. Describir cada módulo
3. Describir las relaciones entre módulos

Ya hemos hablado de los mecanismos de abstracción  y  de  ocultación como piezas claves
para la definición de módulos. Sin embargo, dichos atributos deben
ser traducidos en características operacionales del módulo como son: la historia del
tiempo de incorporación, el mecanismo de activación y el camino de control .

La historia del tiempo de incorporación se refiere al tiempo en el que el módulo se incluye


dentro de una descripción en lenguaje fuente del software. Por ejemplo un módulo
definido como una macro en tiempo de compilación es incluido por el compilador en el
código  salida que genera, al interpretar una referencia puesta en el código por el que lo
desarrollo.  Un subprograma  convencional  se   incluye   mediante   la generación de un
código de enlace y bifurcación.

En cuanto a los mecanismos de activación podemos citar dos: convencionalmente, un


módulo es llamado  mediante referencia,  mientras que en las aplicaciones en tiempo real
un módulo es llamado mediante una interrupción,  que  consiste  en  que  un  suceso 
externo   causa   una discontinuidad en  el  proceso  de información  dando como
resultado el paso de control a otro módulo.

El camino de control de un módulo  describe  la  forma  en  que se ejecuta internamente.
Los módulos tradicionalmente tienen  entrada  y salida únicas, siendo ejecutados
secuencialmente como parte de una  tarea. Sin embargo,  algunas  veces  se  necesitan 
mecanismos  de  control  más sofisticados: un módulo puede ser reentrante, o lo que es lo
mismo puede ser diseñado de tal forma que no se modifique a sí mismo ni acepte
ninguna modificación externa, por lo que puede ser utilizado por más  de una tarea

3
Padrón M. (2014) 6.1 Descomposición modular. Antología Fundamentos de desarrollo de sistemas. (p. 245) Tepic.
concurrente.
Desde el punto de vista de su estructura software podemos tener:
Módulos secuenciales.
Módulos incrementales. Puede  ser   interrumpido   antes   de su finalización y
restablecido posteriormente.
Módulos paralelos. Es ejecutado simultáneamente con otro  módulo en entornos de
multiprocesadores concurrentes.
Una descomposición modular debe poseer ciertas cualidades mínimas para que se pueda
considerar suficiente validad como:
a) Independencia funcional
b) Acoplamiento
c) Cohesión
d) Comprensibilidad
e) Adaptabilidad

a) Independencia funcional
Cada módulo debe realizar una función concreta o un conjunto de funciones afines. Es
recomendable reducir las relaciones entre módulos al mínimo.
Para medir la independencia funcional hay dos criterios: acoplamiento y cohesión

b) Acoplamiento
El acoplamiento es un medida de la interconexión entre módulos en la estructura del
programa. Podemos graduarla en un amplio espectro, pero por lo general se tiende a que
el acoplamiento sea lo menor posible, esto es a reducir las interconexiones entre los
distintos módulos en que se estructure nuestra aplicación. El grado de acoplamiento mide
la interrelación entre dos módulos, según el tipo de conexión y la complejidad de la
interface puede ser Fuerte, Moderado o Débil:
Fuerte
 Por contenido, cuando desde un módulo se puede cambiar datos locales de
otro.
 Común, se emplea una zona común de datos a la que tienen acceso varios
módulos.
Moderado
 De control, la zona común es un dispositivo externo al que están ligados los
módulos, esto implica que un cambio en el formato de datos los afecta a todos.
 Por etiqueta, en intercambio de datos se realiza mediante una referencia a la
estructura completa de datos(vector, pila, árbol, grafo,…)
Débil
 De datos, viene dado por los datos que intercambian los módulos. Es el mejor.
 Sin acoplamiento directo , es el acoplamiento que no existe

c) Cohesión
Un módulo cohesivo ejecuta una tarea sencilla en un procedimiento de software y requiere
poca interacción con procedimientos que se ejecutan en otras partes de un programa.
Podemos decir que un módulo coherente es aquel que intenta realizar solamente una
cosa.
Para que número de módulos no sea demasiado elevado y complique el diseño se tratan
de agrupar elementos afines y relacionados en un mismo módulo. La cohesión puede ser:
Alta, Media y Moderada
Alta
 Cohesión abstraccional , se logra cuando se diseña el módulo como tipo abstracto
de datos o como una clase de objetos Cohesión funcional, el módulo realiza una
función concreta y específica
Media
 Cohesión secuencial, los elementos del módulo trabajan de forma secuencial
 Cohesión de comunicación, elementos que operan con el mismo conjunto de datos
de entrada o de salida
 Cohesión temporal, se agrupan elementos que se ejecutan en el mismo momento.
Por Ejemplo: .Arrancar o parar dispositivos
Baja
 Cohesión lógica, se agrupan elementos que realizan funciones similares.
 Cohesión coincidental, es la peor y se produce cuando los elementos de un
módulo no guardan relación alguna

La descripción del comportamiento de un módulo permite establecer el grado de


cohesión:
 Si es una frase compuesta y contiene más de un verbo la cohesión será MEDIA
 Si contiene expresiones secuenciales (primero, entonces, cuando…), será temporal
o secuencial
 Si la descripción no se refiere a algo específico (Ej. Todos los errores), cohesión
lógica
 Si aparece “inicializar”, “preparar”, “configurar”, probablemente sea temporal.
d) Comprensibilidad
Para facilitar los cambios, el mantenimiento y la reutilización de módulos es necesario que
cada uno sea comprensible de forma aislada. Para ello es bueno que posea independencia
funcional, pero además es deseable:
 Identificación, el nombre debe ser adecuado y descriptivo
 Documentación, debe aclarar todos los detalles de diseño e implementación que
no queden de manifiesto en el propio código
 SIMPLICIDAD, las soluciones sencillas son siempre las mejores
e) Adaptabilidad
La adaptación de un sistema resulta más difícil cuando no hay independencia funcional, es
decir, con alto acoplamiento y baja cohesión, y cuando el diseño es poco comprensible.
Otros factores para facilitar la adaptabilidad:
 Previsión, es necesario prever que aspectos del sistema pueden ser
susceptibles de cambios en el futuro, y poner estos elementos en módulos
independientes, de manera que su modificación afecte al menor número de
módulos posibles
 Accesibilidad, debe resultar sencillo el acceso a los documentos de
especificación, diseño, e implementación para obtener un conocimiento
suficiente del sistema antes de proceder a su adaptación
 Consistencia, después de cualquier adaptación se debe mantener la
consistencia del sistema, incluidos los documentos afectados

En un libro clave sobre el tema, Shaw y Garlan [Sha96] plantean lo siguiente sobre la
arquitectura del software:4

Desde el primer programa que se dividió en módulos, los sistemas de software han tenido
arquitecturas y los programadores han sido los responsables de las interacciones entre los
módulos y las propiedades globales del ensamble. Históricamente, las arquitecturas han
estado implícitas: accidentes de implementación o sistemas heredados del pasado.
Los desarrolladores de buen software han adoptado con frecuencia uno o varios patrones
de arquitectura como estrategias para la organización del sistema, pero los utilizan de
manera informal y no tienen manera de hacerlos explícitos en el sistema resultante.
En el presente, la arquitectura de software eficaz y su representación y diseño explícitos
se han vuelto los temas dominantes en la ingeniería de software.

1. Para elaborar las tarjetas de clases sigue los siguientes pasos

a. Identifica todas las clases del sistema. Utiliza el modelo de clases del
proyecto.
b. Inicia con una de las clases y completa con la información que requiere el
formato de tarjeta de clases, Incluye en este apartado las tarjetas de clases
con las responsabilidades agregadas para el proyecto integral del
semestre.
c. Repite el paso anterior para cada una de las clases del sistema.

2. Diseña el diagrama de menús para el proyecto integral del semestre por medio
de los siguientes pasos:
a. Utiliza el modelo de clases del proyecto y elabora una lista de las
funcionalidades que se requieren para cada clase
b. Organiza de manera lógica las funcionalidades enlistadas para cada clase
c. Diseña el diagrama de menús utilizando una estructura de árbol de

4
Roger S. Pressman. (2010). INGENIERÍA DEL SOFTWARE. UN ENFOQUE PRÀCTICO Séptima Edición. México D.F.:
McGRAW -HILL INTERAMERICANA EDITORES S.A. DE C.V. (p. 12)
acuerdo a los siguientes ejemplos Figura 75 y Figura 86:

Figura 7. Ejemplo Árbol de directorios

Figura 8. Ejemplo Tareas de computación

3. Integra en el reporte R3.1. cada una de las Tarjetas de clases con

5
https://www.google.com.mx/search?
q=estructura+de+arbol+informatica&rlz=1C1LENP_esMX732MX732&tbm=isch&imgil=g22XrnNtQj8kkM%253A
%253BDNh27CGV-bujGM%253Bhttp%25253A%25252F%25252Festructura-de-datos-garo.blogspot.com
%25252F2011%25252F10%25252Fel-arbol-es-una-estructura-de-datos.html&source=iu&pf=m&fir=g22XrnNtQj8kkM
%253A%252CDNh27CGV-bujGM%252C_&usg=__ZQeBK3Wdv2K_Pj9hA3_ltbV5woQ
%3D&biw=1680&bih=944&ved=0ahUKEwixzpGTysbVAhUFSiYKHcl9AEUQyjcITQ&ei=YiCJWbGVFIWUmQHJ-
4GoBA#imgdii=MtMJ31aNPaRRJM:&imgrc=R2Fubjn9X-9OHM:
6
https://www.google.com.mx/search?
q=estructura+de+arbol+informatica&rlz=1C1LENP_esMX732MX732&tbm=isch&imgil=g22XrnNtQj8kkM%253A
%253BDNh27CGV-bujGM%253Bhttp%25253A%25252F%25252Festructura-de-datos-garo.blogspot.com
%25252F2011%25252F10%25252Fel-arbol-es-una-estructura-de-datos.html&source=iu&pf=m&fir=g22XrnNtQj8kkM
%253A%252CDNh27CGV-bujGM%252C_&usg=__ZQeBK3Wdv2K_Pj9hA3_ltbV5woQ
%3D&biw=1680&bih=944&ved=0ahUKEwixzpGTysbVAhUFSiYKHcl9AEUQyjcITQ&ei=YiCJWbGVFIWUmQHJ-
4GoBA#imgdii=MtMJ31aNPaRRJM:&imgrc=R2Fubjn9X-9OHM:
responsabilidades
4. Integra el diagrama de menús diseñado.

S-ar putea să vă placă și