Sobes.tech
Назад к вопросам
Junior — Middle
62

Какие основные принципы SOLID применял при улучшении архитектуры вашего кода?

Компании, где спрашивали
РунитиРунити

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Важно услышать, что SOLID применялся не формально, а для уменьшения связности и упрощения изменений. Хороший ответ показывает, что код становился легче тестировать, расширять и сопровождать. Обычно ожидают примеры, где один класс отвечал за слишком многое, а после рефакторинга обязанности были разделены.

Определение:

SOLID — это набор из пяти принципов проектирования, которые помогают делать код более гибким и устойчивым к изменениям. В Python их обычно применяют не ради “идеальной архитектуры”, а чтобы снизить риск, что правка в одном месте сломает другое. Основная идея — разделять ответственности, опираться на абстракции и проектировать код так, чтобы его можно было расширять без переписывания существующей логики.

Пример использования:

Например, был сервис, который одновременно считывал данные, валидировал их, сохранял в БД и отправлял уведомление. После рефакторинга ответственность разделили: один класс стал отвечать только за валидацию, другой — за сохранение, третий — за отправку уведомлений, а сервис начал только координировать их работу.

from abc import ABC, abstractmethod


class Notifier(ABC):
    @abstractmethod
    def send(self, message: str) -> None:
        pass


class EmailNotifier(Notifier):
    def send(self, message: str) -> None:
        print(f"Send email: {message}")


class OrderService:
    def __init__(self, notifier: Notifier):
        self.notifier = notifier

    def process(self, order_id: int) -> None:
        # одна ответственность: обработать заказ
        print(f"Order {order_id} processed")
        self.notifier.send(f"Order {order_id} is ready")

Пояснение кода:

Код показывает принцип инверсии зависимостей и частично принцип открытости/закрытости. OrderService не зависит от конкретной реализации уведомлений, а работает через абстракцию Notifier. Если позже нужно отправлять уведомления через SMS или Telegram, достаточно добавить новый класс, не меняя OrderService.

Если разложить по шагам:

  1. Описана абстракция Notifier с методом send.
  2. EmailNotifier реализует конкретный способ уведомления.
  3. OrderService принимает Notifier в конструкторе.
  4. При обработке заказа сервис вызывает send, не зная, как именно отправляется сообщение.
  5. Это упрощает замену реализации и тестирование через мок или заглушку.

Ключевые моменты:

  • S — Single Responsibility: у класса должна быть одна основная причина для изменения.
  • O — Open/Closed: код лучше расширять новыми классами, а не править существующую логику.
  • L — Liskov Substitution: наследники должны заменять базовый тип без сюрпризов в поведении.
  • I — Interface Segregation: лучше несколько маленьких интерфейсов, чем один “толстый” с лишними методами.
  • D — Dependency Inversion: верхнеуровневый код должен зависеть от абстракций, а не от конкретных реализаций.
  • При рефакторинге SOLID особенно полезен для снижения связности, упрощения тестов и локализации изменений.