Question

Not a new programmer but new to architecture design. I'm about halfway through "Clean Architecture" by Robert C. Martin and I've realized that few components in my program need to have their dependencies inverted. The program is using C#/ASP.NET MVC but that shouldn't be relevent.

One example is the Investigation component. The gist of this workflow is that the Web creates and runs an Investigation. The Investigation creates a list of ICheck based on its configuration and runs them. A CheckImplementation is more often than not just a passthrough to an ApiIntegration, although some CheckImplementation need to use the database. There are currently 10 CheckImplementation and the system should be designed for that number to be grow easily.

The current architecture is as follows:

enter image description here

Investigation violates all sorts of principles, Stable Dependency Principle, Stable and Not Abstract (Zone of Pain), etc.

I redesigned my architecture by:

  • Check implementation and API integration have been consolidated into CheckImplementations, which replaces the old ApiIntegrations. This eliminates the redundant CheckImplementation->ApiIntegration structure from before.
  • Inverted the Investigation->ApiIntegrations/CheckImplementations dependency, which creates a Stable/Abstract dependency in favor of a Concrete dependency.
  • Used the Factory pattern to achieve the Dependency Inversion.

Architecture After

Is this a good application of Dependency Inversion Principal? I'm familiar with using dependency inversion at the class-level via Dependency Injection, but using it at the component-level is an entirely new concept to me.

Also, I didn't include it in the diagram but I have a Models component which only contains data structures. Instead of creating an entirely new component for the ICheck interface, would it be wise to just place it in Models?

Was it helpful?

Solution

You haven't achieved anything with your redesign, the Investigation module is still transitively dependent on CheckImplementations module.

To properly achieve the decoupling of your Investigation and CheckImplementation modules, it would be necessary to create ICheckFactory interface, so that dependency between Investigation and CheckFactory is inverted, eg. CheckFactory depends on Investigation through the ICheck interface.

After that I would recommend to simplify the design by moving ICheck and ICheckFactory into Investigation module and Check and CheckFactory into CheckImplementations module. Combined with the above, the CheckImplementations module would depend on Investigation module, resulting in inverted dependency compared to what you have now.

Licensed under: CC-BY-SA with attribution
scroll top