Circular dependency – is there a good design to eliminate

circular-dependency

I was writing some code and came across a scenario that I was thinking about doing a circular dependent class, which I have not done before. I then looked circular dependencies up and whether they are impermissible, and found that it is achievable but not desirable. But I have some dilemma regarding how to implement it without circular dependencies so I thought I should see if there are other suggestions available.

Imagine that you are building an index for a number of files, and those files have a number of attributes, including an attribute that records what files the particular file references.

Attempting to set up some classes mimicking such structure, I have written a number of classes.

  1. subClassA includes defining attributes of a file, let's call this
    attribute set A

  2. subClassB includes classification attributes of a file, let's call
    this attribute set B

  3. fileObject is an object representing a file, and has one
    subClassA object and one subClassB object.

  4. fileSet is an object representing a particular set of files, and
    is essentially a collection of fileObjects

As I was creating subClassB, I realized that the information related to reference files within subClassB is really just a simplified fileSet with limited subClassA information. Is it wise then to simply circular reference within subClassB a fileSet object? Or if that is a terrible idea, how should one go about storing the information? Technically, we can create another collection class object under fileObjectthat will store a bunch of subClassA objects, but I don't really favor that as I would need to duplicate certain functions of fileSet within that new class definition (for example, functions that checks those objects, combines those objects, and etc).

And if I do it where I have an object_M that includes a collection of subClassA and another object_N that includes a collection of subClassB (that has an object_M included), and a top level fileSet that includes one object_M and object_N, that will solve the problem, but we suddenly got a new problem of needing some way to link the objects within object_M and object_N together somehow, another complexity in itself.

With the given scenario, should I just go with circular dependency? Or is there a better way to do it altogether?

Best Answer

Circular relationships exist in the world, so if your object model is to accurately reflect such a relationship, the model must have circular logical relationships as well. There is nothing wrong with this.

The issue arises in the case of circular references, as a matter of implementation, not design. An object graph that cycles unto itself may have issues with the language's disposal mechanism, e.g. in the COM universe, which uses reference counting, the objects will never dispose, resulting in a memory leak.

The simplest way to avoid this is to use identifiers instead of object references. For example, instead of

class FileSet: List<File>

You might use

class FileSet : List<int>

class File
{
    public int UniqueID { get; }
}

And then give each File instance a unique integer identifier. When you need to find the files themselves, you can use the identifiers to select them via their identifier (e.g. as an index into an array) rather than by an actual memory reference. This design will never have circular object references-- because there are no object references to begin with.

As long as you take care of the implementation details diligently, there is absolutely nothing wrong with circular logical dependencies in your design.