Just What IS Circular Dependency?
Circular dependency.
Initially, the phrase invokes visions of things that we naturally know to steer clear of, like infinite loops. If we've come to OO from a procedural world, we've probably been groomed to fear circular dependency in coding, reinforced by having encountered errors that demeaningly declared "Can't resolve circular dependencies, Idiot!". Circular dependency...it just sounds dangerous, doesn't it? Unstable, unpredictable, uncontrollable; without an end and without a beginning, as in the proverbial question of the chicken and the egg. In OO though, circular dependency needn't be a taboo phrase at all.
When you take a look at the natural world (of which Object Oriented methodologies are a rough emulation of), circular dependencies are common occurrences, and actually viewed as good things. I need my job and my job needs me. That's circular. I need my spousal unit and my spousal unit needs me. That's got a roundness to it, too (pun intended). But, even deeper than the "we need each other" view, circular dependency implies that each of the two are within one another. Kinda like the ol' Frampton song, "I'm in you....you're in meEEeeeee....". A circular dependency in code is exactly the same thing: two objects who depend on one another for something and exist within each other. My user service needs my address service, and my address service needs my user service. We shouldn't be looking for ways to break these guys up! Rather, let us look at their relationship with admiration, because it is a perfectly natural one.
Now, some architects (we're ALL architects to some degree) might hold fast to a rule of "No Circular Dependencies", and rather than have two objects dependent upon one another directly, they'll create a third object to act as the broker between them. Instead of the two objects being injected into one another, those same two objects are instead injected into the third object, who orchestrates how they work together. I wouldn't say this is a bad thing, and in fact probably makes perfect sense to do so in many situations. Bottom line, though, is that we don't have to avoid circular dependency relationships when they do make sense.
All this talk about circular dependencies got me to wondering just how it all works under the covers. For instance, if I instantiate a CFC that needs another CFC internally, how can I do that without having first instantiating the OTHER CFC (who itself needs an instance of the first CFC I haven't instantiated yet!)? And if I DO manage to get instances injected into one another, will they be by ref or by val? In other words, will object 1 have a copy of object 2 inside of it, and my object 2 have a copy of object 1 inside of it? Or, will they both actually be seeing one another real time? Time for an experiment in object dependency! I'll share the results very soon.
Doug out.
P.S. Here is the link to my circular dependency experiment. (http://www.dougboude.com/blog/1/2007/06/Circular-Dependency-Experiment.cfm). It REALLY helped clear some things up regarding how to "think about" this topic.
Initially, the phrase invokes visions of things that we naturally know to steer clear of, like infinite loops. If we've come to OO from a procedural world, we've probably been groomed to fear circular dependency in coding, reinforced by having encountered errors that demeaningly declared "Can't resolve circular dependencies, Idiot!". Circular dependency...it just sounds dangerous, doesn't it? Unstable, unpredictable, uncontrollable; without an end and without a beginning, as in the proverbial question of the chicken and the egg. In OO though, circular dependency needn't be a taboo phrase at all.
When you take a look at the natural world (of which Object Oriented methodologies are a rough emulation of), circular dependencies are common occurrences, and actually viewed as good things. I need my job and my job needs me. That's circular. I need my spousal unit and my spousal unit needs me. That's got a roundness to it, too (pun intended). But, even deeper than the "we need each other" view, circular dependency implies that each of the two are within one another. Kinda like the ol' Frampton song, "I'm in you....you're in meEEeeeee....". A circular dependency in code is exactly the same thing: two objects who depend on one another for something and exist within each other. My user service needs my address service, and my address service needs my user service. We shouldn't be looking for ways to break these guys up! Rather, let us look at their relationship with admiration, because it is a perfectly natural one.
Now, some architects (we're ALL architects to some degree) might hold fast to a rule of "No Circular Dependencies", and rather than have two objects dependent upon one another directly, they'll create a third object to act as the broker between them. Instead of the two objects being injected into one another, those same two objects are instead injected into the third object, who orchestrates how they work together. I wouldn't say this is a bad thing, and in fact probably makes perfect sense to do so in many situations. Bottom line, though, is that we don't have to avoid circular dependency relationships when they do make sense.
All this talk about circular dependencies got me to wondering just how it all works under the covers. For instance, if I instantiate a CFC that needs another CFC internally, how can I do that without having first instantiating the OTHER CFC (who itself needs an instance of the first CFC I haven't instantiated yet!)? And if I DO manage to get instances injected into one another, will they be by ref or by val? In other words, will object 1 have a copy of object 2 inside of it, and my object 2 have a copy of object 1 inside of it? Or, will they both actually be seeing one another real time? Time for an experiment in object dependency! I'll share the results very soon.
Doug out.
P.S. Here is the link to my circular dependency experiment. (http://www.dougboude.com/blog/1/2007/06/Circular-Dependency-Experiment.cfm). It REALLY helped clear some things up regarding how to "think about" this topic.
Subscription Options
You are not logged in, so your subscription status for this entry is unknown. You can login or register here.
Re: Just What IS Circular Dependency?
I guess you may already know all this, but ColdSpring uses setter injection to handle circular dependency injection. Peter Bell's Lightwire offers the additional option of mixins as an alternative. Those are 2 ways to go about it.
Posted by Thomas Messier on June 20, 2007 at 8:13 PM

