Loading...
Skip to Content

The Key to Microservice Design: Understanding Cohesion and Coupling

  Today we look at cohesion and coupling, two concepts that play a critical role in designing microservices.

Cohesion describes how closely related the elements within a single module are. A module with high cohesion has a clear, focused purpose.

Coupling refers to the degree of interdependence between different modules. Low coupling increases the independence of modules and greatly improves the flexibility and scalability of a system.

The Key to Microservice Design: Understanding Cohesion and Coupling

Software designed with high cohesion and low coupling is efficient and easy to maintain and extend. To make this easier to understand, let's walk through a real-life example.

Imagine a restaurant that serves a variety of bread-based dishes such as sandwiches, hamburgers, and pizza. Most restaurants store ingredients like bread, vegetables, and meat in one place, and gather the various cooking tools in another.

Arranging things by type makes it easy to find what you need, but it creates an inefficient structure where the relevant ingredients and tools have to be fetched every time an order comes in. Translated into software, this is a structure where, every time a request hits the system, the data needed to process it has to be fetched on the spot.

The Key to Microservice Design: Understanding Cohesion and Coupling

The image above is an EventStorming model showing how a kitchen designed in the way just described handles its work. Ingredients and tools are grouped as data concepts, and at each cooking step the required ingredients are pulled one by one from each database in a Req/Res (Request/Response, i.e. synchronous) style.

This structure is known as a Chatty Microservice. As the name suggests, there is so much communication (chatter) between microservices to look up data that it is classified as a classic anti-pattern. A situation like this, where the elements needed to perform an action are scattered here and there, is a case of low cohesion.

 So how can we improve the model above to raise cohesion and lower coupling?

The Key to Microservice Design: Understanding Cohesion and Coupling

The image above is an EventStorming model that improves on the one introduced earlier. Here the bounded contexts are separated by menu item, such as 'Sandwich Preparation', 'Hamburger Preparation', and 'Pizza Preparation'. Within each context, the cooking steps needed to prepare that dish are laid out as events, and the ingredients each dish requires are added as data inside the aggregate. By integrating data and functionality this way, we arrive at a design with higher cohesion and lower coupling.

This design improvement can greatly increase the maintainability and scalability of the software. Because each bounded context operates independently, the impact of changing or adding a specific feature on other areas is minimized. Clearly separating bounded contexts by feature and concern, and integrating the data and functionality each context needs, is the key to efficient, maintainable software design.

 Now let's take the real-life example a step further and revisit the importance of cohesion and coupling using an application that is actually in service.

The Key to Microservice Design: Understanding Cohesion and Coupling

The EventStorming model above represents the database structure and service flow of the kind of food delivery application we use every day. As in the restaurant example, the information about customers, restaurants, and riders is managed as data inside separate bounded contexts, and as the service progresses, each step fetches the data it needs over synchronous calls, exhibiting the Chatty Microservice pattern.

The most common mistake when building a microservices architecture is splitting concerns from a database perspective. From a data-management standpoint, managing each domain's data separately while providing the service may look like the way to move to microservices, but this kind of design results in Tight Coupling, i.e. high coupling, because every action in the service flow is managed within a single bounded context.

The Key to Microservice Design: Understanding Cohesion and Coupling

The model above improves the anti-pattern shown earlier in terms of cohesion and coupling. The service flow has been split into three concerns from a behavioral perspective: the customer placing an order, the restaurant receiving that order and preparing the food, and the rider picking up the finished food and delivering it to the customer.

A service designed this way proceeds as domain events, meaning the results produced by an action, are delivered to services with other concerns in a Pub/Sub (Publish/Subscribe, i.e. asynchronous) style.

With this shape, a failure in one service does not affect the operation of the others, and each service runs independently, which is the ideal form of microservices.

 Here are ways to improve a service with cohesion and coupling in mind, as shown above.

Improving cohesion

  1. Apply the Single Concern principle rigorously - Break complex logic into smaller, focused units so that each class and module has only one clear responsibility.
  2. Manage method size and complexity - Write methods that are concise and clear, ideally keeping them within 20-30 lines.
  3. Logical grouping - Place related functionality in the same class or module, and use packages and namespaces to make the logical structure of the code clear.

Improving coupling

  1. Gain flexibility with dependency injection - Reduce direct dependencies between objects and create loose connections through interfaces.
  2. The power of abstraction - Rather than concrete implementations, focus on interfaces and abstract classes that maximize the code's openness to change and guarantee extensibility.
  3. Separation of concerns - Clearly separate data handling, business logic, UI logic, and so on so that each module can focus on its own well-defined role.

 Designing a microservices architecture with the high cohesion and low coupling described above is no easy task. To give developers practical help through this complex process, we built a tool called 'MSA Easy'.

The EventStorming model images in this article were actually generated with the AI-powered modeling features of MSA Easy. MSA Easy lets you move through the entire process, from microservice design to implementation and deployment, with intelligent guidance from AI. In particular, it provides intelligent features that help you design an optimal architecture with cohesion and coupling in mind.

Microservices architecture is more than a technical choice; it is a strategy for realizing business value. By understanding and applying the two core concepts of cohesion and coupling, we can design systems that are more flexible and scalable. No architecture is perfect, but we hope that continuous improvement and learning with MSA Easy will help you design better software.