Diseño de los
Objetos
- Diseño del
Sistema - Definición de
subsistema - Identificación de la
concurrencia - Almacenamiento de
datos - Administración de los
recursos - Software de
control - Diseño De Los
Objetos - Algoritmos
- Controles
- Asociaciones
- Bibliografía
El diseño
del sistema es la
estrategia de
alto nivel para resolver problemas y
construir una solución. Éste incluye decisiones
acerca de la
organización del sistema en
subsistemas, la asignación de subsistemas a componentes
hardware y
software, y
decisiones fundamentales conceptuales y de política que son las
que constituyen un marco de trabajo para el diseño
detallado
La organización global del sistema es lo que
se denomina la arquitectura del
sistema. Existe un cierto número de estilos frecuentes de
arquitectura,
cada uno de los cuales es adecuado para ciertas clases de
aplicaciones. Una forma de caracterizar una aplicación es
por la importancia relativa de sus modelos de
objetos, dinámico y funcional. Las distintas arquitecturas
ponen distintos grados de énfasis en los tres modelos.
El diseño de
sistemas es la primera fase de diseño en la cual se
selecciona la aproximación básica para resolver el
problema. Durante el diseño del sistema, se decide la
estructura y
el estilo global. La arquitectura del sistema es la
organización global del mismo en componentes llamados
subsistemas. La arquitectura proporciona el contexto en el cual
se toman decisiones más detalladas en una fase posterior
del diseño. AL tomar decisiones de alto nivel que se
apliquen a todo el sistema, el diseñador desglosa el
problema en subsistemas, de tal manera que sea posible realizar
más trabajo por parte de varios diseñadores que
trabajarán independientemente en distintos subsistemas. El
diseñador de sistemas debe
tomar las siguientes decisiones:
– Organizar el sistema en subsistemas
– Identificar la concurrencia inherente al
problema
– Asignar los subsistemas a los procesadores y
tareas
– Seleccionar una aproximación para la
administración de almacenes de
datos
– Manejar el acceso a recursos
globales
– Seleccionar la implementación de control en
software
– Manejar las condiciones de contorno
– Establecer la compensación de
prioridades
En todas las aplicaciones, salvo en las más
pequeñas, el primer paso para diseñar un sistema
consiste en dividir el sistema en un pequeño número
de componentes. Cada uno de los componentes principales de un
sistema se llama subsistema. Cada subsistema abarca aspectos del
sistema que comparten alguna propiedad
común.
Un subsistema no es ni una función ni
un objeto, sino un paquete de clases, asociaciones, operaciones,
sucesos y restricciones interrelacionados, y que tienen una
interfaz razonablemente bien definida y pequeña con los
demás subsistemas. Normalmente, un subsistema se
identifica por los servicios que
proporciona. Un servicio es un
grupo de
funciones
relacionadas que comparten algún propósito
común, tal como el procesamiento de entrada-salida,
dibujar imágenes o
efectuar cálculos aritméticos. Un subsistema define
una forma coherente de examinar un aspecto del
problema.
Cada subsistema posee una interfaz bien definida con el
resto del sistema. Ésta especifica la forma de todas las
interacciones y el flujo de información entre los límites de
subsistemas, pero no especifica cómo está
implementado internamente el subsistema. Cada subsistema se puede
diseñar, entonces, independientemente, sin afectar a los
demás.
Los subsistemas deberían definirse de tal manera
que la mayoría de las interacciones se produzcan dentro de
y no entre los límites de
distintos subsistemas, con objeto de reducir las dependencias
existentes entre ellos. Todo sistema debería dividirse en
un pequeño número de subsistemas. Cada subsistema,
a su vez, debe descomponerse en subsistemas propios aún
más pequeños. Los subsistemas de más bajo
nivel se denominan módulos.
La relación entre dos subsistemas puede ser
cliente-proveedor
o punto a punto. En las primeras, el cliente debe
conocer la interfaz del proveedor, pero éste no necesita
conocer las interfaces de aquellos porque todas las interacciones
son iniciadas por los clientes,
empleando la interfaz del proveedor. En una relación entre
pares, cada subsistema puede llamar a los demás. Una
comunicación desde un subsistema hacia otro
no va necesariamente seguida por una respuesta inmediata. Las
interacciones entre pares son más complejas porque los
subsistemas deben conocer las interfaces del otro. Hay ciclos de
comunicaciones
que son difíciles de entender y proclives a sutiles
errores de diseño. Hay que buscar descomposiciones
cliente-proveedor siempre que sea posible, porque una
interacción monodireccional es mucho más
fácil de construir, comprender y modificar que una
interacción bidireccional.
Identificación de la
concurrencia
EN el modelo de
análisis, al igual que en el mundo real y
en el hardware,
todos los objetos son concurrentes. En una implementación,
sin embargo, no todos los objetos del software son concurrentes,
porque un procesador puede
dar soporte a muchos objetos. En la práctica, se pueden
implementar muchos objetos en un único procesador si los
objetos no pueden estar activados a la vez. Un objetivo
importante del diseño del sistema es identificar los
objetos que deben estar activados concurrentemente, y los objetos
que tienen actividad que sea mutuamente exclusiva. Estos
últimos objetos se pueden plegar y juntar en un
único hilo de control o
tarea.
Cada subsistema concurrente debe ser asociado a una
unidad de hardware, bien a un procesador de propósito
general o a una unidad funcional especializada. El
diseñador del sistema deberá:
– Estimar las necesidades de rendimiento y los recursos
necesarios para satisfacerlas
– Seleccionar las implementaciones de hardware o de
software para los subsistemas
– Asignar los subsistemas de software a los procesadores para
satisfacer las necesidades de rendimiento y para minimizar
la
comunicación entre procesadores
– Determinar las conexiones de las unidades
físicas que implementan los subsistemas.
Los almacenes de
datos internos
y externos dentro de un sistema proporcionan puntos limpios de
separación entre subsistemas con interfaces bien
definidas. En general, todo almacén de
datos puede
combinar estructuras de
datos, archivos y
bases de datos
implementados en memoria o bien en
dispositivos de
almacenamiento secundario. Los distintos tipos de almacenes
de datos proporcionan diversas compensaciones entre costo, tiempo de acceso,
capacidad y fiabilidad.
Los archivos son una
forma de almacenamiento de
datos barata, sencilla y permanente. Sin embargo, las operaciones de
archivos son de bajo nivel y las aplicaciones deben incluir un
código
adicional para proporcionar un nivel de abstracción
adecuado. Las implementaciones de los archivos son distintas
según los diferentes sistemas de
computadoras,
así que las aplicaciones transportables deben de aislar
cuidadosamente las dependencias con sistemas de archivos. Las
implementaciones para archivos secuenciales son las más
comunes, pero las ordenes y los formatos de almacenamiento
para ficheros de acceso aleatorio e indexados varían
mucho.
Las bases de datos,
que son administradas mediante sistemas de gestión
de bases de datos, son otro tipo de almacenamiento. Existen
varios tipos de sistemas de gestión
disponibles comercialmente: jerárquicos, en red, relacionales,
orientados a objetos y lógicos. Estos sistemas intentan
reservar los datos de acceso frecuente en memoria, con
objeto de alcanzar la mejor combinación posible de
costo y
rendimiento desde y hacia la memoria y
el almacenamiento en disco. Las bases de datos son potentes y
hacen que las aplicaciones sean más fáciles de
transportar a sistemas
operativos y a distintas plataformas, por cuanto el vendedor
transporta el código
del sistema de gestión. Una desventaja es que tienen una
interfaz compleja.
Las siguientes líneas generales caracterizan el
tipo de datos que pertenece a una base de datos
formal:
– Datos que requieran un acceso a niveles finos de
detalle por parte de múltiples usuarios
– Datos que puedan ser administrados eficientemente
mediante ordenes de un sistema gestor de base de datos
– Datos que deban transportarse a través de
múltiples sistemas
operativos y muchas plataformas hardware
– Datos a los que deba acceder más de un programa de
aplicación
Las siguientes líneas caracterizan las clases de
datos que pertenecen a un archivo y no a
una base de datos
relacional:
– Datos que sean voluminosos respecto a cantidad pero
difíciles de estructurar en los confines de un sistema de
datos.
– Datos que sean voluminosos en cantidad y con una baja
densidad de
formación
– Datos crudos que estén resumidos en la base de
datos
– Datos volátiles que se mantengan durante un
corto periodo de tiempo y se
descarten después.
Administración de los
recursos
El diseñador de sistemas debe identificar los
recursos globales y tiene que determinar mecanismos para
controlar el acceso a ellos. Entre los recursos globales se
cuentan: unidades físicas, tales como procesadores,
unidades de cinta y satélites
de comunicación; espacio, tal como el espacio
en disco, una pantalla de una estación de trabajo, y los
botones de un ratón; nombres lógicos, tales como la
identificación de los objetos, nombres de archivos y
nombres de clases; y el acceso a datos compartidos, tales como
bases de datos.
Si el recurso es un objeto físico se puede
controlar a sí mismo estableciendo un protocolo para
obtener el acceso dentro de un sistema concurrente. SI el recurso
es una entidad lógica,
tal como la identidad de
un objeto, o una base de datos, existe el peligro de que el
acceso produzca conflictos en
un entorno compartido. Podría ser, por ejemplo, que varias
tareas independientes utilizasen simultáneamente la misma
identidad de
un objeto. Todo recurso global debe ser poseído por un
objeto guardián que controle el acceso a éste. Un
objeto guardián puede controlar varios recursos. Todo el
acceso al recurso debe pasar a través del objeto
guardián. Por ejemplo, la mayoría de los
administradores de bases de datos son tareas libres a las cuales
invocan otras tareas para obtener datos de la base de datos. La
asignación de cada recurso global compartido a un
único objeto es un reconocimiento de que ese recurso tiene
una identidad.
Un recurso lógico también se puede
descomponer lógicamente, de forma que los subconjuntos se
asignan a distintos objetos guardianes para ser controlados de
modo independiente.
En una aplicación en la cual el tiempo sea
crítico, el costo de pasar todo el acceso a un recurso a
través de un objeto guardián resulta a veces
excesivo, por lo que los clientes deben
acceder directamente al recurso. En este caso, se pueden situar
bloqueos en subconjuntos del recurso. Un bloqueo es un objeto
lógico asociado con algún subconjunto definido de
algún recurso que proporciona a quien posea el bloqueo el
derecho de acceder directamente a ese recurso. Sigue siendo
necesario que exista un objeto guardián para asignar los
bloqueos, pero tras una interacción con el guardián
para obtener un bloqueo, el usuario del recurso puede acceder
directamente al recurso. Esta aproximación es más
peligrosa porque hay que confiar en que todos los usuarios de
recursos se comporten correctamente en su acceso al mismo. El uso
de accesos directos a recursos compartidos no debe de propugnarse
en un diseño orientado a objetos a no ser que resulte
absolutamente necesario.
Durante el análisis, todas las interacciones se
muestran como sucesos entre objetos. El control del hardware se
parece mucho al modelo de
análisis, aunque el diseñador de sistemas de be
escoger entre varias maneras de implementar el control en
software. Aún cuando no existe una necesidad lógica
de que todos los subsistemas utilicen la misma
implementación, lo normal es que el diseñador
seleccione un único estilo de control. Existen dos clases
de flujos de control en un sistema de software: el control
externo y el interno.
El control externo es el flujo de los sucesos
externamente visibles entre los objetos del sistema. Existen tres
clases de control para sucesos externos: secuencial, controlado
por procedimientos,
secuencial controlado por sucesos, y concurrente. El estilo de
control que se adopte dependerá de los recursos
disponibles y de la trama de interacciones existentes en la
aplicación.
El control
interno es el flujo de control dentro de un proceso. Solo
existe en la implementación y, por tanto, no es
inherentemente concurrente ni secuencial. El diseñador
puede decidir descomponer un proceso en
varias tareas por claridad lógica o por rendimiento. A
diferencia de los sucesos externos, las transferencias internas
de control, tales como las llamadas a procedimientos o
las llamadas entre tareas, están dirigidas por el programa y se
pueden estructurar de la forma que más convenga. Son
frecuentes tres clases de control de flujo: llamadas a
procedimientos, llamadas entre tareas que son casi concurrentes y
llamadas entre tareas concurrentes. Las llamadas entre tareas
casi concurrentes, tales como las corrutinas o procesos
ligeros, son conveniencias de programación en las cuales existen
múltiples espacios de direcciones o pilas de llamada,
pero en las que solamente puede estar activo un hilo de control
en cada momento.
La fase de análisis determina lo que debe hacer
la implementación y la fase de diseño del sistema
determina el plan de ataque.
La fase de diseño de objetos determina las definiciones
completas de las clases y asociaciones que se utilizarán
en la implementación, así como las interfaces y
algoritmos de
los métodos
utilizados para implementar las operaciones. La fase de
diseño de objetos añadirá objetos internos
para la implementación y optimizará las estructuras de
datos y los algoritmos. El
diseño de objetos es análogo a la fase preliminar
de diseño del ciclo de vida
de desarrollo de
software tradicional.
Aspectos generales del diseño de
objetos
Durante el diseño de objetos, se ejecuta la
estrategia
seleccionada durante el diseño del sistema y se rellenan
los detalles. Se produce un desplazamiento del énfasis
pasando de los conceptos del dominio de la
aplicación a los propios de las computadoras.
Los objetos descubiertos durante el análisis sirven como
esqueleto del diseño, pero el diseñador debe
escoger distintas formas de implementarlos con el objetivo de
minimizar el tiempo de ejecución, la memoria y
el costo. En particular, las operaciones identificadas durante el
análisis deben expresarse en forma de algoritmos,
descomponiendo las operaciones complejas en operaciones internas
más sencillas. Las clases, atributos y asociaciones del
análisis deben de implementarse en forma de estructuras de
datos específicas. Es necesario introducir nuevas clases
de objetos para almacenar resultados intermedios durante la
ejecución del programa y para evitar la necesidad de
recalcularlos. La optimización del diseño no
debería llevarse a extremos exagerados porque la facilidad
de implementación y mantenimiento
y la extensibilidad son también objetivos
importantes.
Cada operación especificada en el modelo
funcional debe ser formulada como un algoritmo. El
análisis de especificaciones dice lo que hace la
operación desde el punto de vista de sus clientes y los
algoritmos muestran cómo se hace. Un algoritmo se
puede subdividir en llamadas a operaciones más sencillas y
así sucesivamente, hasta que las operaciones del nivel
más bajo sean suficientemente sencillas para
implementarlas directamente sin más
refinamiento.
El diseñador de algoritmos debe:
– Seleccionar algoritmos que minimicen el costo de
implementar las operaciones
– Seleccionar estructuras de datos adecuadas para los
algoritmos
– Definir nuevas clases y operaciones internas
según sea necesario
– Asignar la responsabilidad de las operaciones a las clases
adecuadas
El diseñador debe refinar la estrategia para
implementar los modelos de estados y sucesos presentes en el
modelo dinámico. Como parte del diseño del sistema,
se habrá seleccionado una estrategia básica para
construir el modelo dinámico. Durante el diseño de
objetos, es necesario desarrollar esta estrategia.
Para implementar el modelo dinámico hay tres
aproximaciones básicas:
– Utilizar la posición dentro del programa para
almacenar el estado
(sistema controlado por procedimientos
– Implementación directa de un mecanismo de
máquina de estados (sistema controlado por
sucesos)
– Utilización de tareas concurrentes
Las asociaciones son el pegamento de nuestro modelo de
objetos, y proporcionan vías de acceso entre objetos
siendo entidades conceptuales útiles para el modelado y el
análisis. Durante la fase de diseño de objetos hay
que formularse una estrategia para implementar las asociaciones
habidas en el modelo de objetos. Se puede seleccionar una
estrategia global para implementar todas las asociaciones
uniformemente o bien seleccionar una técnica particular
para cada asociación, teniendo en cuenta la forma en que
será utilizada en la aplicación. Para tomar
decisiones inteligentes acerca de las asociaciones se necesita
analizar primero la forma en que serán
utilizadas.
"Modelado y Diseño Orientados a
Objetos"
James Rumbaugh et al
Ed. Prentice Hall 1997
Octavio Mancilla González
Universidad Tecnológica de
México