Dependency Inversion Principle (The “D” of SOLID Programming Principles)
The Dependency Inversion Principle is the “D” in SOLID Programming.
Take your coding up a notch with the Dependency Inversion Principle! The DIP will result in architectures that are:
- More flexible!
- More secure!
- More stable!
The Book: https://amzn.to/3GPypMA
Transcripts (the following transcripts are auto-generated and may have typos or inaccuracies):
all right we’ve done it we’re at the d
The Dip the dependency inversion
principle which is the D in solid the
last of our solid uh programming
principles so
um what is the dependency inversion
principle and why have I been referring
to it in every single video because of
course it is last but not least it is
probably the most important thing here
um so while I’m stumbling over my words
we are going to continue and actually
learn what it means which is effectively
that the uh system will be more flexible
when your source code dependencies refer
to abstractions over concretions that is
that abstractions uh which hide the
implementation details when you import
those into a class or a module you’re
making your system more flexible when
you import the concretions that is the
units of code that that have the actual
implementation details you are making
your system more rigid and thus less
change tolerant and so the more we
invert these dependencies using the dip
the more flexible the system will be so
let’s get into it arcanium
welcome to a production by Dr Miles
Aaron
CEO and co-founder at arcanium ventures
don’t forget to subscribe subscribe
subscribe
alright so if you take the dependency
inversion Principle as this great thing
that you should apply to everything to
make your system more flexible at some
point your system is going to be so
flexible that it’s going to be a pain to
work with and you’re not going to be
able to get anything done so it becomes
obvious that we need some way of
thinking about this that doesn’t result
in putting some sort of interface or
adapter between every single function in
our code base and there are a couple
ways to think about this the way that
Uncle Bob shares that I think is is is
great
um is that you should think about the
volatility of those concrete classes or
concrete artifacts so
in your concretions you’ve got
implementation details that may be where
a function is actually described where
the function
um implementation details live and that
function may require some other
functions maybe they’re even language
built-in functions or maybe they’re just
some private methods that are also
concrete and you don’t need interfaces
between those because
um
they have this High cohesion and they’re
stable and so what Uncle Bob says is
look focus on the volatility of your
concrete abstractions so if it’s highly
volatile it’s probably something that
could cause issues if it’s extremely
stable
um then it’s probably something you
don’t need to worry about as much and
what the dip or dependency inversion
principle teaches us is that we should
favor favor
um stable interfaces so when you make
um your uh abstractions extremely stable
that means that you can rely on other
principles like liskov
basically we’re using open close
principle here we’re making that
interface very stable so that the um the
concrete Parts can be substituted in and
out or we can even change the concrete
Parts
um but we don’t really require any
change to our interface because we are
following that open closed principle and
list of substitution Principle as
described in previous videos and so
um
this gives you a way to kind of focus
your energy rather than making this
system that has way too many degrees of
freedom in a lot of ways I like to think
of software as when you when you add
these
abstractions these these layers in
between that don’t carry the
implementation details
um it’s kind of like you’re adding a
degree of freedom to a um to a mass
spring damper system in engineering or
mechanical engineering vibrations and as
you can imagine if you have this system
of Springs and masses and as you’re
adding more connectors and more Springs
and more hinges and eventually you get
this system that’s just floppy and
unusable and chaotic right and so you do
want to have
um
some control and some thought behind
this and the way to do that is according
to volatility now one way you can make
this practical is just look at your code
base all the git analytics are right
there for you and you can see which
um concrete uh parts of my code base
which implementation details are getting
the most traffic and the most changes
um well if that means they’re very
volatile I want to make sure that I have
a stable
um abstraction that they’re connected to
a stable interface so that it can
insulate the rest of my code base from
that instability just a bit and you can
use the dependency inversion principle
to accomplish that another way to think
about all this that I think is really
practical is to say that I want to put
all of my business logic in my
abstractions so the real you know meat
of what the application does is in the
abstractions and all the implementation
deal details are in the concretions and
so this idea of having your concrete
components flowing toward your abstract
components it allows us to say that
effectively the source code dependencies
are going against the flow of control
and that is all dependency inversion
really is and as you separate your
abstract components from your concrete
components and you have stable
interfaces to deal with the volatility
of those volatile concrete
implementation details you’ve
effectively set up an architectural
boundary and so as we go from thinking
about this in terms of you know classes
and functions and modules up until
components and then we start looking at
entire architectures
this becomes the the dependency
inversion principle leads to actual
architectural boundaries where you’re
saying hey this is a boundary between
abstract and concrete I can see that
there’s going to be something else on
the other side of that line and that
starts to to break your architecture
ultimately into domains if you’re
following some kind of domain driven
design but does create this
um this kind of high level
decoupling of of architectural domains
not just components and modules and
functions like so many things it’s like
software architecture is a big fractal
man
so now I want to talk about just three
ways briefly that you can use the
dependency inversion principle what
patterns that creates in your software
one example that I use all the time is
called the adapter pattern what is the
adapter pattern put simply it’s a way to
put a square peg in a round hole so when
you’re using the adapter pattern what
you’re doing is saying I want to be be
able to adapt this thing into that thing
and
[Music]
in practice that may look something like
a payment system for example where you
want to be able to use a stripe payment
processor or the Paypal payment
processor or some other payment
processor that comes along the way
without having to
um
re-do your application rewrite your
application code and so you use the
adapter pattern to have a little adapter
in between that allows different payment
processors to be plugged in without
changing any of the business Logic on
the abstract side of that architectural
boundary now
another pattern that will emerge is the
facade pattern so where the adapter is
talking about the Square Peg and the
round hole the facade pattern is more
about interoperability
of a kind of more complex system than
just one to one so I like to think of
the facade pattern and others have said
this as well as more of a control panel
it’s like abstracting away all of the
implementation details of a much more
complex system potentially you don’t
know how complex it is but it just gives
you some some knobs and some switches
and so it’s just kind of taking that
adapter pattern up a notch to create an
entire interface to another system where
the implementation details are
completely hidden and so the last
pattern that you’ll see emerge from the
dependency inversion principle that
we’ll talk about today is Factory
patterns and there are a few different
Factory patterns you can check out we’re
not going to to cover the details right
now but in general a factory pattern is
effectively
taking some disparate objects that
um or some objects that are created in
disparate places and creating a factory
to create them at one location to create
that abstract interface again to bring
what was
um putting implementation details on the
abstract side and bringing it into the
concrete side of your architecture
effectively it it changes where objects
are made so that where the objects are
used is not where they are created so
put simply since I just bungled the hell
out of that factories can be used to put
to separate where objects are used from
where objects are made and typically you
are going to make those objects in the
concrete side of your architecture
you’re going to use a factory to bridge
from concrete side to the abstract side
in order to allow your application
details to only depend on that factory
so that it can use those objects without
having connections to the details around
how those objects are made so we have
the adapter we’ve got the facade pattern
we’ve got factories the dependency
inversion principle you should check out
dependency injection which uses very
similar Concepts as well
um and you’ll be Off to the Races
hopefully you enjoyed this series on
solid I have to jump into a meeting so I
will see you on our next journey into
software architecture we’ve covered all
the basics now I think to a reasonable
level
um so I hope that we’ll get into some
more
um exciting architectures and start
looking at some open source repos real
soon see you next time