Contexto
El diseño de software se puede representar a través de una pirámide que está dividida en niveles del diseño. Cada nivel persigue un objetivo específico. Mientras más se acerque a la punta, el alcalce será el detalle que debe incluir.
En el caso del diseño de componentes, el ingeniero de software debe proporcionar estructuras con mayor nivel de abstracción, lo que permite diseñar algoritmos que serán utilizados cuando se construya el software.
Esta etapa del diseño de software es importante porque le permite al ingeniero de software evaluar la idoneidad de la arquitectura propuesta antes de iniciar la fase de construcción, permitiéndole evitar introducir errores que impacten a la calidad del producto.
Explicación
11.1. Perspectivas del diseño de componentes
Según Pressman (2010), un componente de software es cualquier parte de un sistema que sea modular, desplegable y sustituible, que requiere de un conjunto de interfaces para poder comunicarse con otros componentes internos o externos de un sistema.
Existen tres perspectivas relacionadas con el diseño de componentes. Cada una de ellas ofrece una visión diferente sobre cómo tratar o ver los componentes. A continuación se muestran dos de las tres perspectivas:
Visión orientada a objetos
En esta perspectiva un componente es un conjunto de clases que interactúan entre sí. Cada clase incluye atributos y operaciones que se pueden utilizar para la clase. Además se utilizan interfaces para comunicarse con otras clases.
El diseño de componentes inicia con el diagrama de clases generado en el análisis. A este diseño se le incorporan otras clases que apoyarán a las clases iniciales (clases de análisis) con otros servicios.
En el siguiente diagrama se ejemplifica cómo es que a partir de un diagrama de clases obtenido del análisis, se transforma en un diagrama de componentes y en un diagrama de clases de diseño.
El ejemplo está enfocado en generar un sistema para un taller de impresión. Observa cómo a partir de los requerimientos del usuario se determinó la necesidad de crear una clase llamada “ImprimirTrabajo”, sus atributos son los siguientes: NúmerodePáginas, NúmerodeLados, TipodePapel, Escala, CaracterísticasdeProducción. Las operaciones (métodos) son CalcularCostodelTrabajo() y PasarTrabajoImpresora.
El siguiente paso es crear un diagrama de componentes a partir de las clases de análisis. El diseñador determinó que el componente “ImprimirTrabajo” debe tener 2 interfaces, las cuales están representadas por una línea con un círculo vacío en su origen. A estas interfaces les llamó “CalcularTrabajo” e “IniciarTrabajo”. La primera establece el costo del trabajo y la segunda ordena el inicio del trabajo. Estas interfaces sirven para comunicarse con otras clases (que no se muestran en el diagrama de ejemplo).
Más abajo vuelve a aparecer un diagrama de clases, detallando la clase ImprimirTrabajo. Observa que contiene todos los atributos que se determinaron en la clase de análisis, agregando además algunos detalles necesarios, como PesodePapel, TamañodePapel y ColordePapel, entre otros. Además que incluye otras operaciones necesarias para obtener más información: CalcularCostoporPágina(), CalcularCostodelPapel(), CalcularCostodeProducción(), ElaborarOrdendeTrabajo() y VerificarPrioridad().
Elaboración de un componente de diseño. Diagrama tomado del libro de Pressman, R. (2010). Ingeniería de Software. (7ª Ed). EE.UU: McGraw Hill. Sólo para fines educativos.
Visión Tradicional
En la perspectiva tradicional, según Pressman (2010): “Un componente es elemento funcional de un programa que incorpora lógica de procesamiento”. A este componente se le conoce como módulo y se le pueden asignar 3 funciones diferentes: control, dominio del problema, e infraestructura.
Haz clic en cada concepto para conocer más detalle.
Coordina la invocación de todos los componentes.
Implanta una función total o parcial requerida por el cliente.
Contiene todas las funciones de apoyo necesarias al procesamiento requerido.
Para diseñar los componentes utilizando esta perspectiva, se requiere del Diagrama de Flujo de Datos (DFD) elaborado en el análisis. Cada nivel del diagrama es representado de forma jerárquica, y cada proceso corresponde a un componente.
En el siguiente ejemplo puedes observar cómo cada rectángulo representa un proceso del DFD, y los niveles jerárquicos corresponden a la profundidad del diagrama de flujo de datos.
El siguiente paso en el diseño de componentes tradicional es especificar con mayor detalle cada uno de los componentes a través de un módulo elaborado, que es una notación modificada UML, donde se detallan las entradas y salidas del proceso a manera de pseudocódigo. Observa que en este caso se ha tomado en cuenta el diccionario de datos para especificar la información necesaria para el cálculo del costo por página.
Haz clic en cada concepto para conocer más detalle.
Gráfica de la estructura de un sistema tradicional (izq.) y diseño en el nivel de componente para CalcularCostoporPágina (der). Diagramas tomados del libro de Pressman, R. (2010). Ingeniería de Software (7ª ed.). EE.UU: McGraw Hill. Sólo para fines educativos.
11.2 Principios del diseño
La perspectiva del diseño de componentes tiene mayor uso, dada su relación con los lenguajes orientados a objetos de última generación, como C#, C++, Java y Python. A continuación se presentan algunos de los principios del diseño de componentes orientados a objetos que ayudan a evitar introducir defectos al software y facilitan la modificación posterior:
Haz clic en cada concepto para conocer más detalle.
11.3 Lineamientos del diseño
Con el fin de facilitar el mantenimiento y legibilidad de los diagramas de componentes, se presentan los siguientes lineamientos o recomendaciones para el diseño de componentes:
Haz clic en cada concepto para conocer más detalle.
Es necesario establecer lineamientos prácticos para nombrar a los componentes durante el diseño del software.
La sugerencia de Pressman (2010) es que los nombres deben provenir del dominio del problema que pretenden solucionar, de tal suerte que contenga un significado para quienes participan del proyecto, y así sea más sencillo entender el diseño.
En este sentido es recomendable agregar títulos que puedan ser interpretados rápidamente. Palabras como << infraestructura >>, << base de datos >>, << tabla >> son términos que fácilmente pueden interpretarse por el equipo técnico.
Para facilitar la elaboración de diagramas de componentes cuando se incluyen interfaces, es recomendable realizar las siguientes modificaciones al diagrama UML para simplificarlo:
En este diagrama puedes observar que las interfaces son ObtenerDatosdelTrabajo y AccederBDdeCostos.
Para permitir que los diagramas de componentes puedan tener una mayor legibilidad, se recomienda lo siguiente:
Cierre
El diseño de componentes es parte fundamental de todo diseño modular; además, permite la reutilización de código, ya sea de otros proyectos anteriores, o bien código que puede servir para futuros proyectos.
Al fabricar software por módulos es posible que el desarrollador construya pensando en obtener la mayor flexibilidad posible y tratar de cubrir futuros requerimientos, lo que hace más tardado el proceso de construcción, además de agregar complejidad al código.
Es preferible generar un módulo que solucione una necesidad específica con interfaces a otros componentes que poner el sistema en riesgo de introducir bugs que sean difíciles de detectar.
Mantener la sencillez debe ser una prioridad en los desarrolladores de software. Si el módulo no responde a las necesidades de otros desarrollos, se deberá diseñar un componente diferente.
No hay que olvidar que gran parte del éxito en el diseño de componentes es la documentación de los objetivos, precondiciones, postcondiciones y resultados esperados. Esta sencilla información podría ser utilizada por el diseñador en otros proyectos.
Checkpoint
Asegúrate de poder:
Referencias
Glosario
Pseudocódigo: es la descripción de un algoritmo utilizando palabras de uso común que no dependen de un lenguaje de programación, facilitando la comunicación de la secuencia de pasos.
Sobrecarga de métodos: es un mecanismo que permite los lenguajes orientados a objetos, para cambiar el método de una superclase. Tiene el mismo nombre del método de la superclase, pero varía su implementación.