Francisco Silva
Francisco Silva

Reputation: 1

Dependency inversion principle

Here in this blog: https://blog.ploeh.dk/2013/12/03/layers-onions-ports-adapters-its-all-the-same/#db5adf784deb4c9b92a656627283c9da.

They said that changing the direction of the dependency between the Domain library and the Data Access Library it would respect the DIP. How so? Isn't the idea of DIP the loose coupling, for example, one library references the interface of another instead of the concrete definition? They refer as an example the Ports and Adapters or Onion, but in a .NET project for my domain to send data to a repository it needs a dependency of the data access layer so I think it's impossible to make the dependency in a different way.

Upvotes: -1

Views: 104

Answers (2)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57307

How so? Isn't the idea of DIP the loose coupling, for example, one library references the interface of another instead of the concrete definition?

I would say no -- loose coupling is not "the" idea of dependency inversion principle; the separate handling of "high level" and "low level" modules is an important part of the motivation for what is going on.

The original authoritative reference on Dependency Inversion Principle is Robert Martin's 1996 essay, linked here so that you can read and draw your own conclusions.

The principle is generally expressed using two bullet points:

  • High level modules should not depend upon low level modules. Both should depend upon abstractions.
  • Abstractions should not depend upon details. Details should depend upon abstractions.

Here's the passage that I think is lost when you look at the bullet points in isolation, and is critical to understanding why Seemann draws his arrows the way he did.

It is the high level modules that contain the important policy decisions and business models of an application.... Yet, when these modules depend upon the lower level modules, then changes to the lower level modules can have direct effects upon them; and can force them to change

....It is the high level modules that should take precedence over the lower level modules. High level modules simply should not depend upon low level modules in any way.

Moreover, it is high level modules that we want to be able to reuse. We are already quite good at reusing low level modules in the form of subroutine libraries. When high level modules depend upon low level modules, it becomes very difficult to reuse those high level modules in different contexts. -- Martin, 1996

As usual, The Literature broadly sucks; we've got Martin here writing about high and low as regards to policy, at the same time that we've got people writing about layers/tiers (typically with presentation on top, data access at the bottom), and of course we're reading this today in a context where we've got an inside/outside orientation.

But it's not too difficult to see what Martin means here - that the description of our policies for tracking commercial containers as they move from one port to another, or the description of the processes we use to track restaurant reservations, should be outside of the blast radius of changes like "we're switching to a faster database" or "we're relocating our hosting from on-prem to cloud".

In the context of libraries, and managing a dependency graph, this idea is expressed as the constraint that it is acceptable for "details" in the data access library to "depend on" abstractions defined within the domain library, but that it is not acceptable for "details" in the domain library to "depend on" abstractions defined in the data access library.

All models are wrong: three simple boxes with directed lines connecting them is, at best, an imperfect representation of the idea, which in itself is an abstraction that hides many details that may leak through in practice. So... not your fault that it wasn't clear.

Upvotes: 1

jaco0646
jaco0646

Reputation: 17144

Yes, the DIP relies on abstractions in place of concretions, which does result in loose coupling. It also "inverts" the flow of control in a program, by allowing compile-time dependencies to point in the opposite direction of runtime dependencies.

Bob Martin talks about this concept in many places, for example in a talk at Yale School of Management.

Here's our module M (perhaps a domain module). Here's our module N (perhaps a repository module). It has a function named F (perhaps a DB read). The flow of control will go from M to N calling F. But, if I have polymorphism, if I have an OO language... my M module can mention the name of an interface and use it to call F. The N module will derive from that interface.

And notice what has happened to the compile-time dependency: it points against the flow of control. This is what polymorphism gives you. Polymorphism gives you the ability to create one module calling another and yet have the compile-time dependency point against the flow of control instead of with the flow of control.

The dependency pointing against the flow of control is the inheritance dependency from N to the interface. So both M and N have compile-time dependencies pointing at the interface, even though the runtime dependency points from M (domain) to N (repo).

Selective application of this concept defines the Dependency Inversion Principle.

Upvotes: 0

Related Questions