Создание сервиса отправки email с применением Dependency Injection

Передавайте реализацию SendMessage в сервис через конструктор, а не создавайте SendMail внутри бизнес-метода. Тогда отправитель заменяется без изменения сценария, в том числе тестовым объектом.

Короткий ответ

Что ответить на собеседовании

Передавайте реализацию SendMessage в сервис через конструктор, а не создавайте SendMail внутри бизнес-метода. Тогда отправитель заменяется без изменения сценария, в том числе тестовым объектом.

Подробный разбор

Ответ с пояснениями

Условие

Необходимо реализовать механизм отправки электронных писем, строго следуя принципу внедрения зависимостей. Определите абстрактный базовый класс SendMessage и его конкретную реализацию SendMail.

from abc import ABC, abstractmethod

class SendMessage(ABC):
    @abstractmethod
    def send(self, res: str, text: str, subject: str) -> None:
        pass

class SendMail(SendMessage):
    def send(self, res: str, text: str, subject: str) -> None:
        print("Email:", res, text, subject)

Ответ

Передавайте реализацию SendMessage в сервис через конструктор, а не создавайте SendMail внутри бизнес-метода. Тогда отправитель заменяется без изменения сценария, в том числе тестовым объектом.

К существующим интерфейсу и адаптеру добавьте потребителя:

class NotificationService:
    def __init__(self, sender: SendMessage):
        self.sender = sender

    def notify(self, recipient: str, text: str, subject: str) -> None:
        self.sender.send(recipient, text, subject)

service = NotificationService(SendMail())

Связывание выполняется в точке сборки приложения. Для теста передайте fake, записывающий вызовы, без SMTP. Показанный SendMail только печатает данные и не отправляет настоящий email. Рабочий адаптер должен иметь явную обработку ошибок и не выводить содержимое писем/адреса в обычные логи.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее