Cycles in dependency injection

9. November, 2010

There is an old argument in DI: How to handle dependency cycles?

Say you have logging and reading of configuration files. Logging needs the config (how should I log?) and the config needs to log (where was the config read from?). How do you solve that?

It gets worse when people insist that DI fields have to be final (i.e. immutable) or that dependencies must be injected via constructors. How on earth can you create the logger if it needs a config instance as constructor parameter and the config instance needs a logger in the constructor?

The “solution”: Proxies. You create the config instance with a proxy to the real logger, then create the logger with the config instance and finally, you replace the proxy with the logger.

Why is that solution bad?

Because your code now has two bugs: You have a cyclic dependency (bad but sometimes necessary) and you’re trying hard to pretend you don’t have one. If someone will have to fix a bug in there, they won’t expect that the “final” instances can actually change.

On top of that, it makes your code inflexible. My gut feeling is that there is a reason why you can’t add plug-ins to Eclipse without having to restart the whole IDE. The infrastructure to manage plug-ins can add and remove them at runtime – unless you prevent that by using “solutions” code like the one outlined above.

Or as Yoda would have said: Much fear in you I sense.

Get over your fear. Write better unit tests (which will also become more simple if you don’t use final fields). Avoid “final” unless Java forces you to use it.

%d bloggers like this: