En informática, el acoplamiento es la forma y nivel de interdependencia entre módulos de software; una medida de qué tan cercanamente conectados están dos rutinas o módulos de software;[1] así como el grado de fuerza de la relación entre módulos.[2] Un ejemplo simple de acoplamiento es cuando un componente accede directamente a un dato que pertenece a otro componente. En ese caso, el resultado del comportamiento del componente A dependerá del valor del componente B, por lo tanto, están acoplados.
El acoplamiento está comúnmente contrastado con la cohesión. Un bajo acoplamiento normalmente se correlaciona con una alta cohesión, y viceversa. El bajo acoplamiento es frecuentemente una señal de un sistema bien estructurado y de un buen diseño de software.
La métrica de software de acoplamiento y cohesión fue inventada por Larry Constantine a finales de la década de 1960 como parte del diseño estructurado, basado en características de 'buenas' prácticas de programación que reducen los costos de mantenimiento y modificación. El diseño estructurado, incluyendo cohesión y acoplamiento, se publicó en el artículo Stevens, Myers y Constantine (1974) y en el libro Yourdony Constantine (1979), el último de los cuales posteriormente se volvió un estándar.
Modelo conceptual de acoplamiento
El acoplamiento puede ser "bajo" (también "débil") o "alto" (también "fuerte").
El bajo acoplamiento entre las unidades de software es el estado ideal que siempre se intenta obtener para lograr una buena programación o un buen diseño. Cuanto menos dependiente sean las partes que constituyen un sistema informático, mejor será el resultado. Sin embargo, es imposible un desacoplamiento total de las unidades.
Por ello, el objetivo final del diseño de software es reducir al mínimo el acoplamiento entre componentes. Para ello, lo más importante es saber eliminar el acoplamiento que no sea funcional o arquitectónico.
El caso del acoplamiento funcional, puede ser por ejemplo que un componente de cálculo de probabilidades dependa de un componente de cálculo matemático básico, ya que para calcular probabilidades será necesario aplicar fórmulas matemáticas.
El bajo acoplamiento permite:
Mejorar el mantenimiento de las unidades de software.
Aumentar la reutilización de las unidades de software.
Evitar el efecto onda, ya que un defecto en una unidad puede propagarse a otras, haciendo incluso más difícil de detectar dónde está el problema.
Minimiza el riesgo de tener que cambiar múltiples unidades de software cuando se debe alterar una.
Algunos tipos de acoplamiento, de mayor a menor, son los siguientes:
Programación estructurada
En programación estructurada, un módulo hace referencia a una subrutina de cualquier tipo. Por ejemplo, un conjunto de una o más secciones de código que tiene un nombre y preferiblemente su propio conjunto de nombres de variable.
Acoplamiento de contenido (alto)
El acoplamiento de contenido (también conocido como Acoplamiento patológico) ocurren cuando un módulo modifica o se apoya en el funcionamiento interno de otro módulo (por ejemplo, accediendo a datos locales de otro módulo).
Por lo tanto, cambiar la forma en que el segundo módulo produce datos (ubicación, tipo, velocidad) conducirá a cambiar el módulo dependiente.
Acoplamiento común
El acoplamiento común (también conocido como Acoplamiento global) ocurre cuando dos módulos comparten las mismos datos globales (por ejemplo, una variable global).
Cambiar el recurso compartido implica cambiar todos los módulos que lo usen.
Acoplamiento externo
El acoplamiento externo ocurre cuando dos módulos comparten un formato de datos impuesto externamente, protocolo de comunicación, o interfaz de dispositivo. Esto está básicamente relacionado con la comunicación a herramientas externas y dispositivos.
Acoplamiento de control
El acoplamiento de control es un módulo controlando el flujo de otro, mediante el paso de información sobre lo que debe hacer (por ejemplo, pasándole una bandera tipo what-to-do flag).
El acoplamiento sellado (Stamp coupling en inglés) ocurre cuando los módulos comparten una estructura de datos compuesta y usan solo una parte de ella, posiblemente una parte diferente (por ejemplo, pasando un registro completo a una función que solo necesita un campo de dicho registro).
Esto podría llevar a cambiar la forma en la que un módulo lee un registro debido a que un campo que el módulo no necesita ha sido modificado.
Acoplamiento de datos
El acoplamiento de datos ocurre cuando los módulos comparten datos entre ellos, por ejemplo, parámetros. Cada dato es una pieza elemental y dicho parámetro es la única data compartida (por ejemplo, pasando un entero a una función que calcula una raíz cuadrada).
Acoplamiento de mensajes (bajo)
Este es el más bajo tipo de acoplamiento. Se puede lograr por la descentralización de estados (como en los objetos) y la comunicación de componentes se realiza mediante parámetros o paso de mensajes.
Sin acoplamiento
Módulos que no se comunican para nada uno con otro.
Describe la relación entre una clase hija y su clase padre. La hija se conecta a su padre, pero el padre no se conecta al hijo.
Acoplamiento temporal
Cuando dos acciones se agrupan en un módulo sólo porque suceden al mismo tiempo.
En un trabajo reciente varios otros conceptos de acoplamiento se han investigado y utilizado como indicadores para diferentes principios de modularización utilizados en la práctica.[3]
Sistemas estrechamente acoplados tienden a presentar las siguientes características de desarrollo, que a menudo son vistos como desventajas:
Un cambio en un módulo usualmente fuerza un efecto dominó de cambios en otros módulos.
El ensamble de módulos podría requerir más esfuerzo y tiempo debido a la interdependencia entre módulos.
Un módulo particular podría ser más difícil de reutilizar o probar debido a que los módulos dependientes deben incluirse.
Ya sea con alto o bajo acoplamiento, el rendimiento de un sistema se ve afectado la creación de mensajes y parámetros, transmisión, traducción (por ejemplo, el cálculo de referencias) y la interpretación de mensajes (que podría ser una referencia a una cadena, matriz o estructura de datos), o incluso mensajes más complejos como SOAP.
Transmisión de mensajes y rendimiento
Dado que un mensaje debe transmitirse completo para recuperar su información completa, la transmisión de mensajes se debe optimizar. Mensajes más largos requieren más memoria para transmitirse y recibirse. También, cuando es necesario, los receptores deben reensamblar el mensaje a su estado original para completar su recepción. En ese sentido, para optimizar el rendimiento en tiempo de ejecución, el tamaño del mensaje se debe minimizar, y la información contenida se debe maximizar.
Traducción de mensajes y rendimiento
Los protocolos de mensajes y los mensajes mismos muchas veces contienen información extra (por ejemplo, paquete, estructura, definición e información del lenguaje). Por lo tanto, el receptor muchas veces necesita traducir un mensaje en otro más refinado removiendo caracteres extra y estructuras de información y convirtiendo valores de un tipo a otro. Cualquier tipo de traducción incrementa el uso de CPU y memoria. Para optimizar el rendimiento en tiempo de ejecución, los mensajes y sus contenidos se deben reducir y refinar para maximizar la información contenida y reducir la traducción.
Interpretación de mensajes y rendimiento
El receptor debe interpretar todos los mensajes. Mensajes simples como enteros no deberían requerir procesamiento adicional para interpretarse. No obstante, mensajes complejos como mensajes SOAP requieren parseo y transformación de cadenas de caracteres para exhibir su significado interno. Para optimizar el rendimiento en tiempo de ejecución, los mensajes se deben refinar y reducir para minimizar la sobrecarga por interpretación.
Un enfoque para disminuir el acoplamiento es el diseño funcional, el cual busca limitar las resposabilidades de los módulos basándose en su funcionalidad. El acoplamiento se incrementa entre dos clases A y B si:
A tiene un atributo que refiere a (es del tipo) B.
A llama a un servicio de un objeto B.
A tiene un método que referencia a B (vía tipos return o parámetros).
A es una subclase de (o implementa) la clase B.
El bajo acoplamiento se refiere a una relación en la cual un módulo interactúa con otro vía una simple y estable interfaz y no necesita conocer la implementación interna del otro módulo (ver encapsulamiento (informática)).
Sistemas como CORBA o COM permiten objetos que se comunican con los demás sin tener que saber nada acerca de la implementación de los otros objetos. Estos dos sistemas incluso permiten la comunicación entre objetos escritos en diferentes lenguajes.
Acoplamiento y cohesión son términos que ocurren juntos muy frecuentemente. El acoplamiento se refiere a la interdependencia entre módulos, mientras que la cohesión describe cómo se relacionan las funciones dentro de un módulo independiente. Baja cohesión implica que un módulo dado ejecuta tareas que no están muy relacionadas unas a otras y por tanto pueden crear problemas como que el módulo se vuelva muy grande.
El acoplamiento en ingeniería de software[4] describe una versión de métricas asociadas con este concepto.
Para el acoplamiento de datos y flujo de control:
di: número de parámetros de entrada
ci: número de parámetros de control
do: número de parámetros de salida
co: número de parámetros de control de salida
Para el acoplamiento global:
gd: número de variables globales usadas como data
gc: número de variables globales usadas como control
Para acoplamiento de entorno:
w: número de módulos llamados (fan-out)
r: número de módulos llamantes bajo consideración (fan-in)
Acoplamiento(C) hace que el valor sea más grande cuanto más acoplado esté el módulo. Este número varía de aproximadamente 0,67 (bajo acoplamiento) a 1,0 (altamente acoplado).
Por ejemplo, si un módulo tiene un solo parámetro de entrada y datos de salida,
Si un módulo tiene 5 parámetros de entrada y salida de datos , el mismo número de parámetros de control y accede a 10 elementos de datos globales , con un fan-in de 3 y un fan-out de salida de 4,
Métrica CBO
En Programación Orientada a Objetos la métrica CBO (Coupling Between Object Classes) obtiene un nivel de acoplamiento entre clases mediante el cómputo de ligas de una clase a otra. Es decir, el número de clases ligadas a otra, excluyendo constantes, llamadas a APIS, y herencia.
F. Beck, S. Diehl. On the Congruence of Modularity and Code Coupling. In Proceedings of the 19th ACM SIGSOFT Symposium and the 13th European Conference on Foundations of Software Engineering (SIGSOFT/FSE '11), Szeged, Hungary, September 2011. doi10.1145/2025113.2025162
Pressman, Roger S. Ph.D. (1982). Software Engineering - A Practitioner's Approach - Fourth Edition. 0-07-052182-4
Stevens, W.P.; Myers, G.J.; Constantine, L.L. (1974). IBM Systems Journal 13 (2): 115–139, ed. Structured design(en inglés). doi:10.1147/sj.132.0115.
Yourdon, Edward; Constantine, Larry L. ((1979) 1975). Yourdon Press, ed. Structured Design: Fundamentals of a Discipline of Computer Program and Systems Design(en inglés). ISBN0138544719.