Write Stable Code using Coupling Metrics

Are you tired of changing one part of a system, only to have another part break? Write stable code! Writing stable code can seem impossible. Trying to keep things from breaking can be a nightmare if you’re unaware of how your system is coupled. Understanding Afferent & Efferent coupling can guide you into insights about your software architecture & design.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

Coupling

To illustrate coupling, I’m going to talk about it at a project/package/boundary level. You could also think of these diagrams at a class level as well, however I think looking at it from a higher level such as project/packages of your system is a better place to start.

Write Stable Code using Coupling Metrics

Each blue box in the above diagram represents a boundary/project within the system. The direction of the arrows is to illustrate the coupling required from one boundary to another.

Shipping is dependent on Sales
Billing is dependent on Sales
Sales is dependent on CRM

Afferent Coupling (Ca)

Who depends on you? Afferent coupling (denoted by Ca) is a metric that indicates the total number of other projects/boundaries that are dependent upon it.

So from the viewpoint of the Sales boundary, it has an Afferent Coupling of 2. Shipping and Billing are both dependent upon Sales.

From a .NET solution, this would be represented by project references. When you take the viewpoint of a particular project in a solution, what other projects reference it? The number of other projects that reference your project is the total of Afferent Coupling (Ca).

Afferent Coupling: Who depends on You?

Efferent Coupling (Ce)

Who do you depend on? Efferent coupling (denoted by Ce) is another metric that is the verse of Afferent Coupling. It is the total number of projects that a given project depends on.

From the viewpoint of the Sales project/boundary, it has an Efferent Coupling (Ce) of 1. It depends on the CRM project/boundary.

From a .NET solution, this would represent all the references you have to other projects for a given project.

Efferent coupling: Who do you depend on?

Coupling Metrics

If we count all the Afferent (Ca) and Efferent (Ce) coupling in the entire diagram, we get the following counts.

Write Stable Code using Coupling Metrics

If you were to do this with your solution/system, what could you derive from this data? How could you use this to better understand your system overall and the possible issues with it?

Having a high Afferent Coupling (Ca) will generally cause you pain when you make a non-compatible change. Meaning, if you make a change to a project that is used by a lot of other projects, you have a high risk of causing issues with all those other projects. You’ll know this if you make a change and break other parts of your system.

Having a high Efferent Coupling (Ce) will generally cause you pain when you need to change it. Because it’s so dependent on so many other projects/ boundaries, it’s can be difficult to change. Having a lot of dependencies could mean that it’s simply doing too much or that you actually have misaligned boundaries.

Instability

Instability another metric that is a ratio.

I = Ce / (Ce + Ca)

This metric is a ratio between 0 and 1. With 0 meaning it’s totally stable and 1 meaning it’s unstable.

Note: Having a high ratio of instability isn’t unreasonable depending on the context of the project.

Here’s the calculated instability ratio for each project/boundary.

Write Stable Code using Coupling Metrics

CRM has an Instability of 0. Meaning it’s stable. And this makes sense because it has no dependencies. Nothing can affect it. In other words, no changes to any other projects can affect it. However, since it has a high Ca, changes to it can affect other parts of the system. We need to be cautious of change.

Billing & Shipping have Instability of 1. If sales changes in a way that is not handled by Billing, it can make it unstable. This isn’t inherently bad because we need to realize that it’s relative to the Ce for those projects. Having a dependency on 1 project is much different than having 10 dependencies. Also, we can change these projects freely and we will not affect any other projects.

Sales has a combination of both Ca and Ce. While these numbers are low, if you’re in a situation where a project has a high number of both Ca and Ce, it may be cause for concern in your design. This would be the center point of your diagram. It can be affected by many projects, and change to it can affect many projects. Not an ideal scenario.

Coupling Metrics

Use coupling metrics of Afferent Coupling (Ca), Efferent Coupling (Ce), and Instability (I) as a way to review your system and your design goals. Let metrics guide your decision making in refactoring where needed.

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Avoiding a Big Ball of Mud

How can you prevent creating a big ball of mud? Understanding your boundaries and the coupling between them. How do you communicate between boundaries within a monolith? Coupling is the enemy! Define contracts of functionality that are exposed to other boundaries. This hides implementation. If you want to be coupled less, go even further with asynchronous messaging.

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

Direction of Dependencies

A lot of people are using onion architecture or a layered approach to writing their software. This really is about the direction of dependencies and having the core domain logic not be coupled to on anything else.

In the diagram above, the very center is the domain, which on top of it is domain services. Meaning domain services depends on the domain. Above that are application services, which depend on domain services.

The dependencies point inward. The outermost shell will generally be UI, Integration Tests, etc.

While I do think this is an approach to limiting coupling, I actually don’t think it’s the most important thing. Boundaries are.

Coupling between Boundaries

If you’re developing a large system, boundaries are key. Boundaries allow you to split up a complex system allowing you to create more focused models. If you want more info on defining boundaries, check out my Context is King: Finding Service Boundaries series.

Once you’ve defined boundaries, you’re likely going to need to communicate between them.

Big Ball of Mud

If you’re creating a monolith, this will likely be done in-process via typical method or function calls. Generally, a boundary will expose an interface that other boundaries can consume.

In my Loosely Coupled Monolith series, I describe having each boundary contain a project for Contacts and Implementation (and tests).

Each Implementation project within a boundary will reference other Contact projects from other boundaries. An Implementation project from a boundary will never reference another implementation project from another boundary.

Contacts & Implementation

The contacts project will contain types that are contracts. This means interfaces, Data Transfer Objects (DTO), and delegates.

The implementation project will contain the actual implementation for any interfaces or delegates. It will also be what is creating any DTOs that may be used as return values from interface methods or delegates.

To illustrate this, in our Sales boundary, there is a Place Order command. We have a business rule that the must have the quantity on hand in the warehouse of all the products on an order.

The IWarehouseInventory is owned by the Shipping boundary and lives in the contracts project. The actual implementation is defined in the Shipping implementation project.

Delegates

Probably the most underused language feature that I see are the usage of delegates. They represent a function. A lot of times, as a consumer, all you ant is a function.

If you have interfaces that have low cohesion, meaning the methods inside an interface don’t necessarily belong together, then maybe you should be exposing a delegate.

Delegates are contracts. They are as low of coupling in C# as interfaces. they do not define implementation.

Another way of exposing the need for a function is when testing your consumers. If you take a dependency on an interface and you create a fake implementation, you absolutely must know which methods of that interface your consumer needs.

From the example above, if our Handle method implementation changes and it uses a different method on the IWarehouseInventory, our test will likely fail. However, if we passed in a delegate, when creating tests, we know exactly what needs to be returned.

Here is our definition of our delegate in the Shipping boundaries Contracts project.

Now replaced in our implementation to simply use the delegate.

Once you write tests for PlaceOrderHandler, you will soon realize that in these types of situations, you really just want a function and not an interface.

Messaging

The only way to remove coupling from interfaces and delegates is to move to asyncronomous messaging.

This means having boundaries be publishers and consumers of messages. These messages (DTOs) would live in the contract projects.

Big Ball of Mud

While I do think onion architecture and direction of dependencies are important, I do think separating a large system into smaller pieces ultimately allows you to turn a big ball of mud into smaller balls of mud. By creating smaller modules that limit their coupling can help prevent a big ball of mud. You may end up with smaller balls of mud, but that’s much easier to tackle and comprehend in a large system.

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.

Messaging Commands & Events Explained!

In service oriented architecture (including microservices) that leverage messaging, you’re going to run into both types of messages: Commands & Events. What’s the difference between Commands & Events? When should you use a command and when should use an event?

YouTube

Check out my YouTube channel where I post all kinds of content that accompanies my posts including this video showing everything that is in this post.

What’s a Command?

Commands are messages with the intent to change the state of the system.

They are actions to be performed that have side effects.

They may be created by an end-user or another part of the system that could be automated.

They are away to execute behavior.

What’s an Event

Events are statements of fact.

They are named in the past tense because they represent something that has already occured.

Events are things that have happened within a system.

They are the result (not in the method/return sense) of an executed command.

They are notifications.

They are used to tell other parts of the system that something has occurred.

Consumers

One important distinction between Commands & Events are consumers.

A command will have exactly one consumer. There will only be one consumer that will handle an instance of a command. When your producer sends a command to a message broker, it will send that command to only one consumer.

Commands & Events Explained!

An event will have zero to many consumers. When a producer publishes an event to a message broker, it will deliver it to as many consumers that want it. Each consumer will receive a copy of the event. There may not be any consumers that want to receive an event. The publisher does not know who the consumers are, or how many of them exist for an event.

Commands & Events Explained!

When to use a Command?

When you want to tell the system to perform some type of behavior. For example, sending a PlaceOrder command. You’re telling the system to perform an action that could have a side effect.

Name your commands like actions or tasks. They should be contain a verb.

When to use an Event?

When something has occurred as the result of a command and you want to tell other parts of the system. For example, OrderPlaced event can let other parts of the system know that an order has been placed. This likely would have resulted from a PlaceOrder command.

Because events are things that have occurred, they will be named in the past tense.

Commands & Events: Orchestration

You can leverage both commands and events together to orchestrate a business process or workflow. An orchestrator will send commands and consume the resulting events to kick off the next command.

Check out my blog post and video on Event Choreography & Orchestration (Sagas) for more details.

Follow @CodeOpinion on Twitter

Enjoy this post? Subscribe!

Subscribe to our weekly Newsletter and stay tuned.