Что такое инверсия зависимостей

Ответ

Инверсия зависимостей (Dependency Inversion Principle, DIP) — один из принципов SOLID, который гласит, что высокоуровневые модули не должны зависеть от низкоуровневых. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей, а детали — от абстракций.

Пример без DIP:

class LightBulb {
  turnOn() { /* ... */ }
}

class Switch {
  constructor(bulb) {
    this.bulb = bulb;
  }
  operate() {
    this.bulb.turnOn();
  }
}

Пример с DIP:

class Switchable {
  turnOn() {}
}

class LightBulb extends Switchable {
  turnOn() { /* ... */ }
}

class Switch {
  constructor(device) {
    this.device = device;
  }
  operate() {
    this.device.turnOn();
  }
}

Теперь Switch зависит от абстракции (Switchable), а не от конкретной реализации (LightBulb). Это упрощает расширение кода.

Ответ 18+ 🔞

Ну, слушай, вот есть такая штука — принцип инверсии зависимостей, DIP, из этих ваших SOLID. А звучит он, блядь, как заклинание какое-то: «Высокоуровневые модули не должны зависеть от низкоуровневых. Оба должны зависеть от абстракций. Абстракции не должны зависеть от деталей, детали — от абстракций». Пиздец, да? Словно не код писать, а в философском диспуте участвовать.

А на деле-то всё просто, ёпта. Смотри, вот тебе пример, как делают все распиздяи, которые про этот принцип не слышали.

class LightBulb {
  turnOn() { /* ... */ }
}

class Switch {
  constructor(bulb) {
    this.bulb = bulb;
  }
  operate() {
    this.bulb.turnOn();
  }
}

В чём тут, блядь, проблема? А в том, что наш выключатель (Switch) — это типа высокоуровневая штука, логика управления, а лампочка (LightBulb) — низкоуровневая, конкретная железяка. И выключатель намертво привязан к этой самой лампочке. Захотел ты вместо лампочки вентилятор воткнуть — нихуя! Придётся переписывать сам выключатель, потому что он ждёт именно LightBulb. Ебать-колотить, какой же это пиздец, когда всё так завязано!

А теперь смотри, как надо делать по-человечески, с DIP. Мы создаём абстракцию — типа общий договор, что любая штука, которую можно включать, должна уметь turnOn.

class Switchable {
  turnOn() {}
}

class LightBulb extends Switchable {
  turnOn() { /* ... */ }
}

class Switch {
  constructor(device) {
    this.device = device;
  }
  operate() {
    this.device.turnOn();
  }
}

Видишь, в рот меня чих-пых? Теперь наш Switch вообще похуй, что к нему подключено — лампочка, вентилятор, блядь, чайник или сигнализация. Лишь бы эта хрень соблюдала контракт Switchable и умела turnOn. Выключатель зависит от абстракции, а не от конкретной лампы. И лампочка, и вентилятор — это уже детали, которые зависят от этой же абстракции.

Вот и вся магия, ёпта. Не нужно быть семи пядей во лбу, чтобы понять: когда всё завязано на абстракции, а не на конкретике, то и расширять, и тестировать, и менять всё становится в разы проще. А иначе — один сплошной головняк и костыли на костылях.