Принцип инверсии зависимостей (буква D в SOLID) состоит из двух частей: модули верхнего уровня (бизнес-правила) не должны зависеть от модулей нижнего уровня (SMTP, базы данных, файлы, часы); оба должны зависеть от абстракций. А абстракции не должны зависеть от деталей: детали зависят от абстракций.

Слева сервис зависит от `EmailSender`, справа сервис и уведомители зависят от протокола `Notifier`
Слева сервис зависит от EmailSender, справа сервис и уведомители зависят от протокола Notifier

Нарушение: жёстко прописанная деталь

OrderService создаёт EmailSender() в конструкторе. Бизнес-правило теперь знает канал доставки. Чтобы отправить SMS, нужно менять сервис, а тест можно запустить, лишь отправив настоящее письмо.

python
class EmailSender:
    def send(self, to, text):
        print(f"EMAIL to {to}: {text}")

class OrderService:
    def __init__(self):
        self.sender = EmailSender()      # hard-wired detail

    def place(self, user, item):
        self.sender.send(user, f"order {item} accepted")

OrderService().place("ann@x.io", "book")
text
EMAIL to ann@x.io: order book accepted

Исправление: абстракция принадлежит клиенту