2

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?

  • Is the main issue here that Investigation is creating the CheckImplementation instances? To introduce a dependency injection, you can simply have something else (e.g. InvestigationUtility) create the ICheck instances and pass them to Investigation. – JimmyJames Jul 1 at 13:25
2

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.

| improve this answer | |
  • Great solution, I was worried that Investigation was still transitively dependent on CheckImplementations. After redesigning to your suggestions would it just be a matter of using dependency injection to give Investigation the correct implementation of ICheckFactory? – zwaller Jul 1 at 17:12
  • @zwaller Yes, exactly. – Euphoric Jul 1 at 17:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.