Question

Consider a component-based system, where components use each other's capabilities and may have soft circular dependencies. Here a "soft dependency" is when a dependent component will use the services of the other if it is available, but can still function property without one. There are also hard dependencies in the system, when one component can not function without the other, but they are not circular. Is this a good design or should one avoid circular dependencies even if they are soft?

This question has arisen from the fact that C# doesn't allow projects to have circular dependencies between projects and I use projects to isolate components in my system. They are then compiled into assemblies and a subset of them is loaded dynamically by the application depending on configuration.

P.S. If you mark this question as not constructive, please add a comment suggesting a site where I can ask design questions that do not always have an single objective answer and require some discussion.

Update: An example of the soft dependency as requested: a client manager component needs to use services of the location component, to tell clients about the location of objects (this is hard dependency as clients must know where objects are located). The location component however also wants to use the interface of the client manager component to extend client's API and allow them to set the position as well (this is soft dependency) as client manager component may not be present in the system if the current instance of the server doesn't need to talk to clients.

Was it helpful?

Solution

From the example you provided in the update, I'd express your need in terms of static (instead of hard) and dynamic (instead of soft) dependencies.

I wouldn't consider as a design problem if ClientImpl uses statically LocationImpl and LocationImpl uses dynamically ClientImpl (through a ClientInterface). ClientImpl could even inject itself in LocationImpl through a LocationImpl method that would take a ClientInterface as argument. This constitutes a pretty widely adopted object-oriented pattern (call it Injection of Control, or Dependency Injection the philosophy behind is the same, see what Martin Fowler wrote about it almost a decade ago).

Btw, all this implies that ClientImpl has a higher level than LocationImpl that itslef has a higher level than ClientInterface.

When design documentation refers to circular dependencies as a major design problem, it typically refers to static/hard dependencies.

This question has arisen from the fact that C# doesn't allow projects to have circular dependencies between projects and I use projects to isolate components in my system.

Indeed, because chances are very high that if two assemblies reference each others, a static/hard dependencies would be created. MS has always considered assemblies as the .NET way to implement the notion of component and thus, VS prevents circular dependencies between components.


Interestingly enough, the .NET Framework design comes with several circular assemblies dependencies!

enter image description here

enter image description here

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top