Tuesday, February 9, 2010

Injection and cyclic dependencies

Cyclic dependencies are bad, and they are usually a sign that one on more classes have too many responsibilities. Cyclic dependencies make your design rigid.

Finding the cycle
There are basically two ways cyclic dependencies can appear:
  1. You're using an injection framework such as Guice or Spring that automatically resolves cyclical dependencies without you knowing you even had them.
  2. You're using setters instead of constructors to initialize your classes.
The first case is easily exposed if you have suitable unit or scenario tests that are manually wired up.
The second case is simply bad practice. I really really advice you to use final fields and set them in the constructor. I can't begin to count the number of runtime issues I've had due to uninitialized fields.

So how do you resolve a cyclic dependency?
Resolving it is a much harder problem. You need to analyze your code and figure out what the cycle looks like, and what the root problem is.
Usually the problem is that one or more classes have too much responsibility and thus need many collaborators. Split up the classes in distinct responsibilities and remove dependencies you don't actually need.

Another option is to move some fields to methods instead and just pass along the collaborator you need. It's not always a good idea, but neither is keeping a large state inside a class.