liveBook · Manning

Coupling

As explained in ASP.NET Core in Action, 3e

Loose coupling is a software design property in which components have limited knowledge of and dependence on one another.

Coupling describes how much a class depends on other classes to do its job. Loosely coupled code needs to know fewer details about the components it uses. That makes it easier to change or test one part of an application without changing another. section 8.2

Listing 8.3 Sending email without DI when you create dependencies manually
string RegisterUser(string username)
{
    var emailSender = new EmailSender(     #1
        new MessageFactory(),              #2
        new NetworkClient(                 #3
            new EmailServerSettings        #4
            (                              #4
                Host: "smtp.server.com",   #4
                Port: 25                   #4
            ))                             #4
        );
    emailSender.SendEmail(username);       #5
    return $"Email sent to {username}!";
}

Here, the registration handler creates an email sender and all its dependencies. If the sender needs another dependency, the handler must change too. This is tight coupling: handling a registration requires knowledge of how email delivery is assembled. section 8.1 section 8.2

Dependency injection removes that construction work from the handler: it declares the service it needs and receives it. Depending on an interface reduces coupling further. The handler can call the interface’s method without knowing which implementation it received, so a test can supply a stub or mock instead of sending a real email. section 8.1 section 8.2

Listing 8.5 Using interfaces with dependency injection
string RegisterUser(string username, IEmailSender emailSender)   #1
{
    emailSender.SendEmail(username);                             #2
    return $"Email sent to {username}!";
}

The handler accepts an email-sending interface and uses its method. Its business task stays visible, while the choice of implementation is kept elsewhere. section 8.2

Loose coupling also matters between larger parts of a web application. With separation of concerns, a view generates HTML, application logic performs business work, and a page handler validates the request and chooses a response. Clear boundaries help keep a UI change from requiring a business-logic change. section 13.4.4

A change that reached too far

In one web app, business-layer class names were used to generate HTML. Renaming a misspelled class broke the website in users’ browsers. The problem was not the rename itself, but the hidden dependence between business logic and HTML generation. section 13.4.4

Aim to reduce coupling between logically separate parts, not to add wiring for its own sake. Dependency injection can be unnecessary overhead in a simple application; its value grows as dependencies and changes become harder to manage. section 8.1 section 13.4.4

How ASP.NET Core in Action, 3e covers it

How deep it goes
Defines coupling and works through handler dependencies, interfaces, and testing; defers application-class dependency injection configuration.
Examples
Uses an email-sending registration handler, alternative test implementations, and a website broken by a business-class rename.
What it assumes
Introduces dependency injection from basics while using C# classes, methods, and ASP.NET Core request handlers as examples.
What you can do after
Apply it via dependency injection and interfaces to reduce handler dependencies and substitute implementations during tests.
How it connects
Connects coupling to dependency injection, interfaces, unit testing, separation of concerns, and the MVC pattern.

Also explained in

Compare how 17 books explain coupling →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of ASP.NET Core in Action, 3e. The section links point to the parts of the book it draws on.