Weak Coupling

From Jonathan Gardner's Tech Wiki
Jump to: navigation, search

Abstract

A simple design paradigm will help you build large, scalable systems.

Definition

Weak Coupling is the idea that different components should interact each a few other components in a few, well-defined ways.

The key is to limit the number of interactions, and to limit the complexity of each interaction.

Source of the Idea

I was thinking about car engines. I read about how you can buy after-market carburetors. I wondered why it was that you can adapt a carburetor for engines made by different companies, and then I realized why this was possible.

See, carburetors are rather simple devices. They mix the air and fuel together. They interact in a limited number of ways. First, they need clean, filtered air. Then they need fuel, pressurized. They mix the fuel and the air, and then allow the engine to suck in the mixture through obvious holes.

The most complicated interfaces was how the carburetor bolts on to the engine, and how the air filter bolts on to it. This is where the most time was spent explaining how to adapt the carburetor for different engine types, and where the manufacturer had to specifically change fundamental aspects of its design to adapt. Had there been a single standard for all air filters and all engines, the manufacturer would not even mention which engines it could fit on and such.

Having these well-defined, simple interfaces meant that people could experiment with many different kinds of carburetors. It also meant that if you had engine problems, you could test the carburetor rather easily and see whether it is the problem. (Does a mixture of fuel and air come out of the bottom?)

In Software

In software, try to limit the number of components that interact with each other. Try to simplify the interactions, using common standards with simple parameters. Try to reduce components into their irreducible component parts.

Cautions

One common problem is that we'll write components that simply pass through the interface of subordinate components. Don't do this. It means you're doing it wrong. The carburetor, for instance, has no idea what kind of spark plugs are being used or how many cylinders the engine has. Nor does it care who's driving the car.

As an example, consider the case of authorization. You want to limit the features of your software based on who is using it. One way to do this is to make every component aware of the authentication code, and have them ask repeatedly whether a particular action is allowed. Another way to do this is to calculate how the software should behave according to authentication, then turn on or off components appropriately. Which do you think is easier to work with? Is it easier to work with a component with 2 dependencies, or the same component, but it chooses different code paths based on what the auth module says?