MacMusic  |  PcMusic  |  440 Software  |  440 Forums  |  440TV  |  Zicos
connascence
Recherche

Five kinds of static code coupling

mercredi 13 août 2025, 11:00 , par InfoWorld
Last week I talked about connascence, a measure of the coupling of code. We all agree that loosely coupled code is good, but what that means isn’t always clear. Connascence helps us reason about how code is coupled. You can’t decouple your code if you don’t understand how code couples together, right?

Of course, modules of code have to be coupled in some way for anything to work. The phrase “loosely coupled” implies that we want code to be less coupled rather than more coupled. But how do we measure that? How do we think about the degree to which code is coupled? Much of the specifics I’ll look at here will probably seem obvious—much of it is common-sense developer wisdom—but I find the taxonomy of connascence to be illuminating. It can reveal surprising insights into how our code is put together.

There are two types of connascences—static and dynamic. Static connascence can be discovered by visually examining your code, while dynamic connascence is discovered only by running your code. This week I’ll cover static connascence, and next week I’ll discuss dynamic connascence.

There are five types of static connascence. Recognizing them and understanding them can help you see more deeply into your code and how it works. Many and perhaps all of them will be familiar to you, though I bet you never really considered them to be “coupling.”

Connascence of name

Connascence of name occurs when two things have to agree about the name of something. This is the weakest form of connascence, or the loosest form of coupling, and the one that we should aspire to limit ourselves to. If you declare a procedure such as

function DoSomething(): void {
    // Code that does something
}

Then you have to call it using its name, in this case DoSomething. Once you choose the name, you are stuck with it. Changing the name of something requires changes elsewhere. If you want to change the name of the procedure, you need to change it everywhere that you’ve called it. That seems obvious, and of course this level of connascence is unavoidable. In fact, it’s desirable. It’s the lowest level of coupling we can have. If we could limit our coupling to connascence of name, we’d be doing extremely well.

Connascence of type

Connascence of type occurs when two entities have to agree on the type of something. The most obvious example is the parameters of a method. If you declare a function as follows:

class SomeClass {
    processWidget(aWidget: Widget, aAction: WidgetActionType): boolean {
        // Function logic goes here
        return false; // Example return value
    }
}

Then any calling code must pass a Widget and a WidgetActionType as parameters of the processWidget function and must accept a boolean as a result type.

Connascence of type isn’t quite as weak as connascence of name, but it is still considered a weak and acceptable level of connascence. Indeed, you couldn’t get along without it, could you? You have to be able to call a method of a class to get anything done, and it’s not very burdensome to ensure that your types match. Most code won’t even work properly if you don’t couple code via connascence of type. The compilers of a typed language won’t even compile code that isn’t coupled with connascence of type.

Connascence of meaning

Connascence of meaning occurs when components must agree on the meaning of particular values. Connascence of meaning most often occurs when we use “magic numbers,” that is, when we use specific values that have meaning in multiple places.

Consider the following code:

function getWidgetType(aWidget: Widget): number {
    if (aWidget.status === 'Working') {
        return 1;
    } else if (aWidget.status === 'Broken') {
        return 2;
    } else if (aWidget.state === 'Missing') {
        return 3;
    } else {
        return 0;
    }
}

If you want to use the above code, then you have to know the meaning of the result code for the GetWidgetType function. If you change one of the result codes (1, 2, 3, or 0) or add a new one, then you need to change the code that uses this function wherever it is used. And to make that change, you have to know the meaning of each result code. Sure, you can look at this function and figure out that 'Working' is 1, but that is not at all obvious to the caller of the function, is it?

The solution here is to refactor the code to use constant names for the result codes, or better, an enumerated type that defines what the states mean. This reduces your coupling level from connascence of meaning to connascence of name, a desirable outcome. Any time you can refactor from a higher to a lower level of connascence, you have lowered coupling and thus improved your code.

Connascence of position

Connascence of position occurs when code in two different places must agree on the position of things. This most commonly occurs in parameter lists where the order of parameters is required by the method. If you add a parameter in the middle of an existing parameter list, all uses of that method must add the new parameter in the correct position.

The degree of your connascence of position can be reduced by limiting the number of parameters in any given routine. For example, you could reduce a parameter list to a single type, thus moving from connascence of position to connascence of type. Connascence of type is a weaker coupling, so this is something you should try to do.

Here’s an example. Consider this routine:

class UserManager {
addUser(aFirstName: string, aLastName: string, aAge: number, aBirthdate: Date,
aAddress: Address, aPrivileges: Privileges): void {
// add the user here
}
}

We can reduce connascence or loosen coupling by refactoring this connascence of position to use connascence of type instead. For example:

type UserRecord = {
    firstName: string;
    lastName: string;
    age: number;
    birthday: Date;
    address: Address;
    privileges: Privileges;
};

class UserManager {
    addUser(aUser: UserRecord): void {
        // add user here
    }
}

Here we have reduced the coupling by creating a single type and having the addUser procedure depend on the type of one parameter instead of the positions of a long list of parameters. You can fill out the data for the UserRecord in any order that you like, reducing the cognitive load for calling the addUser function.

By weakening the connascence, or reducing the strength of the coupling, we’ve improved the code.

Connascence of algorithm

Connascence of algorithm occurs when two modules must agree on a specific algorithm to function together.

Imagine you are building a server with a C# API that will be consumed by a TypeScript client. The information to be sent between these two modules is sensitive and must be encrypted. Thus, these two modules will be coupled by connascence of algorithm because both must agree on the encryption algorithm that will be used. If the encryption algorithm is changed for the server, then it must also be changed for the client.

Reducing connascence of algorithm can be difficult, because it most often has a high degree of locality (that is, the coupling occurs in modules that are either logically or physically distant). One solution might be to create a third module that becomes the one place where the algorithm is found, and have the server and client modules use that third module. In this case, you would create a third service that handles all of the encryption in a single location.

My guess is that you have run across all of these situations and intuitively understood the right way to refactor things, following well-known principles like “Don’t repeat yourself” and “Never use magic numbers.” But often, the coupling of your code is more subtle and harder to see than the problems those aphorisms address. In those cases, understanding static connascence can help you write cleaner, less coupled code. 
https://www.infoworld.com/article/4038367/five-kinds-of-static-code-coupling.html

Voir aussi

News copyright owned by their original publishers | Copyright © 2004 - 2025 Zicos / 440Network
Date Actuelle
jeu. 14 août - 01:59 CEST