Placeholder Image

Subtitles section Play video

  • (upbeat music)

  • - [Eric] The dependency and version principle

  • gives us guidance to not design our high-level modules

  • to depend on our low-level modules,

  • but that sounds counterintuitive,

  • because it advises us to think about designs

  • in a manner that's really the opposite

  • of what we're used to.

  • We're used to thinking about designs

  • as top-down decompositions.

  • We take a problem and we factor it

  • into a high-level set of components

  • that depend on a lower level set of components.

  • We often think of the high-level components

  • as some kind of policymakers

  • that are commanding a set of low-level components

  • who are really carrying out all the real work.

  • The problem with this approach

  • is that it typically tightly couples

  • our high-level components to our low-level ones.

  • A symptom of this tight coupling

  • is that it's often difficult to take

  • that high-level component and then to go reuse it

  • with the totally different underlying implementation

  • of the low-level components.

  • If our design is right,

  • that's something we really should be able to do.

  • The dependency inversion principle

  • tells us to think of this in a different way,

  • by reversing the direction of this dependency.

  • It tells us really two things.

  • First, as we've said, high-level modules

  • should not depend on low-level modules,

  • actually both should depend on abstractions.

  • And second, the principal offers that abstractions

  • should not depend on details,

  • actually details should depend on abstractions.

  • Both of these statements require some explanation.

  • Let's take a look at an example.

  • Consider this remote control class.

  • It has a click method that's called one user indicates

  • they want to control a television.

  • The remote control depends

  • on a lower level class call television,

  • and that class offers two methods,

  • turn TV on and turn TV off.

  • So when the user clicks,

  • the remote control click method has the logic to toggle

  • between the on and off states by calling the turn TV on

  • and turn TV off methods respectively.

  • So this design looks straightforward enough,

  • but there is room for improvement.

  • For starters, this remote control controls only televisions

  • and more specifically the television represented

  • by the concrete television class.

  • What if we want to control another kind of television

  • or even another kind of device with an on-off switch?

  • It's not hard to notice that we have a high level component,

  • our remote control depending directly

  • on a low-level component,

  • the concrete television class.

  • So according to our principal, that can't be good.

  • But how else would we approach this?

  • Let's think through what the high level policy

  • for this design should be.

  • What's the high level policy?

  • Well as Robert Martin,

  • the originator of this principle says,

  • "It's the abstraction that underlies the application."

  • So, how's this for an improved high-level policy

  • or abstraction, or remote control

  • that can control anything with an on off button,

  • a TV, a light, a sprinkler system, and so on.

  • Let's express that in our class diagram.

  • To do that,

  • we're going to create an abstraction for an on-off device.

  • More specifically, we're going to create an interface

  • on off device that supports two methods,

  • turn on and turn off.

  • Next, we'll have our remote control

  • depend on that abstraction by composing our remote control

  • with an on-off device.

  • And remember before the remote control dependent

  • on a concrete type, that television class.

  • So, now a remote control no longer depends

  • on a low level class.

  • Instead, it actually depends on an abstraction

  • that's that on off device interface.

  • This goes the other way too

  • remember that our principal also tells us

  • that abstractions should not depend on details,

  • rather details should depend on abstractions.

  • Well, let's examine the television class now

  • and notice first that it implements

  • the on-off device interface,

  • no longer does it expose its proprietary turn TV on

  • and turn TV off methods.

  • So rather than our abstraction, the on-off device,

  • depending on the low level details of the television,

  • that is it's turned TV on and turn TV off methods,

  • it is the television that is depending

  • on the high level of abstraction,

  • that is the turn on and turn off methods

  • in the on off device interface.

  • So this is often the reverse of how we think of design,

  • but by adhering to the dependency and version principle,

  • we really free our high-level components

  • from being dependent on the details of low-level components.

  • This really helps us avoid rigidity,

  • fragility and immobility.

  • The dependency in version principle

  • tells us that all relationships between components

  • shouldn't involve abstract classes and interfaces,

  • not concrete classes, in doing so helps us design software

  • that's reusable and resilient to change,

  • because these abstractions allow the details

  • between the components to remain isolated from each other.

(upbeat music)

Subtitles and vocabulary

Click the word to look it up Click the word to find further inforamtion about it