High coupling is bad, low coupling good.
I won't put it so black and white. Some coupling is necessary. Plus some roundabout ways to get rid of coupling can introduce too much overhead. In particular for applications that need to respond in real time. It is trade-offs.
Yes, you want to avoid high coupling. However, if introducing patterns in an attempt to lower coupling is preventing you from meeting your requirements first (which might include response time, time budgets, etc…) then it is not worth it.
In Java, when A creates an object B and calls one of its methods it's said to be tightly coupled. But if we create an interface IB, used from A where B implements IB it's said to be loosely coupled. I don't see why since one change in the interface would have an impact in A and B. And one change in B would have an impact in IB and A. They still seem to be call coupled.
Yes, they are still call coupled. Well, depends on how you define the metric. However, interfaces are not the right tool if you want to deal with that.
Regardless, with the interfaces, the classes would be loosely coupled in that A is not coupled directly to B. You could have other implementations of the interface.
A common anti-pattern is making an interface that matches what the consumed class offers. You should make an interface that matches what the consumer class needs. See interface segregation. The interface becomes a requirement for consumed class.
If you conceptualize the interface that way, the interface would change only when it is necesary for its consumers. When changing A, you can decide to change the interface or use a new one.
If we decide to change the interface when changing A, the change would propagate from A to B. Instead of it propagating from B to A. However, we do not have to decide to change the interface, or we can introduce an adapter that implement the interface and wraps B. That is, we have opportunities to stop the change from propagating. That is what we want. And that is what loose coupling (which is still coupling) buys us. We design to have more options, not less.
Again, that is not solving call coupling.
The same rationale applies to the Facade GoF design pattern. It's said it promotes low coupling, since we put an intermediary between a subsystem and the client code. In this case, it looks like we transferred the problem from the client code to the Facade. Since a change in the subsystem would have an impact on the Facade instead of the client code. The client code is no longer coupled to the subsystem but the Facade is.
The facade hides whatever you do behind it. It is similar to how an object encapsulates its state. The facade encapsulates a (sub)system. The consumer code only needs to talk to the facade and it is unaware of the details behind it.
Of course, it is still coupled. And yes, you have moved the problem to the Facade. However, thanks to the Facade, the consumer code does not have to change because of the changes of what is behind the facade.
But the answers are not specific enough. First, since encapsulation is also about treating objects as black boxes, the first answer does not specify any gain by using interfaces compared to regular classes (= tight coupling, in case it's all about black boxes)
If you use the class directly, then whatever the consumer code needs must be implemented by the class. If the consumer code uses an interface instead, then it does not have to be implemented by any particular class. You can change the class without the consumer code being aware of it. The consumer code has less knowledge, thus it is less coupled.
What interfaces provide is decoupling between the interface and the implementation when multiple implementations exist. But doesn't solve anything related to call coupling.
Correct, this is not about call coupling. You are the one narrowing the discussion to call coupling between two classes and an interface. And then wondering why they provide nothing.
Interfaces are not the right tool to deal with call coupling. Instead you want an event driven architecture, a consumer subscriber pattern, or similar. That way, there might not even be an implementation on the other side. Of course, some infrastructure might be required, if not provided by the language and runtime. Oh, this is Java, yeah, some infrastructure required.
Best Answer
The only substantial reference I could find to "data coupling" is quite a bit different from the Wikipedia and article definitions.
In the LDRA paper, data coupling is
Their example is:
The paper says
display_airspeed
is coupled tospeed
because it's declared and set independently ofdisplay_airspeed
.display_airspeed
will break if the order of operations is switched above.I don't like this definition because I think spirit of the term data coupling is broader. Yes,
display_airspeed
is data coupled tospeed
, but that's irrelevant to the execution and flow of the program. Their example is more indicative of "Common coupling" according to the Wikipedia entry.The Wikipedia entry and the article you've read take a broader definition of data coupling. Wikipedia uses:
Yes.
print
is still data-coupled in two ways.text
is in itself data coupling according to the definition, because removing the parameter and makingprint
parameter-less or adding a parameter would be a breaking change. Thereforeprint
is data coupled to being passed a single parameter.print
is coupled to the type oftext
. Even in a dynamically-typed language like your example, ifoutput_to_screen
expects aFoo
to be passed in, and I callprint
and pass it aBar
, it will breakprint
(because print is incorrectly callingoutput_to_screen
). Thereforeprint
is data-coupled to theFoo
type transitively because ofoutput_to_screen
. I'm not actually sure this is data coupling. It may actually be "external coupling" to the type oftext
.By removing the call to
to_s
, you've removed what I believe is "Stamp coupling (Data-structured coupling)" (from Wikipedia's definition)In this case
print
only really needs a string, but the parameter is a different type, andprint
accesses theto_s
member oftext
to retrieve a string value. Thereforeprint
is couple to the structure oftext
and changing or undefiningto_s
is a breaking change.