What is Loose Coupling?

Anyone can write software, but it takes a seasoned developer to write decoupled software. Today, I cover the definition of loose coupling, how to detect it, and ways to improve your code.

Written by Jonathan "JD" Danylko • Last Updated: • Develop •
Two knots in two pieces of rope

A couple days ago, I had a developer ask me what it meant to have tightly coupled code and how do you detect it.

On Tuesday, I saw a similar question on Quora asking if there was any tool to analyze layers in application architecture.

Since these two subjects relate to each other, I thought I would provide a solid resource (excuse the pun) to explain every aspect of loosely coupled systems.

So where do we begin? How about the obvious?

What is Loose Coupling?

Loose Coupling is when two objects can interact with each other, but has very limited knowledge about what each object can do.

While this concept is relatively simple to understand, it's difficult to implement. Sometimes you may be under the gun to get a project out the door (hey, you gotta ship it, right?).

Some advantages of making your code loosely coupled include:

  • Better Testability
    Since your code isn't dependent on other objects and they are just passed in, this makes your unit tests easier to write.

  • Easy to understand code
    When your code is decoupled from other objects, they are usually passed in or dependency injected into the code. Your code provides a self-documenting service to your users.

  • Swappable components
    While most developers don't think about a plug-in architecture, this is ultimately what developers strive to achieve. If you want to swap out the Oracle database component with a SQL Server component, if developed properly, it can be done easily.

  • Scalability
    As your system grows, you can provide a diverse number of components to plug into your application making it more scalable. There is a term I use when a system can't scale properly. It's called "painting yourself into a corner" where you need to re-evaluate your design.

  • Isolated Code/Features
    Adding new features to a system means that you can write additional code without breaking existing functionality and feel safe writing it.

But how do you know when a code base has been "tightly wound?"

Detecting Highly-Coupled Code

Not everyone can immediately detect highly coupled code, but there are some quick ways to identify them.

Passing in Interfaces

One way to identify whether we have a tightly-coupled application is that most parameters passed into methods are concrete classes instead of using interfaces. I provide an example below using a CustomerRepository.

Methods "New-ing" up Classes

This is a dead giveaway for tightly-coupled code. When a piece of code is new-ing up a new class inside a method, this is a code smell.

Examine this code for a second.

public void ProcessInsured()
{
    var repository = new PostRepository();
    repository.CreateRecord();
}

Wouldn't it make more sense to initialize the object at the class level or pass it into the method itself?

public void ProcessInsured(IRepository repository)
{
    repository.CreateRecord();
}

These are just two that stand out the most.

Yet, if we need to examine code across a solution, double-clicking on each class would be time-consuming so we would need some tools to help us in our coding efforts.

These tools are called static code analyzers. If you aren't a C# developer, don't worry. There are static code analyzers for your language as well.

For .NET, there are two that I would recommend.

NDepend

NDepend takes your static code analysis to the next level. It provides a deep-dive into your code and makes you aware of every single dependency in your application.

While it does cost a little bit of money, it provides an elaborate amount of analysis of your code using it's own LINQ language to determine if your code is loosely coupled or not. They have a Dependency Matrix and general rules for comparing higher cohesion with lower coupling.

I also did a review of NDepend giving it a thumbs-up. It's an absolute amazing product and I definitely recommend it.

FxCop

The second static code analysis tool is FxCop.

While this doesn't integrate into Visual Studio and has it's own GUI tool, it provides a solid amount of analysis to where you can examine assemblies for dependencies.

It just occurs outside of your IDE.

While these two tools are a great help in finding problematic code, we need to focus on how to write loosely-couple code.

How to Write Loosely-Coupled Code

It all starts here. What are some techniques for writing loosely-coupled code?

Interfaces

Interfaces are probably the easiest way to decouple your code.

Examine the following piece of code:

public class CustomerRepository
{
    private readonly DbContext _context;
    public CustomerRepository(DbContext context)
    {
        _context = context;
    }
}

The CustomerRepository has a dependency on a concrete implementation of a DbContext. This is a tightly coupled example.

It makes more sense to change the code to use interfaces (changes in bold).

public class CustomerRepository
{
    private readonly IDbContext _context;
    public CustomerRepository(IDbContext context)
    {
        _context = context;
    }
}
public interface IDbContext
{
    void SaveChanges();
}

By making this simple change, we now have the ability to pass in any kind of DbContext so long as it implements an IDbContext interface. The interface defines the contract, but doesn't expect an implementation making it easier to create various DbContexts that perform different implementations. 

Dependency Injection (DI)

Whether you use Ninject, StructureMap, or Castle Windsor, using any kind of dependency injection framework is a move in the right direction.

While I won't go into a full-on Dependency Injection tutorial, it's something common most developers are using to write full-featured software and websites.

You've already seen the most simplistic version in the CustomerRepository example. The code above is often called "Poor man's" Dependency Injection since it passes it in.

If interested in learning more about dependency injection, check out this PluralSight course on Dependency Injection On-Ramp from Jeremy Clark.

Recently, you may have noticed when you start Visual Studio, it uses yet another type of dependency injection framework called MEF (Managed Extensibility Framework) from Microsoft. It's intent is to create a plug-in architecture for your application which is another way to decouple your code.

NuGet it! 

If you have a library of routines, a great exercise is to create and publish a NuGet package.

This forces you to examine your code, refactor it, and isolate it into a reusable (or decoupled) package.

Web Services

I would consider this to be the holy grail of highly-decoupled code. You cross domains when making a web service call and receive a loosely-typed JSON object.

Web Services are just another reason why software is STILL eating the world.

Conclusion

Honestly, loose coupling is something that can be taught, but it's harder when you are sitting down and writing code while a deadline is looming over you.

If you want to practice looking over highly-coupled code, I would recommend gathering some Code Katas to give you a better understanding of high cohesion/lower coupling in software development and design.

There is also an Enterprise Fizzbuzz (https://code.google.com/archive/p/fizzbuzz/) which is a sample project showing a number of code no-nos for you to refactor. ;-)

Did you like this content? Show your support by buying me a coffee.

Buy me a coffee  Buy me a coffee
Picture of Jonathan "JD" Danylko

Jonathan Danylko is a web architect and entrepreneur who's been programming for over 25 years. He's developed websites for small, medium, and Fortune 500 companies since 1996.

He currently works at Insight Enterprises as an Principal Software Engineer Architect.

When asked what he likes to do in his spare time, he replies, "I like to write and I like to code. I also like to write about code."

comments powered by Disqus