>  Blog

Managing Dependencies, Part 1

You have a system with object-oriented design. But the complex dependencies among classes are becoming hard to manage. What to do?


Pradyumn Sharma

August 15, 2017


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?

When class A uses class B, we say that class A is dependent on class B. Another term for dependency is coupling; class A becomes coupled with class B.



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.



Closing Remarks

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.