0

I have read a bounch of articles about coupling which all without exception view it from a high perspective. They rarely elaborate it with real projects.

So, there is a specific question I met:

Simplified model as following:

  • architecture 1
# m: module
      ---------                                                                 
      |context|
      ---------
     /  |    |  \
    /   |    |   \
----  ----  ----  ----
|m1|  |m2|  |m3|  |m4|
----  ----  ----  ----

Context depends on m1, m2, m3, and m4, and only one single dependency.

  • architecture 2
# m: module
# al: abstract layer
      ---------
      |context|
      ---------
      /       \
   -----     -----
   |al1|     |al2|
   -----     -----
  /   |       |   \
----  ----  ----  ----
|m1|  |m2|  |m3|  |m4|                                                          
----  ----  ----  ----

Context depends on al1 and al2, and al1 and al2 depend respectively on
m1, m2 and m3, m4. They all have only one single dependency.

The questions is:

  1. Which one have looser coupling than the other and why?
  2. If answer is latter, then is there any relation between loose coupling and more layers?
yixuan
  • 375
  • 2
  • 17

1 Answers1

1

Consider Coupling not as a number that you can measure. Coupling is the property of code using something from other code. Coupling is not just the number of dependencies or includes. The motivation of loose coupling is to reduce the ripple effects that occur when changing something in your code in order to avoid that you also have to change something somewhere else, and then again something else and then more and more and so on.

That been said consider that in architecture 2 you have some things in al1 and al2, which in architecture 1 you have in context. That has consequences: If you have to change for example the code of al1, then you can immediately say that m3 and m4 are not affected. That is good. And that is the purpose of loose coupling. You change something and you know in advance that in m3 and m4 you have no consequences. In professional life knowing such things is valuable because you can well estimate the consequences of modifying al1.

If you don't have al1, then you only know, there is something in context. So typically you cannot estimate the consequences, you have to recompile everything (coupling has indeed an impact to the compilation time). Changing something in context is more a surprise than changing something in al1. You don't want surprises. And therefore the architecture 2 is probably better. Things are more loosely coupled.

Concretely: In your diagram of architecture 2 m3 and m4 do not depend on al1. This is clearly a reduction of the coupling.

But the word coupling is not the only terminus of importance. Architecture 2 demonstrates that there are two parts that are not related to each other (because al1 and al2 do not depend on each others). Both parts have a strong "cohesion". Grouping them together in context would be a mistake. Things that don`t belong to each others shouldn't be grouped together.

To your question 2: The answer is yes, if your abstraction does not add extra complexity. But typically abstraction does add extra complexity. So that means, there is no general answer to your question. In your daily life as software developer you are often in the situation to establish an abstraction layer with the objective to improve the code but then you realise that you have overengineered things and the abstraction layer made everything to the worse.

You may have heared the word "refactoring". It is important to change such wrong architecture decisions. You often have to try out things in the architecture to see what does they mean and restructure the code. It would be nice to have a criteria that helps you to decide what architecture is better.

But if you mean with "layers" levels of inheritance, then the general answer is: Inheritance is a very strongest coupling and often does not reduce the coupling.

habrewning
  • 735
  • 3
  • 12
  • I agreen almost whole thoughts. Each architecture has their own strengths and usage scenes. But one claim: **Grouping them (`al1` and `al2`) together in context would be a mistake** might be wrong. Group them together under `context` because they both are depended on by `context` they don't need any relationship for it. – yixuan Aug 24 '22 at 10:44
  • I would like improve my answer, but don't fully understand your point. Assume you want to change something in `al1`. You typically have to recompile `m1` and `m2`. If you don't have this intermediate layer, that thing will be in `context` and you would have to recompile everything. That is an indication that the coupling is actually tighter. Of course with the `context` only solution, you don't see these dependencies any more. But as I said. Coupling is not a question of dependencies or includes, but a question of "how much" lines of code are dependent to other lines of code. – habrewning Aug 24 '22 at 17:08
  • I find that I misunderstanded your words, Your are right. but for this `Coupling is not a question of dependencies or includes, but a question of "how much" lines of code are dependent to other lines of code`, isn't the coupling the number of modules one module depends on? Counting the lines of code would be a mistake. – yixuan Aug 27 '22 at 12:31
  • 1
    Coupling is rather a question how rigid your code is in general. A class X can use a class Y by calling exactly one well defined method or by accessing crisscross all the data objects of it. The first option is least coupled than the second option. But the dependencies are the same. Y may not even be aware of X manipulating it. X may destroy something in Y. So the correct functioning of Y depends also on the correctness of X. There is actualy a reverse dependency. This is an example of a very strong coupling. This is not visible as a file include. It is just a semantical dependency. – habrewning Aug 27 '22 at 15:51
  • See for example this discussion here: https://www.linkedin.com/pulse/why-class-inheritance-should-considered-harmful-vedran-bilopavlovi%C4%87 To their opinion inheritance is some sort of bad because it creates a tight coupling. They rather prefer composition over inheritance. Normally when talking about coupling, you mean such sort of questions. Why is one design better over another one? But if you just look at includes or file dependencies, there is no difference between composition or inheritance. File dependencies do not measure coupling. – habrewning Aug 27 '22 at 17:10