I recently noticed decoupling as a topic in a question, and want to know what it is and where it can apply.

By "where can it apply", I mean:

Is it only relevant where compiled languages like C and Java are involved?

Should I know about / study it as a web developer?

closed as too broad by Jörg W Mittag, GlenH7, user40980, jwenting, Dan Pichelman Jun 12 '14 at 2:19

Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • It would help if you did a little research and ask a question based on any unclear parts of the definition. – JeffO Jun 9 '14 at 23:29
  • 2
    @JeffO - I think the world benefits from full concept questions as much as it does from specific nuance ones. "Why is the sky blue?" allows answers to cover the concept itself without going into extreme detail on the specifics. That is why I went ahead and asked my question without research. – user129679 Jun 10 '14 at 0:27
  • What's the specific problem you are having? As it stands now, your question is much too broad. In tis current form, the answer is essentially the entire text of Structured Design: Fundamentals of a Discipline of Computer Program and Systems Design by Edward Yourdon and Larry Constantine. – Jörg W Mittag Jun 10 '14 at 9:29
  • I think the answers here do a perfect job of describing the concept. It's like asking "What's the definition of this word in relation to programming" - How then is it too broad? @GlenH7 – user129679 Jun 10 '14 at 15:47
  • 1
    @jt0dd I'd have to agree. Just because you can explain something with a book, doesn't mean there isn't value in a more succinct answer. With programming literature, people often swamp you with details before giving a decent higher level overview. "What is OOP?" would be way too broad. But this is a reasonably specific topic IMO. – Erik Reppen Jun 10 '14 at 16:52
up vote 39 down vote accepted

'Coupling' is a term that describes the relationship between two entities in a software system (usually classes).

When a class uses another class, or communicates with it, it's said to 'depend' on that other class, and so these classes are 'coupled'. At least one of them 'knows' about the other.

The idea is that we should try to keep the coupling between classes in our systems as 'loose' as possible: hence 'loose coupling' or sometimes 'decoupling' (although in English 'decoupling' would mean 'no coupling at all', people often use it to imply 'loose coupling' between entities).

So: what is loose-coupling versus strong coupling in practice, and why should we make entities loosely-coupled?

Coupling describes the degree of dependency between one entity to another entity. Often classes or objects.

When ClassA depends heavily on ClassB, the chances of ClassA being affected when ClassB is changed are high. This is strong coupling.

However if ClassA depends lightly on ClassB, than the chances of ClassA being affected in any way by a change in the code of ClassB, are low. This is loose coupling, or a 'decoupled' relationship.

Loose coupling is good because we don't want the components of our system to heavily depend on each other. We want to keep our system modular, where we can safely change one part without affecting the other.

When two parts are loosely coupled, they are more independent of each other and are less likely to break when the other changes.

For example, when building a car, you wouldn't want an internal change in the engine to break something in the steering wheel.

While this would never happen by accident when building a car, similar things happen to programmers all the time. Loose coupling is meant to reduce the risk of such things happening.

Strong coupling usually occurs when entity A knows too much about entity B. If entity A makes too many assumptions about how entity B operates or how it is built, than there is a high risk that a change in entity B will affect entity A. This is because one of it's assumptions about entity B are now incorrect.

For example, imagine that as a driver, you would make certain assumptions about how the engine of your car works.

The day you buy a new car with an engine that works differently (or for some reason your engine was replaced), your previous assumptions would be incorrect. If you were code in a computer, you would now be incorrect code that doesn't work properly.

However, if all the assumptions that as a driver you made about cars is that: A- they have steering wheels and B- they have brake and gas pedals, than changes in the car won't affect you, as long as your few assumptions stay correct. This is loose coupling.

An important technique to achieve loose coupling is Encapsulation. The idea is that a class hides it's internal details from other classes, and offers a strictly defined interface for other classes to communicate with it.

So for example, if you were defining a class Car, it's interface (public methods) would probably be drive(), stop(), steerLeft(), steerRight(), getSpeed(). These are the methods other objects can invoke on Car objects.

All of the other details of the Car class: how the engine works, kind of fuel it uses, etc. are hidden from other classes - to prevent them from knowing too much about Car.

The moment class A knows too much about class B: we have a strongly coupled relationship, where class A is too dependent on class B and a change in class B is likely to affect class A. Making the system hard to expand and maintain.

A relationship between two entities, where they know little about each other (only what's necessary) - is a loosely coupled, or decoupled relationship.

Decoupling is generally all about seeing whether or not two things need to closely work together or can be further made independent. Independence is great because it makes those things easy to change or use somewhere else. Decoupling can be applied in many areas, not only development, and this is especially true for temporal decoupling, which can even be applied in your daily life (to some extent). Also noting, there are many types of coupling in software development to consider, and not all will be covered in the answer. You will have to do your research.

Two things, A and B, are coupled if there's a dependency between them. If A depends on B, you can use B without taking A into consideration. If you want to use A, you will have to also carry B over, as A depends on it.

In software development, usually, you can't remove coupling between components completely. Decoupling in that context normally means loosening the existing coupling. That is, making sure each component knows as little as possible about the other components around it.

This is probably the most common type of coupling found in the wild:

//Inside a class meant to display info for a particular Facebook user.
void DisplayFriends(FacebookUser user, FacebookClient client)
     Friend[] = (Friend[])client.GetConnection().ExecuteCommandForResult("getFriends:" + user.Name);

Here DisplayFriends is needlessly manually operating with the connection behind the Facebook client in order to get what it needs. DisplayFriends's class is coupled to both FacebookClient and Connection. If FacebookClient suddenly changes the kind of connection it uses, the app won't be able to get the Facebook friends anymore. We can remove the coupling between DisplayFriends' class and Connection by asking FacebookClient to provide what we need for us.

//Inside a class meant to display info for a particular Facebook user.
void DisplayFriends(FacebookUser user, FacebookClient client)
     Friend[] = client.GetFriends(user);

Now we don't really care how FacebookClient gets our friends. All we really care about is the fact that it gets them. Any change brought to its internal behavior won't damage our own class.

This kind of decoupling can be easily achieved by following the Law of Demeter for functions, which says (quoting Wikipedia):

The Law of Demeter for functions requires that a method m of an object O may only invoke the methods of the following kinds of objects:

  • O itself
  • m's parameters
  • Any objects created/instantiated within m
  • O's direct component objects
  • A global variable, accessible by O, in the scope of m

Since I mentioned about temporal coupling in the beginning of the answer, I'm going to shortly describe it.

Temporal coupling is normally considered when designing applications that execute algorithms in parallel. Consider two executable units (be them actual instructions, methods, or whatever you wish to consider a unit to be), A and B. We say A is temporally coupled to B if B must be executed before A is executed. If A is not temporally coupled to B, A and B can be executed at the same time. Build your own example for this one: think of the usual things you do in your daily life. Are there any two things that you do one after the other, but you could do at the same time?

Finally, to answer your last bit:

Should I know about / study it as a web developer?

Yes. For example, one of the most popular design patterns for web development (MVC) is all about decoupling.

The other answers do a good job of describing what decoupling is. I wanted to discuss your final question.

Should I know about / study it as a web developer?

The answer is an emphatic yes. It doesn't matter what kind of developer you are. You could be a web developer or an embedded systems developer.

Let's say that you have a class that generates custom URLs that are placed on your web page. You might be tempted to have the class write the URLs directly to the page, placing them in the href of an a tag. This might seem simpler at first. But what happens when you need to make a change to put the links in a email and send them to a user? Your current code wouldn't work because your URL generator is tightly coupled to the web framework you are using.

The better option would be to have a URL generator class that returns the URL as a string. This could be used by your web code and it could also be used by your email code. It may seem like more work upfront to have decoupled code, but the effort pays for itself over time.

Having code that is modularized and decoupled will make your code more understandable, more testable, and more maintainable, no matter what programming domain you are working in.

  • After this and the other two answers, I really do get this and see how I can use it. – user129679 Jun 10 '14 at 15:56