Unidad 5: Cohesión

 

5.0 Introducción: Relación Funcional

Hemos visto que la determinación de módulos en un sistema no es arbitraria. La manera en la cual dividimos físicamente un sistema en piezas (particularmente en relación con la estructura del problema) puede afectar significativamente la complejidad estructural del sistema resultante, así como el número total de referencias intermodulares.

Adaptar el diseño del sistema a la estructura del problema (o estructura de la aplicación, o dominio del problema) es una filosofía de diseño sumamente importante. A menudo encontramos que elementos de procesamiento del dominio de problema altamente relacionados, son trasladados en código altamente interconectado. Las estructuras que agrupan elementos del problema altamente interrelacionados, tienden a ser modularmente efectivas.

Imaginemos que tengamos una magnitud para medir el grado de relación funcional existente entre pares de módulos. En términos de tal medida, diremos que sistema más modularmente efectivo será aquel cuya suma de relación funcional entre pares de elementos que pertenezcan a diferentes módulos sea mínima. Entre otras cosas, esto tiende a minimizar el número de conexiones intermodulares requeridas y el acoplamiento intermodular.

Esta relación funcional intramodular se conoce como cohesión.

La cohesión es la medida cualitativa de cuan estrechamente relacionados están los elementos internos de un módulo.

Otros términos utilizados frecuentemente son "fuerza modular", "ligazón", y "funcionalidad".

En la práctica un elemento de procesamiento simple aislado, puede estar funcionalmente relacionado en diferentes grados a otros elementos. Como consecuencia, diferentes diseñadores, con diferentes "visiones" o interpretaciones de un mismo problema, pueden obtener diferentes estructuras modulares con diferentes niveles de cohesión y acoplamiento. A esto se suma el inconveniente de que muchas veces es difícil evaluar el grado de relación funcional de un elemento respecto de otro.

La cohesión modular puede verse como el cemento que amalgama juntos a los elementos de procesamiento dentro de un mismo módulo. Es el factor más crucial en el diseño estructurado, y el de mayor importancia en un diseño modular efectivo.

Este concepto representa la técnica principal que posee un diseñador para mantener su diseño lo más semánticamente próximo al problema real, o dominio de problema.

Claramente los conceptos de cohesión y acoplamiento están íntimamente relacionados. Un mayor grado de cohesión implica uno menor de acoplamiento. Maximizar el nivel de cohesión intramodular en todo el sistema resulta en una minimización del acoplamiento intermodular.

Matemáticamente el cálculo de la relación funcional intramodular (cohesión), involucra menos pares de elementos a los cuales debe aplicarse la medida, en comparación con el cálculo de la relación funcional intermodular (acoplamiento).

Ambas medidas son excelentes herramientas para el diseño modular efectivo, pero de las dos la más importante y extensiva es la cohesión.

Una cuestión importante a determinar es como reconocer la relación funcional.

El principio de cohesión puede ponerse en práctica con la introducción de la idea de un principio asociativo.

En la decisión de poner ciertos elementos de procesamiento en un mismo módulo, el diseñador, utiliza el principio de que ciertas propiedades o características relacionan a los elementos que las poseen. Esto es, el diseñador pondrá el objeto Z en el mismo módulo que X e Y, porque X, Y, y Z poseen un misma propiedad. De esta manera, el principio asociativo es relacional, y es usualmente verificable en tales términos (p.e. "es correcto poner Z junto a X e Y, porque tiene la misma propiedad que ellos") o en términos de miembro de un conjunto (p.e."es correcto poner Z junto a X e Y, pues todos pertenecen al mismo conjunto").

Debe tenerse en mente que la cohesión se aplica sobre todo el módulo, es decir sobre todos los pares de elementos. Así, si Z está relacionado a X e Y, pero no a A, B, y C, los cuales pertenecen al mismo módulo, la inclusión de Z en el módulo, redundará en baja cohesión del mismo.

Intencionalmente se ha usado el término "elemento de procesamiento" en esta discusión, en lugar de términos más comunes como instrucción o sentencia. Porqué:

Primero, un elemento de procesamiento puede ser algo que debe ser realizado en un módulo pero que aún no ha sido reducido a código. En orden de diseñar sistemas altamente modulares, debemos poder determinar la cohesión de módulos que todavía no existen.

Segundo, elementos de procesamiento incluyen todas las sentencias que aparecen en un módulo, no solo el procesamiento realizado por las instrucciones ejecutadas dentro de dicho módulo, si no también las que resultan de la invocación de subrutinas.

Por ejemplo, las sentencias individuales encontradas en el módulo B, el cual es invocado desde el módulo A, NO figuran dentro de la cohesión del módulo A. Sin embargo el procesamiento global (función) realizado por la llamada al módulo B, es claramente un elemento de procesamiento en el módulo llamador A, y por lo tanto participa en la cohesión del módulo A.

5.1 Niveles de Cohesión

Diferentes principios asociativos fueron desenvolviéndose a través de los años por medio de la experimentación, argumentos teóricos, y la experiencia práctica de muchos diseñadores.

Existen siete niveles de cohesión distinguibles por siete principios asociativos. Estos se listan a continuación en orden creciente del grado de cohesión, de menor a mayor relación funcional:

Cohesión Casual (la peor)
Cohesión Lógica (sigue a la peor)
Cohesión Temporal (de moderada a pobre)
Cohesión de Procedimiento (moderada)
Cohesión de Comunicación (moderada a buena)
Cohesión Secuencial
Cohesión Funcional (la mejor)

Podemos visualizar el grado de cohesión como un espectro que va desde un máximo a un mínimo.

 

5.1.1 Cohesión Casual (la peor)

La cohesión casual ocurre cuando existe poca o ninguna relación entre los elementos de un módulo.

La cohesión casual establece un punto cero en la escala de cohesión.

Es muy difícil encontrar módulos puramente casuales. Puede aparecer como resultado de la modularización de un programa ya escrito, en el cual el programador encuentra un determinada secuencia de instrucciones que se repiten de forma aleatoria, y decide por lo tanto agruparlas en una rutina.

Otro factor que influenció muchas veces la confección de módulos casualmente cohesivos, fue la mala práctica de la programación estructurada, cuando los programadores mal entendían que modularizar consistía en cambiar las sentencias GOTO por llamadas a subrutinas

Finalmente diremos que si bien en la práctica es difícil encontrar módulos casualmente cohesivos en su totalidad, es común que tengan elementos casualmente cohesivos. Tal es el caso de operaciones de inicialización y terminación que son puestas juntas en un módulo superior.

Debemos notar que si bien la cohesión casual no es necesariamente perjudicial (de hecho es preferible un programa casualmente cohesivo a uno lineal), dificulta las modificaciones y mantenimiento del código.

 

5.1.2 Cohesión Lógica (sigue a la peor)

Los elementos de un módulo están lógicamente asociados si puede pensarse en ellos como pertenecientes a la misma clase lógica de funciones, es decir aquellas que pueden pensarse como juntas lógicamente.

Por ejemplo, se puede combinar en un módulo simple todos los elementos de procesamiento que caen en la clase de "entradas", que abarca todas las operaciones de entrada.

Podemos tener un módulo que lea desde consola una tarjeta con parámetros de control, registros con transacciones erróneas de un archivo en cinta, registros con transacciones válidas de otro archivo en cinta, y los registros maestros anterior de un archivo en disco. Este módulo que podría llamarse "Lecturas", y que agrupa todas las operaciones de entrada, es lógicamente cohesivo.

La cohesión lógica es más fuerte que la casual, debido a que representa un mínimo de asociación entre el problema y los elementos del módulo. Sin embargo podemos ver que un módulo lógicamente cohesivo no realiza una función específica, sino que abarca una serie de funciones.

 

5.1.3 Cohesión Temporal (de moderada a pobre)

Temporal cohesión significa que todos los elementos de procesamiento de una colección ocurren en el mismo período de tiempo durante la ejecución del sistema. Debido a que dicho procesamiento debe o puede realizarse en el mismo período de tiempo, los elementos asociados temporalmente pueden combinarse en un único módulo que los ejecute a la misma vez.

Existe una relación entre cohesión lógica y la temporal, sin embargo, la primera no implica una relación de tiempo entre los elementos de procesamiento. La cohesión temporal es más fuerte que la cohesión lógica, ya que implica un nivel de relación más: el factor tiempo. Si embargo la cohesión temporal aún es pobre en nivel de cohesión y acarrea inconvenientes en el mantenimiento y modificación del sistema.

Un ejemplo común de cohesión temporal son las rutinas de inicialización (start-up) comúnmente encontradas en la mayoría de los programas, donde se leen parámetros de control, se abren archivos, se inicializan variables contadores y acumuladores, etc.

 

5.1.4 Cohesión de Procedimiento (moderada)

Elementos de procesamiento relacionados proceduralmente son elementos de una unidad procedural común. Estos se combinan en un módulo de cohesión procedural. Una unidad procedural común puede ser un proceso de iteración (loop) y de decisión, o una secuencia linear de pasos. En este último caso la cohesión es baja y es similar a la cohesión temporal, con la diferencia que la cohesión temporal no implica una determinada secuencia de ejecución de los pasos.

Al igual que en los casos anteriores, para decir que un módulo tiene solo cohesión procedural, los elementos de procesamiento deben ser elementos de alguna iteración, decisión, o secuencia, pero no deben estar vinculados con ningún principio asociativo de orden superior.

La cohesión procedural asocia elementos de procesamiento sobre la base de sus relaciones algorítmicas o procedurales.

Este nivel de cohesión comúnmente se tiene como resultado de derivar una estructura modular a partir de modelos de procedimiento como ser diagramas de flujo, o diagramas Nassi-Shneiderman.

 

5.1.5 Cohesión de Comunicación (moderada a buena)

Ninguno de los niveles de cohesión discutidos previamente están fuertemente vinculados a una estructura de problema en particular. Cohesión de Comunicación es el menor nivel en el cual encontramos una relación entre los elementos de procesamiento que es intrínsecamente dependiente del problema.

Decir que un conjunto de elementos de procesamiento están vinculados por comunicación significa que todo los elementos operan sobre el mismo conjunto de datos de entrada o de salida.

fig5-1.jpg (7966 bytes)

En el diagrama de la figura podemos observar que los elementos de procesamiento 1, 2, y 3, están asociados por comunicación sobre la corriente de datos de entrada, en tanto que 2, 3, y 4 se vinculan por los datos de salida.

Los diagramas de flujo de datos (DFD) son un medio objetivo para determinar si los elementos en un módulo están asociados por comunicación.

Las relaciones por comunicación presentan un grado de cohesión aceptable.

La cohesión por comunicación es común en aplicaciones comerciales. Ejemplos típicos pueden ser

un módulo que imprima o grabe un archivo de transacciones
un módulo que reciba datos de diferentes fuentes, y los transforme y ensamble en una línea de impresión.

 

5.1.6 Cohesión Secuencial

El siguiente nivel de cohesión en la escala es la asociación secuencial. En ella, los datos de salida (resultados) de un elemento de procesamiento sirven como datos de entrada al siguiente elemento de procesamiento.

En términos de un diagrama de flujo de datos de un problema, la cohesión secuencial combina una cadena linear de sucesivas transformaciones de datos.

Este es claramente un principio asociativo relacionado con el dominio del problema.

 

5.1.7 Cohesión Funcional (la mejor)

En el límite superior del espectro de relación funcional encontramos la cohesión funcional. En un módulo completamente funcional, cada elemento de procesamiento, es parte integral de, y esencial para, la realización de una función simple.

En términos prácticos podemos decir que cohesión funcional es aquella que no es secuencial, por comunicación, por procedimiento, temporal, lógica, o casual.

Los ejemplos más claros y comprensibles provienen del campo de las matemáticas. Un módulo para realizar el cálculo de raíz cuadrada ciertamente será altamente cohesivo, y probablemente, completamente funcional. Es improbable que haya elementos superfluos más allá de los absolutamente esenciales para realizar la función matemática, y es improbable que elementos de procesamiento puedan ser agregados sin alterar el cálculo de alguna forma.

En contraste un módulo que calcule raíz cuadrada y coseno, es improbable que sea enteramente funcional (deben realizarse dos funciones ambiguas).

En adición a estos ejemplos matemáticos obvios, usualmente podemos reconocer módulos funcionales que son elementales en naturaleza. Un módulo llamado LEER-REGISTRO-MAESTRO, o TRATAR-TRANS-TIPO3, presumiblemente serán funcionalmente cohesivos, en cambio TRATAR-TODAS-TRANS presumiblemente realizará más de una función y será lógicamente cohesivo.

5.2 Criterios para establecer el grado de cohesión

Una técnica útil para determinar si un módulo está acotado funcionalmente es escribir una frase que describa la función (propósito) del módulo y luego examinar dicha frase. Puede hacerse la siguiente prueba:

  1. Si la frase resulta ser una sentencia compuesta, contiene una coma, o contiene más de un verbo, probablemente el módulo realiza más de una función; por tanto, probablemente tiene vinculación secuencial o de comunicación.
  2. Si la frase contiene palabras relativas al tiempo, tales como "primero", "a continuación", "entonces", "después", "cuando", "al comienzo", etc., entonces probablemente el módulo tiene una vinculación secuencial o temporal.
  3. Si el predicado de la frase no contiene un objeto específico sencillo a continuación del verbo, probablemente el módulo esté acotado lógicamente. Por ejemplo editar todos los datos tiene una vinculación lógica; editar sentencia fuente puede tener vinculación funcional.
  4. Palabras tales como "inicializar", "limpiar", etc., implican vinculación temporal.

Los módulos acotados funcionalmente siempre se pueden describir en función de sus elementos usando una sentencia compuesta. Pero si no se puede evitar el lenguaje anterior, siendo aún una descripción completa de la función del módulo, entonces probablemente el módulo no esté acotado funcionalmente.

Es importante notar que no es necesario determinar el nivel preciso de cohesión. En su lugar, lo importante es intentar conseguir una cohesión alta y saber reconocer la cohesión baja, de forma que se pueda modificar el diseño del software para que disponga de una mayor independencia funcional.

5.3 Comparación de Niveles de Cohesión

Utilizaremos el problema representado en la siguiente figura para ilustrar una variedad de particionamientos del mismo problema, correspondiente a diferentes niveles de cohesión.

Es fácil presentar ejemplos de cohesión casual y lógica particionando el diagrama de flujo de datos. El módulo "HacerAlgo" es un ejemplo de cohesión casual. Los módulos "FormatearReportes" y "Editar_y_Validar" son ejemplos de cohesión lógica.

Debido a que el DFD es inherentemente no procedural, es un tanto difícil visualizar en él relaciones temporales y procedurales. Dos posibilidades serían los módulos "Comenzar" (temporal) y "SumLoop" (procedural).

Cohesión secuencial y de comunicación es fácilmente visible en un DFD. Los módulos "DoCombo" y "ObtenerMaestroVálido" son ejemplos de cohesión de comunicación y secuencial respectivamente.

La identificación de cohesión funcional presenta una vez más dificultades. En un nivel superficial, la cohesión funcional sería equivalente a que cada transformación del DFD se corresponda con un módulo, pero un particular arreglo de estos en una jerarquía influencia la cohesión actual de módulos. Estos problemas pueden comprenderse mejor con los conceptos estratégicos introducidos en el capítulo dedicado a morfologías y metodologías.

fig5-2.jpg (32413 bytes)

 

HacerAlgo : cohesión casual

Editar_y_Validar: cohesión lógica

FormatearReportes: Cohesión lógica

 

fig5-3.jpg (27562 bytes)

Comenzar: cohesión temporal

SumLoop: cohesión procedural

 

fig5-4.jpg (26890 bytes)

 

ObtenerMaestroVálido: cohesión secuencial

DoCombo: cohesión de comunicación

5.4 Medición de Cohesión

Cualquier módulo, rara vez verifica un solo principio asociativo. Sus elementos pueden estar relacionados por una mezcla de los siete niveles de cohesión. Esto lleva a tener una escala continua en el grado de cohesividad más que una escala con siete puntos discretos.

Donde existe más de una relación entre un par de elementos de procesamiento, se aplica el máximo nivel que alcanzan. Por esto, si un módulo presenta cohesión lógica entre todos sus pares de elementos de procesamiento, y a su vez presenta cohesión de comunicación también entre todos dichos pares, entonces dicho módulo es considerado como de cohesión por comunicación.

Ahora, cuál sería la cohesión de dicho módulo si también contiene algún par de elementos completamente no relacionados? En teoría, debería tener algún tipo de promedio entre la cohesión de comunicación y la casual. Para propósitos de depuración, mantenimiento, y modificación, un módulo se comporta como si fuera "solo tan fuerte como sus vínculos más débiles".

El efecto sobre los costos de programación es próximo al menor nivel de cohesión aplicable dentro del módulo en vez del mayor nivel de cohesión.

La cohesión de un módulo es aproximada al nivel más alto de cohesión que es aplicable a todos los elementos de procesamiento dentro del módulo.

Un módulo puede consistir de varias funciones completas relacionadas lógicamente. Esto es definitivamente más cohesivo que un módulo que liga lógicamente fragmentos de varias funciones.

La decisión de que nivel de cohesión es aplicable a un módulo dado requiere de cierto juicio humano. Algunos criterios establecidos son:

- la cohesión secuencial es más próxima al óptimo funcional que a su antecesor de comunicación.

- similarmente existe un salto mayor entre la cohesión lógica y la temporal que entre casual y lógica.

Podemos asignar la siguiente escala de valores para ayudar al diseñador en la calificación de niveles:

0: casual
1: lógica
3: temporal
5: procedural
7: de comunicación
9: secuencial
10: funcional

De cualquier modo, esta escala está basada en la experiencia de los autores, y no es una regla fija, si no una conclusión.

La obligación del diseñador es conocer los efectos producidos por la variación en la cohesión, especialmente en términos de modularidad, en orden de realizar soluciones de compromiso beneficiando un aspecto en contra de otro.

 

WB01343_.gif (599 bytes) WB01344_.gif (1348 bytes) WB01345_.gif (616 bytes)