Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
107 changes: 107 additions & 0 deletions src/content/blog/balancing-coupling-in-software-design-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
---
title: 'Balancing Coupling in Software Design - a review'
description: "we have read this 300 pages book on coupling is it worth it? (spoiler yes!)"
author: Alberto Barrilà
keywords: ["book", "coupling", "software design"]
pubDate: '06-23-2025 10:00'
updatedDate: '06-23-2025 10:00'
heroImage: 'balancing-coupling-in-software-design-review/hero.jpg'
timeRead: '10'

---

## What Is Coupling?

Coupling is a normal part of designing a system, every system has a purpose and is made up of components, for the system to work, these components need to interact and that's what coupling means.

Coupling may happens when parts of the system need to share information or have to follow a time related process, the more they share, the more connected they become. This lead to the fact that if one part changes, the other might need to change too. Even without sharing information, components can still be linked if they depend on the same timing.

## Coupling and Complexity

When making design decisions in your software systems, it's helpful to start by identifying which domain you're in. Are you dealing with a clear, complicated, complex, or chaotic situation? Which decision-making approach best fits the domain you're in?

Here is where the Cynefin framework can help you. Cynefin is used it to explain complexity as situations where the results of an action can only be understood in hindsight. In Cynefin terms, complexity arises from weak connections between actions and their outcomes.

In complex situations, decision-making requires running safe experiments to explore possible outcomes. In software design, we often make these decisions based on intuition. However, the next time you need to experiment before making a choice, take a moment to consider where the complexity is coming from.

## Interactions

The complexity of a system isn't just about how big it is or how many parts it has. It's about how those parts interact with each other.

Thinking about interaction we can define two type of complexity. Global complexity refers to how components interact with each other, while local complexity is about interactions within a single component. Both need to be managed carefully.

Good constraints can help control complexity by limiting the system's flexibility and reducing the chances of unpredictable interactions. As usual is a matter of tradeoff

## Modularity

Modularity aims to reduce complexity by organizing knowledge into separate modules. The main goal is to allow the system to evolve over time to meet future needs. So, modular design requires thinking not just about today's requirements, but also about what might be needed in the future.

And this is where problems arise, be careful not to go overboard. A system designed to handle any possible change can become too complicated. Finding the right balance is key—systems shouldn't be too rigid or too flexible.

## Structured Design

Larry L. Constantine began developing the ideas behind the structured design methodology as early as 1963. These ideas were then published in collaboration with Edward Yourdon in the early 1970s. You may think that today, over half a century later, this material is outdated and irrelevant, well it turn out that is a big no.

Even though the structured design methodology was designed more than half a century ago, the problems it was supposed to solve, and some of its solutions, are still very relevant today.

## Connascence

Module coupling was first introduced in the context of procedural programming, but with the rise of object-oriented programming, a more detailed model was needed. Meilir Page-Jones (1996) developed the Connascence model to address this need.

Unlike traditional module coupling, Connascence describes different ways knowledge is shared between components. It has two main types: static connascence and dynamic connascence.

Static connascence deals with decisions that need to be made at compile time for modules to work together while Dynamic connascence focuses on dependencies that happen during runtime.

## Integration Strength

Structured design's module coupling and connascence focus on different ways knowledge is shared between modules. The integration strength model combines both approaches for a more complete analysis of how components relate to each other.

With the integration strength model, you can evaluate not just the types and levels of knowledge shared between components, but also how that knowledge flows at different levels—like from an object's methods to services in a distributed system.

## Distance

When you make design decisions, it's important to consider not just the knowledge shared between components, but also how far that knowledge needs to travel. You can measure this by looking for the closest common ancestor module of the components. Also, remember that social factors can impact how far the knowledge travels, which can affect the cost of updating the design in the future.

Finally, keep in mind the impact of lifecycle coupling. Components that are close to each other can influence each other's lifecycles, causing changes even if they don't share knowledge. In other words, even without direct connections, components may still need to evolve together because of their lifecycle dependencies.

## Volatility

To design a modular system, you need to understand the business domain of the system. By identifying the subdomains and their types, you'll get a sense of how volatile each component is. Core subdomains are usually the most volatile.

Volatility can also come from technical issues, like the need to improve the design or changes in the organization. In some cases, the design itself can make components volatile, as it connects the most unstable parts with the right level of integration strength.

## Balancing Coupling

An integration is stable when either the integration strength or volatility (or both) are low. If both volatility and distance are high, the cost of making changes becomes high.

When integration strength and distance are opposite, the system becomes more modular. But if they're equal, it leads to complexity.

Global complexity occurs when both integration strength and distance are high.Local complexity happens when both values are low.

The balance between these factors can be calculated with this formula, where MIN_VALUE and MAX_VALUE define the numeric range:

`BALANCE = max(|STRENGTH - DISTANCE|, MAX_VALUE - VOLATILITY) + MIN_VALUE`

Creating modularity is important, but even more important is maintaining it over time.

## Rebalancing Coupling

Software changes can be divided into tactical and strategic changes. Tactical changes are about how the system works—either adding new features that fit the current design or improving existing functionality. Strategic changes can disrupt a modular design by upsetting the relationships between components.

Integration strength can increase over time with new features.The distance between components can grow due to refactoring or changes in the organization.Volatility can change if the business domain shifts.

These changes can significantly affect the system. To keep things balanced, you'll need to adjust the other coupling factors. If you don't address the imbalance, it can lead to technical debt and added complexity.

## Fractal Geometry of Software Design

Prof. Geoffrey West has been researching the dynamics of growth in complex systems for many years. His research revealed that the same laws of physics govern growth in a broad range of systems; more specifically, network-based systems and software design can be seen as a network-based system.

Not all parts of a network-based system grow at the same rate, some grow slower, while others grow faster. These differences make larger systems more efficient. Expanding a system's functionality builds on what's already there. However, as a system grows, its complexity also increases—often at a faster rate.

Growth-driven complexity can limit how much a software system can grow. But, like in nature, we can manage complexity using fractal modularity: ensuring that component interactions are balanced at all levels. This is where the balanced coupling model comes in—it acts as a guide for designing modular systems.

## Conclusion

Coupling is a core part of system design, and modularity depends on balancing its three dimensions (Knowledge Sharing, Physical Distance and Volatility).

Reading a 300 pages book on this topic not only expanded my knowledge on how software design need to take coupling deeply in consideration but also give me some truly practical (also in the mathematical way) hint to tame this monster.