Dependencies are services required by an object to perform its responsibilities. In OOP context it can be thought as a parameter in a constructor.
In my experience I’ve never found a case for a valid cyclic A <--> B
dependency. Every time I find this it turns out to be one of two cases:
A
andB
should actually be a single component (AB
)- one of components violates single responsibility principle and should be divided into separate ones (
A1 --> B --> A2
)
To be clear, I’m not talking about cycles in objects used for data structures. I’m interested in components which provide behavior and collaborate between themselves.
3
This is just a self-fulfilling prophecy – whenever you find a cyclic dependency A <–> B where neither A nor B can be split up into smaller components, that gives you a striking argument for having A and B to be combined to single component (AB). As long as you argue that way, you obviously cannot come to a different conclusion.
Lets take a real-world example: Microsofts Scripting Runtime. This library contains components “File” and “Folder”. Each File has a parent folder, and each Folder can contain a list of files. So we have indeed a cyclic dependency. Can those two components be split into smaller ones? I guess not without changing the whole semantics. Do they have behaviour? Of course, there are tight to objects in the file system which can be deleted, queried, tested for existence, moved, and so on. Should they be combined into one bigger component? Well, in some sense they are already, they are both part of the FileSystemObject
part of the Scripting Runtime, and you cannot reference and use a File or Folder component alone. But now this boils down just to your point of view: on one level of abstraction, these two objects are different components on their own, on another they are not. And you can take this as proof of your hypothesis or a disproof, whatever you like.
5