CAPÍTULO 5
EL DISEÑO DEL SOFTWARE
El diseño es el primer paso en la fase de desarrollo de cualquier producto o sistema de ingeniería. Se define como:
El objetivo es construir un modelo o representación de entidad que será construido más adelante.
Una característica del diseño del software es que cambia continuamente conforme aparecen nuevos métodos, mejores análisis y más conocimiento.
Se diferencia de los demás diseños en que se encuentra en una etapa muy temprana de su evolución, faltándole profundidad, flexibilidad y la naturaleza cuantitativa asociada normalmente con las disciplinas de diseño de ingenierías más clásicas.
A pesar de esto, se han propuesto algunas normas a seguir y criterios para cualificar un diseño, entre ellos los propuestos por Daris.
5.1. EL PROCESO DE DISEÑO
La importancia del diseño se basa en que en esta fase es donde se asienta la calidad del desarrollo del producto. El diseño del software sirve de base para todas las fases de desarrollo y el mantenimiento y el que asegura que el producto va a ser estable y de calidad.
El diseño es un proceso mediante el que se traducen los requisitos en una representación del software que, inicialmente es holística, para después, debido a sucesivos refinamientos, conducir a una representación próxima al código fuente.
El diseño se realiza en dos etapas:
1. Diseño preliminar:
Transformación de los requisitos en estructuras de datos y arquitectura del software.
2. Diseño detallado:
Refinamiento de las estructuras de datos y de la arquitectura de la fase anterior. Llevará al diseño procedimental.
La calidad del diseño se establecerá mediante una serie de revisiones técnicas formales. Para ello hay una serie de criterios:
§ Debe exhibir una organización jerárquica.
§ Debe ser modular.
§ Debe contener una representación distinta y separable de datos y procedimientos.
§ Debe conducir a módulos que exhiban características funcionales independientes.
§ Debe derivarse usando un método repetible conducido por la información obtenida en el análisis de requisitos.
Estas características se consiguen a base de revisiones y aplicando metodologías y herramientas. Existen muchos tipos de ´estas, pero todas tienen los siguientes puntos en común:
1. Un mecanismo de traslación de la representación del dominio de la información en representación de diseño.
2. Una notación para representar componentes e interfaces.
3. Heurísticas para el refinamiento y partición.
4. Criterios para la valoración de la calidad.
5.2. CONCEPTOS FUNDAMENTALES DEL DISEÑO
5.2.1. ABSTRACCIÓN
Actividad intelectual que permite trabajar con conceptos y no con instancias particulares de los mismos. Hay tres tipos:
§ Abstracción funcional:
Incluye el uso de subprogramas parametrizados, que permitirán aislar comportamientos iguales pero distintos resultados dependiendo de los parámetros.
§ Abstracción de datos:
Especificación de los tipos de datos u objetos eliminando detalles de la representación y manipulación. Sus características internas son visibles únicamente para las funciones que los manipulan, quedando ocultas para otros grupos que los utilicen (igual concepto que en C++ para tipos abstractos de datos). Puede haber además una jerarquización, construyéndose un tipo abstracto a partir de otros tipos abstractos.
§ Abstracción de control:
Se usa para establecer un efecto deseado sin necesidad de definir el mecanismo exacto del control. Por ejemplo las proposiciones SI o MIENTRAS.
5.2.2. OCULTACIÓN
Consiste de la ocultación de los detalles internos de cada módulo, produciéndose la comunicación intermodular a través de interfaces bien definidas.
Esta técnica se basa en que los módulos deben especificarse y diseñarse de forma que la información contenida dentro de los mismos sea inaccesible a otros módulos que no necesiten dicha información.
La ocultación ayuda a conseguir más efectividad en la modularización haciendo que se intercambie únicamente la información necesaria. Ayuda también en la tarea mantenimiento y la modificación del software y hace que los errores se propaguen con menos probabilidad.
El diseño debe comenzar con una lista de decisiones difíciles y otra con decisiones que probablemente se modifiquen. Cada módulo debe ocultar estas decisiones a los demás módulos. Además de ocultar estas decisiones se pueden considerar los siguientes puntos como sujetos a la ocultación:
§ Una estructura de datos, su ligado de datos y los detalles internos de la implementación de los procedimientos (principio de abstracción de datos).
§ El formato de bloques de control.
§ Los códigos de caracteres, el ordenamiento de conjuntos de caracteres y otros detalles de instrumentación.
§ El corrimiento y enmascaramiento de información binaria.
5.2.3. MODULARIDAD
Un sistema modular consiste en unidades claramente definidas y manejables con las interfaces claramente definidas entre los diversos módulos.
Propiedades de un sistema modular:
§ Cada abstracción de un proceso es un subsistema claramente definido y con el potencial de ser útil para otras aplicaciones.
§ Cada función en cada abstracción tiene un propósito específico, claramente definido.
§ Cada función maneja no más de una estructura de datos del sistema.
§ Las funciones comparten datos globales en forma selectiva.
§ Es fácil de identificar todas las subrutinas.
§ Las funciones que manejan instancias de un tipo abstracto de datos quedan encapsuladas con la estructura de datos en cuestión.
La modularidad es un enfoque aceptado en todas las disciplinas. Reduce la complejidad, facilita la implementación, mejora la claridad del diseño, facilita las pruebas, depuración y documentación…
Cada módulo debe tener un tamaño intermedio. Tanto entorpece la modularización a gran escala como a baja escala.
5.2.4. CONCURRENCIA
Los sistemas de programación pueden clasificarse en secuenciales y concurrentes. Los secuenciales sólo tienen en ejecución una pequeña parte de los mismos. Los concurrentes tienen procesos independientes ejecutándose simultáneamente.
Los sistemas concurrentes presentan problemas de bloqueo (varios procesadores bloqueados esperando a que otros acaben una operación), exclusión mutua (error en el acceso a una variable compartida por varios procesos) y sincronización (comunicación entre procesos lentos y rápidos).
5.2.5. VERIFICACIÓN
Un diseño es verificable si puede demostrarse que el producto satisface los requisitos del cliente. Pasos para la verificación:
1. Verificación de requisitos: Los requisitos de programación satisfacen las necesidades del cliente.
2. Verificación del diseño: El diseño satisface la definición de los requisitos.
5.2.6. ESTÉTICA
Las consideraciones estéticas como simplicidad, elegancia y claridad son fundamentales en el diseño.
Es difícil establecer criterios para evaluar factores estéticos, sin embargo un producto estéticamente agradable es fácilmente reconocido.
5.2.7. ESTRUCTURA DEL PROGRAMA
El uso de una estructuración permite que un sistema grande sea definido en términos de unidades más pequeñas y manejables con una clara definición.
La estructura de programa representa la organización de los componentes del mismo e implica una jerarquía de control. Esta estructura se puede representar de varias formas, aunque el método más común es en forma de árbol.
5.2.8. PROCEDIMIENTOS SOFTWARE
El procedimiento del software se enfoca sobre los detalles de procedimientos de cada módulo individualmente.
El procesamiento debe dar una especificación precisa del procedimiento, incluyendo secuencia de sucesos, puntos de decisiones exactos, operaciones repetitivas e incluso organización/estructura de datos.
5.2.9. REFINAMIENTO
El refinamiento sucesivo es una estrategia temprana del diseño descendente y consiste en ir refinando jerárquicamente, de forma descendente hasta llegar a sentencias del lenguaje de programación.
Cada paso de refinamiento implica algunas decisiones de diseño. A medida que se avanza en el refinamiento se amplía la declaración original, dando más detalles sobre el diseño. Por este motivo el refinamiento podría considerarse como un proceso de elaboración.
5.3. EL DISEÑO MODULAR
Se trata del método de diseño más aceptado. Un diseño modular reduce la complejidad, facilita los cambios y da como resultado una implementación más fácil, posibilitando el desarrollo paralelo de diferentes partes del sistema.
5.3.1. TIPOS DE MÓDULOS
Dentro de una estructura software un módulo puede ser categorizado como:
§ Módulo secuencial:
Se referencia y ejecuta sin interrupción aparente. Son los más frecuentes.
§ Módulo incremental (corrutina):
Puede ser interrumpido y restablecido posteriormente. Estos módulos mantienen un puntero de entrada que permite al módulo restablecer el punto de interrupción.
§ Módulo paralelo (conrutina):
Se ejecuta simultáneamente con otro u otros módulos en entornos de multiprocesadores paralelos.
Las corrutinas y conrutinas requieren unos métodos especiales de diseño desde las primeras etapas del desarrollo.
Características de los módulos:
§ Contienen instrucciones, lógica de proceso y estructuras de datos.
§ Pueden ser compilados de forma individual y usados o almacenados como bibliotecas.
§ Pueden incluirse dentro de un programa.
§ Se pueden usar invocando un nombre y cero o más parámetros.
§ Pueden usar a otros módulos.
Existen muchos criterios para definir la modularidad del sistema que van a determinar las estructuras resultantes para un sistema. Entre ellos:
§ El criterio convencional: Cada módulo junto con sus subordinados corresponden a un paso del proceso en la secuencia de ejecución.
§ El criterio de ocultación: Cada módulo oculta a otros módulos una decisión difícil o modificable del diseño.
§ El criterio de abstracción de datos: Cada módulo oculta detalles de representación y manipulación de la información.
§ Niveles de abstracción: Los módulos y colecciones de módulos proporcionan una jerarquía de servicios más complejos.
§ Acoplamiento y cohesión: Estructuración del programa para lograr la máxima cohesión y el mínimo acoplamiento.
§ Modelización de problemas: La estructura modular de un problema se ajusta a la estructura del problema a resolver.
5.3.2. INDEPENDENCIA FUNCIONAL
Es una derivación directa del concepto de modularidad y los conceptos de abstracción y ocultación de la información. Consiste en diseñar software de forma que cada módulo se enfoca a una subfunción específica de requisitos y tenga una interfaz sencilla.
La independencia funcional se mide usando criterios cualitativos de cohesión y acoplamiento.
COHESIÓN
Es una medida de la fuerza estática de un módulo. Se trata de una extensión del concepto de ocultación. Un módulo coherente ejecuta una tarea sencilla necesitando poca interacción con otros módulos. Tipos de cohesión:
§ Coincidental: Un módulo ejecuta tareas poco relacionas con otras.
§ Lógica: Un módulo ejecuta tareas relacionadas de forma lógica.
§ Temporal: Tareas relacionadas por tenerse que producir dentro de un tiempo.
§ Procedimental: Los elementos de procesamiento están relacionados y deben ejecutarse de forma secuencial.
§ Comunicación: Todos los elementos de procesamiento se concentran en un área de una estructura de datos.
§ Secuencial: Cuando la salida de un elemento es la salida para el siguiente.
Una cohesión baja provoca grandes pérdidas de eficiencia. Una cohesión media tiene una eficiencia bastante similar a la de la cohesión alta. El objetivo es por tanto conseguir una cohesión lo más alta posible y detectar y eliminar la cohesión baja.
Stevens propone una técnica útil para determinar si un módulo está acotado funcionalmente es escribir una sentencia que describa la función del módulo y luego hacer un chequeo de la misma:
1. Si la descripción está formada por una sentencia compuesta el módulo ejecutará más de una función. Por tanto tendrá una cohesión secuencial o de comunicación.
2. Si tiene palabras relativas al tiempo será una cohesión secuencial o temporal.
3. Si el predicado no contiene un objeto después del verbo será una cohesión lógica.
4. Palabras como inicializar, limpiar... indican una vinculación temporal.
ACOPLAMIENTO
El acoplamiento es una medida de la independencia relativa entre los módulos. En el diseño software se busca un acoplamiento lo más bajo posible para que sea más fácil de comprender y menos propenso a la propagación de errores. El acoplamiento se consigue mediante el paso de argumentos sencillos (datos simples).
Tipos de acoplamiento (de menor a mayo importancia):
1. No directo: Módulos independientes.
2. De datos: Paso de datos simples.
3. Por estampado: Paso de una porción de una estructura.
4. De control: Acoplamiento entre módulos y dispositivos.
5. Común: Varios módulos referencian a un área de datos global.
6. Por Contenido: Se produce cuando un módulo hace uso de control o de datos mantenidos dentro de los límites de otro módulo o bien cuando se bifurca a mitad de un módulo.
Se podría permitir hasta un acoplamiento por estampado, los demás tipos de acoplamiento deben evitarse todo lo que sea posible.
Los programas con acoplamientos considerables consumen mucho tiempo y si tienen errores son difíciles de resolver.
Fuentes del acoplamiento son debidos generalmente a decisiones en el diseño que se hacen cuando se desarrolla la estructura, aunque también puede producirse acoplamiento externo durante la codificación.
5.4. ACTIVIDADES DEL DISEÑO
5.4.1. DISEÑO DE DATOS
Es la primera, y se podría considerarse la actividad más importante del diseño, dependiendo de ésta de forma directa la complejidad y calidad del software.
Según Wasserman el proceso de diseño de datos puede se resumir en:
§ La actividad primaria es seleccionar representaciones lógicas de objetos de datos identificadas en la ER.
§ El proceso de selección puede implicar análisis de algoritmos de estructuras alternativas, el uso de módulos…
§ Identificar los módulos del programan que van a operar directamente sobre las estructuras lógicas para así restringir el ámbito del efecto de las decisiones de diseño de datos individuales.
La tarea de diseño de datos suele formar parte del análisis de requisitos. Un buen diseño conduce a que el software tenga una buena estructura, modularidad y menor complejidad procedimental.
Un diseño de datos debe cumplir los siguientes puntos:
1. Los métodos de análisis sistemático aplicado al software deben aplicarse también a datos.
2. Deben identificarse todas las estructuras de datos y operaciones sobre ellas.
3. Debe establecerse y crearse un diccionario de datos.
4. Las decisiones de diseño de datos a bajo nivel deben retrasarse a las últimas etapas del diseño.
5. La representación de la estructura de datos debe ser conocida sólo por los módulos que hagan uso directo de ella.
6. Debe desarrollarse una biblioteca de datos útiles o reusables y operaciones que se pueden realizar con ellos.
7. El diseño software lenguaje usado deben soportar operaciones con tipos abstractos de datos.
5.4.2. DISEÑO ARQUITECTÓNICO
Su objetivo es desarrollar una estructura de programa modular y representar las relaciones de control entre los módulos. El diseño arquitectónico mezcla la estructura del programa y la estructura de datos y define las interfaces que facilitan el flujo de datos a lo largo del programa, lo que aporta una visión general del programa.
5.4.3. DISEÑO PROCEDIMENTAL
Se realiza después de establecer la estructura del programa y de los datos.
Consiste en una descripción completa y sin ambigüedades de los distintos algoritmos en lenguaje natural, pero es el uso del lenguaje natural el que provoca las ambigüedades, pues muchas interpretaciones dependen del contexto donde se hagan.
Esto ha dado lugar a numerosas investigaciones, algunas como la de Dijkstra que propone un conjunto de construcciones lógicas con las que se puede formar cualquier programa.
En otras técnicas se combinan diagramas de flujos y lenguaje natural para definiciones más complejas.
No hay comentarios:
Publicar un comentario