by Miško Hevery
So you discovered dependency injection and GUICE and you are happily refactoring and writing new tests for you code until you come across this circular reference.
class A {
final B b;
A(B b){
this.b = b;
}
}
class B {
final A a;
B(){
this.a = new A(this);
}
}
+---------+ +---------+
| A |<-----| B |
| | | |
| |----->| |
+---------+ +---------+
Hm, dependency injection says that you need to ask for your dependencies and so the resulting code will be:
class A {
final B b;
A(B b){
this.b = b;
}
}
class B {
final A a;
B(A a){
this.a = a;
}
}
But now we have a problem, we can’t instantiate this (I know GUICE can through proxy, but it is not clean and it does not help us in tests). So the real problem in situation like this is mixing of concerns. One of the two objects is hiding another object C. Either A contains C or B contains C. To find out which one it is, list all of the methods in your class A and class B and. The shorter of the two lists is your hidden Class C.
+---------+ +---------+ | A |<-----| B | | | | | +-+ | | | | +->|C| | | |------+---->| | | | | | +-+ | +---------+ +---------+
Suppose B has the shorter list. We now extract all of the methods in B which are accessing the state of hidden C methods into a new object C like this:
+---------+
+---------+ | B |
| A |<-------------| |
| | | |
| | +---+ | |
| |--->| C |<----| |
| | +---+ +---------+
+---------+
class C {
C(){
}
}
class A {
final C c;
A(C c){
this.c = c;
}
}
class B {
final A a;
final C c;
B(A a, C c){
this.a = a;
this.c = c;
}
}
When you go through this exercise you will realize that the C was always an object in its own right but you have never thought about it that way, so the new code is actually better OO. From testing point of view you can now test each class in isolation.



5 responses so far ↓
Brilliant. I think I like this an *awful* lot, but I still don’t get one part. In your sentence:
“To find out which one it is, list all of the methods in your class A and class B and. The shorter of the two lists is your hidden Class C.”
There’s a strange sentence-terminating ‘and’ in there. I don’t understand what the two lists are. Could you state this again for clarity?
Thanks heaps!
I just found your blog, a fantastic read.
I just wanted to ask something.
Could you give a more specific example?
For example, lets say I have two classes:
Dog(Owner o)
+getOwner()
Owner(Dog d)
+getDog
.. what would you do in this case to break the circular dependency? What would your class C be?
@ Dennis,
Putting it like that, there is not enough information. What is it that Dog needs of owner? And What does owner need of Dog? You need to find the subset and extract it. Without knowing that information I can’t tell you the solution.
– Misko
Thanks for your response Misko. My example was a little contrived, sorry about that. I’m trying to use my imagination a little.
I’m just curious to see a more realistic example of how this technique could be used. I’m having trouble seeing what an example of class C might be.
Bravo! I have been trying to get people to understand this problem for years.
Leave a Comment