0

I have never quite understood the second part of the phrase...

'High-level modules should not depend on low-level modules. Both should depend on abstractions (e.g., interfaces)'

If I changed...

class Upper {
  foo = () => {
    console.log('bar')
  }
}

to...

class Upper {
  foo = () => {
    let lower = new Lower()
    lower.bar()
  }
}

class Lower {
  bar = () => {
    console.log('bar')
  }
}

We would say that I have successfully inverted dependencies because now the console code cannot break the high level module (it's in a wrapper).

The abstraction in this case is the interface 'Lower', but the console code does not DEPEND on 'Lower' does it? It depends on nothing. It's just 'code'.

I guess my real question is what exactly denoted a 'dependency' in this case?

chrisis
  • 1,983
  • 5
  • 20
  • 17
Exitos
  • 29,230
  • 38
  • 123
  • 178
  • `Lower` is a concrete class; otherwise it couldn't be instantiated. `Upper` depending on a concrete class `Lower` is a traditional, procedural dependency. Nothing is inverted here. – jaco0646 Feb 19 '21 at 14:22
  • @jaco0646 thanks for your comment but I think this is a commonly held misconception because JS is a dynamic language the interface Lower that has been introduced 'is' the abstraction. The Upper has been inverted in as much as it does not depend on the console. And the console does not depend on the Upper either it depends on the Lower and so is therefor also inverted. If you don't agree, could you perhaps provide a sample of this inverted with what is? I'm assuming you would use a service locator or something? – Exitos Feb 20 '21 at 07:32
  • @jaco0646 I believe the answer here reenforces my idea a little? https://softwareengineering.stackexchange.com/questions/195176/how-does-dependency-inversion-principle-work-in-languages-without-interfaces – Exitos Feb 20 '21 at 07:36
  • I think I see your point. The invocation of `new Lower()` will not resolve to `class Lower` until runtime, and at that time `class Lower` could be some other implementation that does not use the `console`. – jaco0646 Feb 20 '21 at 15:12

1 Answers1

0

let no one left without answer :)

yeap, if you narrow the context to this phrase, then the realization of the console.log('bar') doesn't dependence from public interface bar() of the class Lower.

but in the Dependency Inversion, there is the another sentence: "High-level modules should not depend on low-level modules. Both should depend on abstractions." it means that you should put an abstract interface class between your Upper and Lower.

then: "Abstractions should not depend on details" your interface class doesn't implement different bar() for the different Lowers (with different implementations BarWithDetailsSaveBarToDisk(), BarWithDetailsPrintBarToScreen() etc.) that you could change in your Upper consumer. But the LowerInterface has only Bar().

and finally: "Details should depend on abstractions" you custom classes LowerPrintLogConsole, LowerSaveBarDisk, LowerPrintBarScreen depends on the one Bar() should depend on the abstract LowerInterface realization.

also, you may want to add some specified details through your bar(): for console color, for print size, for save file name. you can do this through abstract wrapper barDetails: bar(barDetails InBarDetails), because "Details should depend on abstractions" again. and before consuming bar() from the Upper, you could construct an appropriate subclass of your another interface wrapper (barDetails).

6r0m
  • 41
  • 5