The following code is from K&B Ch2 Self test question 5.
Select the two statements that best indicate a situation with low coupling. (Choose two.)
A. The attributes of the class are all private.
B. The class refers to a small number of other objects.
C. The object contains only a small number of variables.
D. The object is referred to using an anonymous variable, not directly.
E. The reference variable is declared for an interface type, not a class. The interface provides a
small number of methods.
F. It is unlikely that changes made to one class will require any changes in another.
The correct answers are E, F..
I am confused as to why A is also not a correct answer. If good encapsulation promotes low coupling then A should be the answer as well. This question was asked once some time ago in this forum and no adequate answer was given. I am hoping Ankit, Punit or Ruben or any of the other ranchers can clear this question for me.
It shows relationship between two real-life entities. It shows loose-coupling + well encapsulation through interface. Here encapsulation is being used to build a has-a relationship between two classes using interface, if I used below code:
There car will directly depend on the BMWEngine concrete class, and in future if we want to change the engine type, we need to open this code and change the BMWEngine to some other engine say BMWHighDefEngine.
So changes made in Engine type needs to change BMWCar class. That is not loose-coupling, it is called tight-coupling.
If we had used interface then, we do not need any change in BMWCar class, so only declaring attributes private does not guarantee loose coupling.
Here all three codes are using well-encapsulation, but only one is using loose-coupling.
Got something or need more clarification?
Thanks Punit for your reply. So while encapsulation enhances low coupling it does not guarantee low coupling.
By using the interface variable or by coding to the interface you can ensure low coupling because the BMWCar class that is using it will not and need not know anything about the BMWEngine class. So these 2 classes are loosely coupled.
In your example if the variable private BMWEngine engine; is used would it be an example of Tight Coupling but encapsulated? Please let me know.
meera kanekal wrote:So these 2 classes are loosely coupled.
Only this code is loosely coupled.
meera kanekal wrote:In your example if the variable private BMWEngine engine; is used would it be an example of Tight Coupling but encapsulated?
Not only encapsulated, it is well encapsulated here, and it is tightly coupled with BWMEngine. The only relation between coupling and encapsulation is that coupling uses encapsulation, nothing more than that.
Very interesting discussion, thanks to both of you. Coupling and encapsulation are different concepts (but they are related in some ways.) Lack of (or poor) encapsulation can allow tight coupling, because it will be possible to access non-encapsulated variables directly from another class, which becomes dependent on the implementation of the class that contains those variables. It is possible to have a design with poor encapsulation and loose coupling, it's just that poor encapsulation makes it possible to create tight coupling.
So it appears, based on your discussion, that there are other ways that tight coupling can take place, aside from direct access to variables (which encapsulation would take care of.) The issue regarding "coding to the interface" is interesting. Is that a coupling issue though? If you have a BMWEngine member instead of an Engine member, is that considered tight coupling? Maybe your BMWCar uses facilities that are only available in a BMWEngine, like a turboCharge() method, which the Engine interface does not support. Now, if BMWCar used BMWEngine in such a way that a change in the implementation of BMWEngine would require a change in BMWCar's code, I would see that as a tight coupling issue. But this is something different, isn't it? I see why you are calling this tight coupling, because coding to the interface is always a more general mechanism. But in some situations you can't do that (like when BMWEngine provides methods beyond what is declared in the interface.) That's why I'm reluctant to call that tight coupling, which I would consider "the degree to which a change in the code of a class requires a change in the code of another class in order to maintain the integrity of the system."
Coupling can be maintained loose by always using the API provided by the class of the instance members, so that a change in the implementation of their class doesn't require changing the code in your class. I see the similarities with the "coding to the interface" approach. It's just that although there are similarities I don't think it's exactly the same thing. But I welcome discussion, as this is rather confusing, and a little arbitrary.
All code in my posts, unless a source is explicitly mentioned, is my own.