0

Specifically dependencies that have very specific implementations.

For one example, the Hangfire enqueing library. This has very specific implementations to enqueue background jobs to be executed asynchronously.

I created a wrapper around this dependency, but it ended up being tightly coupled to the dependency itself. Then, when I use my adapter in other assemblies, they all end up needing a reference to Hangfire anyway.

Why would I want to wrap the Hangfire dependency (or similar dependency) in an adapter?

If I ever switch to a different enqueueing system, all of the code will go "red" where I need to switch it anyway. I can see an argument to be made for unit testing and/or late binding, but is there any other reason?

Mattkwish
  • 753
  • 7
  • 16
  • 1
    I don't think this is opinion based. From "when I use my adapter in other assemblies, they all end up needing a reference to Hangfire", you can clearly see that he wants to know how to organize his code so that this is not the case. There are well known architectural patterns that he can use to achieve this. – Yuli Bonner May 31 '18 at 14:40
  • 1
    Yes! The core of the issue boiled down to figuring out how to prevent every single assembly requiring a reference to a dependency. Yuli, you really did help, thanks! – Mattkwish May 31 '18 at 14:47

1 Answers1

1

Your adapter should implement an interface (a port in hexagonal parlance). Your interface should not have a reference to your dependency. The implementation will have this reference. Your business logic should only use the interface (the implementation will be injected). This way your business logic does not have a reference to your dependency. If your dependency changes you just write a new adapter that implements the same interface. This way your business logic doesn't change, nor the associated business logic unit tests. This is a substantial benefit.

Yuli Bonner
  • 1,189
  • 8
  • 12
  • But if my implementation requires a specific dll, then any project that uses that implementation in the end also requires that dll, correct? So even when I program to the interface, and use DI for the implementation, the main solution needs the required dll or else the implementation will throw an exception. There would be no compile-time errors without the dll, however. – Mattkwish May 30 '18 at 16:47
  • 1
    Here's the crux : "any project that uses that implementation." Your business logic project should not use the implementation. It should only use the interface, thus no reference needed. – Yuli Bonner May 30 '18 at 17:00
  • 1
    Maybe I should clarify, the interface (port) should be defined in your business logic. Your adapter, which implements the interface, will reference both your business logic and your external dependency. Your business logic should be free of dependencies/references. – Yuli Bonner May 30 '18 at 17:09
  • 1
    See hexagonal/Onion/Clean/Ports and Adapters Architecture examples. – Yuli Bonner May 30 '18 at 17:10
  • Even if I only use the interface in my business logic, at runtime in the business logic project, it executes `MyInterface.MyMethod`, which eventually ends up at the adapter, which executes `MyDLLMethod`, which requires a reference to the dependency DLL, correct? So no matter where I call `MyInterface.MyMethod` from, I end up needing a reference to that DLL, or am I incorrect? – Mattkwish May 30 '18 at 17:11
  • Just saw your most recent comment - I'll take a look now, thank you. – Mattkwish May 30 '18 at 17:11