Mike Spille’s article on Inversion of Control containers
was, as always,
thoroughly researched and quite illuminating.  It also brought up the old issue of cyclical dependencies, which are usually identified
as a very ugly practice.  Software fundamentalists are quick to point out
that if you see a cycle in your classes or your packages, you should immediately
remove it.

I wish it were that simple.

The sad truth is that sometimes, cyclical dependencies are not only
necessary, they are actually quite essential and contribute greatly to making
your code more readable and maintainable.

The dangers of cyclical dependencies are well-known (stronger coupling,
fragile build, etc…) as are the remedies (the introduction of an interface is
usually a good start).  For example, the following dependency:

public class Person {
public List<Account> getAccounts();
}
public class Account {
public Person getOwner();
}

can be refactored like this:

public interface IAccount {
}
public class Account implements IAccount {
}
public class Person {
public List<IAccount> getAccounts();
}

By introducing an interface, you have decoupled your two concrete classes,
which is usually a good thing.

The point of this post is not to offer a
critique of this method but to bring up two points:

  • Your code is more decoupled but it’s also more complex.
  • The concept of a "cyclical dependency" is highly dependent on the
    language you are using.

The second point is obvious:  the perception of a "cyclical dependency" is very different in
Java and, say, in C++, where you will usually declare and implement two coupled
classed in the same file, thereby reducing the physical dependency (but not the
logical one).

The first point is more subtle.

In the example code above, you now have three classes where you used to have
two.  And two of these three classes need to be kept in sync (IAccount must be modified whenever
you modify Account).  As I said earlier, it is usually a good thing, but
not always, as was the case with Mike’s JobDispatcher example.

I find that most of the time, cycles are created as a consequence of a
previous refactoring in which you have been breaking down one complex class into
two smaller ones.  There is clearly tension between two goals that are
sometimes at odds:  you can’t always decrease both the complexity and the "coupledness"
of your code (I know it’s not a word, sorry, couldn’t come up with a better
one).  If you improve one, you will probably make the other worse.

Overall, introducing an interface in your code is usually the right choice,
but there are some exceptions.  Keep them in mind the next time someone is
trying to convince you that your code is evil because two classes have a
circular dependency on each other.