Seguro que siendo desarrolladores de software todos hemos oído los términos de acoplamiento y cohesión. Para quien no le suene, el término «acoplamiento» hace alusión al grado de dependencia que tienen dos unidades de software y la «cohesión» tiene que ver con la forma en la que agrupamos unidades de software en una unidad mayor.

¿Y todo esto a qué viene? Cuando estamos desarrollando, refactorizando, tenemos test y vamos a modificar el código que tenemos por delante tenemos que tomar decisiones: ¿En base a qué tomamos esas decisiones? Unas veces pueden ser principios de diseño de orientación a objetos, otras basándonos en libros como «clean code», «refactoring patterns»,… basándonos en patrones de diseño, basándonos en nuestra experiencia (buena o mala), o basándonos en los principios SOLID, o a code smell o incluso sobre la base de Kent Beck(¿qué haría Kent Beck aquí?)… al final tomamos decisiones basándonos en todo lo que hemos aprendido hasta el momento y de nuestra intuición.
Este post está basado en la charla de Alfredo Casado «Acoplamiento & Connascence» del meetup Software Craftsmanship Madrid
A la hora de tomar decisiones es bueno tener herramientas que nos guíe durante el camino, ya que normalmente siempre nos guiamos por cosas como: ha quedado un código muy elegante, eso no cumple SOLID, este código está demasiado acoplado a esta librería, ha quedado el código muy sucio,… al final como ya hemos dicho antes no solo debemos tener en cuenta nuestra intuición, sino herramientas como el «Connascence» o «grado de acoplamiento»
Hoy vamos a hablar de los tipos de connascence (o grado de acoplamiento), y de como podemos usarlos como herramienta para evaluar nuestro diseño en términos, de «Coupling & Cohesion». La idea es tener una serie de «métricas», herramientas, o como queramos llamarlas para que nuestras decisiones de diseño no se basen solo en nuestra intuición y podamos argumentar por qué hemos tomado una decisión u otra.
Definición de Connascence
El término connascence no es algo nuevo, aparece en un paper de 1992 de Meilir Page-Jones llamado «Comparing Techniques by Means of Encapsulation and Connascence.» y en el libro What Every Programmer Should Know about Object-Oriented Design. Como comentado antes el connascence tiene que ver con el acoplamiento.
Así pues, el connascence entre dos componentes software A y B quiere decir que: Si se realiza un cambio en A se requiere un cambio en B con el fin de que todo el sistema siga funcionando, o que un cambio va a requerir que se modifiquen A y B juntos para que todo el sistema siga funcionando. En otras palabras, existe una relación entre los 2 elementos software que hace que tengan que modificarse ambos para que el sistema siga funcionando.
Tipos de connascence
Page-Jones distingue varios tipos de connascence y los clasifica en Estáticos, que puede ser evaluado por la estructura léxica del código, o dinámico, cuando depende de la ejecución del código.
Connascence de Nombre – Connascence of Name (CoN)
Cuando varios componentes deben estar de acuerdo con el nombre de la entidad.
var count int;
count := 10;
Por ejemplo nombres de variables o nombres de métodos: Si un nombre de un método cambia, los elementos que llaman a este método deben cambiarse para usar el nuevo nombre.
Connascence de tipo – Connascence of Type (CoT)
Cuando varios componentes deben estar de acuerdo en los tipos de una entidad.
var text string;
text := 10; //ups!
Por ejemplo, si un método cambia el tipo de su argumento de un entero a una cadena, los llamadores de ese método deben cambiarse para pasar un argumento diferente que antes.
Connascence de Significado – Connascence of Meaning (CoM)
Cuando varios componentes deben ponerse de acuerdo en el significado de valores particulares.
int strcmp ( string $str1 , string $str2 )
Por ejemplo, el entero 0 significa «false» y el 1 representa «true». O por ejemplo strcmp
que devuelve < 0 si str1 es menor que str2; > 0 si str1 es mayor que str2 y 0 si son iguales.
Connascence de posición Connascence of Position (CoP)
Cuando varios componentes deben estar de acuerdo en el orden de los valores.
function getUserInfo(){
//name, email, year_birth, is_admin
return ['juan', 'juan@email.com', 1978, false];
}
function createUser($name, $country, $email, $phone)
Por ejemplo, en la llamada a un método los parámetros tienen que tener un orden determinado.
function calculateImageSize($url){
$width = ...
$heigh = ...
return [$width, $height];
}
list($width, $height) = calculateImageSize('url/img');;
O cuando hay que ponerse de acuerdo en como se devuelven los valores de una función ¿Creéis que la función calculateImageSize
devuelve los valores de manera correcta? ¿No sería mejor crear 2 funciones o devolver un objeto?
Connascence de Algoritmo – Connascence of Algorithm (CoA)
Cuando varios componentes deben estar de acuerdo en un algoritmo.
function hash($clearPassword)
{
return md5($clearPassword);
}
Por ejemplo en un algoritmo de autenticación, ambos lados deben tener el mismo algoritmo de hashing o la autenticación fallará.
Connascence de Ejecución – Connascence of Execution (CoE)
Cuando el orden de ejecución es importante.
$email = new Email();
$email->setRecipient('foo@example.com');
$email->setSender('my@domain.com');
$email->send();
$email->setSubject('hello world');
Por ejemplo cuando creamos un objeto y este no funciona justo después de hacer el new, sino que hay que setearle valores como es el caso.
Connascence de tiempo – Connascence of Timing (CoT)
Cuando la sincronización de multiples componentes es importante.
timeout = 200;
socket.writeRequest(data);
answer = socket.readResponse(timeout);
Connascence de Valores – Connascence of Values (CoV)
Cuando existen restricciones sobre los posibles valores que pueden tomar algunos elementos compartidos.
class Article {
const DRAFT = 1;
const PUBLISHED = 2;
private $text;
public $state;
public function __construct($text)
{
$this->text = $text; $this->state = self::DRAFT;
}
public function publish()
{
$this->state = self::PUBLISHED;
}
}
function testArticle()
{
$article = Article("Test Contents"); assertEqual($article->state, Article::DRAFT); $article->publish();
assertEqual($article->state, Article::PUBLISHED);
}
Por ejemplo, cuando varios elementos deben ponerse de acuerdo sobre el estado de un objeto.
Connascence de entidad – Connascence of Identity (CoI)
Cuando varios componentes deben referenciar al mismo objeto
class Producer implements Runnable
{
public static Queue myQueue;
public void run() {
myQueue.put(37);
}
}
class Consumer implements Runnable
{
public void run() {
int item = Producer.myQueue.get();
processItem(item);
}
}
Conclusiones
Como hemos dicho antes la idea del connascence sirve para hablar con propiedad a la hora de argumentar nuestras decisiones, del mismo modo nos da una escala con la que medir el grado de acoplamiento entre componentes.
Si bien es cierto que no existe aun mucha documentación sobre connascence, por poco van saliendo charlas, artículos y post sobre este término.
Un comentario en “Connascence, otra manera de hablar de acoplamiento y cohesión”