design-patternsarchitecturesoftware-designcouplingcohesion

How to distinguish which following archetecture have lower coupling?


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:

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

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

# 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?

Solution

  • 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.