You have a system with object-oriented design. But the complex dependencies among classes are becoming hard to manage. What to do?
When you apply the Single Responsibility Principle (“a class should have only one reason to change”) in your application, you might end up with a lot of classes in the system. The objects of these classes would need to interact with each other, in order to accomplish the desired behaviour of the system. This can lead to complex dependencies among classes. How do we deal with dependencies?
Are Dependencies Bad?
Yes, and no. There are drawbacks of dependencies, but there are also benefits of these.
Dependencies are like cholesterol. There is good cholesterol, and there is bad cholesterol.
While bad dependencies may hamper reuse, and affect the stability of a system, well-crafted dependency relationships can:
- provide clean separation of concerns
- make it easier to change the behaviour in a system
- provide plug-and-play replaceability of classes or components.
Let us look at some drawbacks of dependencies. We’ll consider two classes, A and B, with class A being dependent on class B.
- If you want to reuse class A from the current application in another application,
you need to reuse class B as well, because there is a reference to class B somewhere in the
source code of class A. If you don’t need any behaviour of class B in the target application, then class B just becomes extra baggage.
- If, for some reason, you need to change the interface of class B, then you may
need to change the implementation in class A (if somewhere in class A, you are invoking
the function of class B that is being changed). Of course, you don’t generally go around
changing the interfaces of classes, but sometimes, you may need to do so, for example,
in order to fix a faulty design or incorporate changes in requirements).
But that does not mean that all dependencies are bad, and should be eliminated.
You cannot eliminate dependencies from a system unless you are willing to write
all the code in one single class!
So how do we work with dependencies such that we get the desired benefits,
but we minimize the costs of using these?
Strong Coupling vs Weak Coupling
When a class is dependent on another class, it is called strong coupling
(also tight coupling). But when a class is dependent on an interface,
it is weak coupling (or loose coupling); the reason being
that the class is not aware of, and therefore dependent on or coupled with,
any concrete class. It is only aware of the interface type, and any concrete
class providing implementation of the interface can be supplied in place of the interface.
Let us look at the following design:
In this design, the class BankLoan is only
dependent on the interface InterestStrategy,
but is not aware of any concrete implementation of the interface. As a result of this:
- We can reuse the BankLoan class in some
other application, if required, without necessarily reusing any of the implementations of the InterestStrategy interface.
- New classes implementing the InterestStrategy
interface can be added, without any impact on the BankLoan class.
(For a description of the complete BankLoan example,
look at the post on Open-Closed Principle):
Erich Gamma, in his landmark book “Design Patterns”, presents this concept as: Program
to an interface, not to an implementation.
When a class refers to another object only by its interface type, when required, the other object
can even be dynamically selected or changed.
Dependencies are needed to organize our code into meaningful classes that group closely related
features. This lets us model the behaviour of a complex application. However, it’s important to pay
close attention and manage the dependencies well; otherwise we may have a system that is brittle and
hard to change.
Using interfaces makes the design more flexible. But that is just a starting point for managing
dependencies. A more involved, and related concept, is the D in SOLID Principles, “The
Dependency Inversion Principle”.
We’ll look at the Dependency Inversion Principle in a follow-up to this post, very soon. Stay tuned.