← Назад к вопросам

Как понимаешь принципы SOLID?

1.8 Middle🔥 171 комментариев
#Архитектура и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Как понимаешь принципы SOLID

SOLID — это аббревиатура пяти принципов объектно-ориентированного программирования, которые помогают писать поддерживаемый, гибкий и тестируемый код. Рассмотрю каждый принцип подробно.

S — Single Responsibility Principle (SRP)

Каждый класс должен иметь только одну причину для изменения.

# ❌ Нарушение SRP
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
    
    def save_to_db(self):
        # Сохранение в БД
        pass
    
    def send_email(self):
        # Отправка письма
        pass
    
    def generate_report(self):
        # Генерация отчёта
        pass

Проблемы: класс отвечает за сущность, БД, email и отчёты. Много причин для изменения.

# ✅ Соблюдение SRP
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email

class UserRepository:
    def save(self, user: User):
        # Сохранение в БД
        pass

class EmailService:
    def send(self, to: str, message: str):
        # Отправка письма
        pass

class ReportGenerator:
    def generate(self, user: User) -> str:
        # Генерация отчёта
        pass

O — Open/Closed Principle (OCP)

Классы должны быть открыты для расширения, но закрыты для модификации.

# ❌ Нарушение OCP
class PaymentProcessor:
    def process(self, payment_type: str, amount: float):
        if payment_type == "credit_card":
            self.process_credit_card(amount)
        elif payment_type == "paypal":
            self.process_paypal(amount)
        elif payment_type == "bitcoin":  # Нужно менять класс!
            self.process_bitcoin(amount)
# ✅ Соблюдение OCP
from abc import ABC, abstractmethod

class PaymentMethod(ABC):
    @abstractmethod
    def process(self, amount: float) -> bool:
        pass

class CreditCardPayment(PaymentMethod):
    def process(self, amount: float) -> bool:
        # Обработка кредитной карты
        return True

class PayPalPayment(PaymentMethod):
    def process(self, amount: float) -> bool:
        # Обработка PayPal
        return True

class BitcoinPayment(PaymentMethod):  # Новый способ без изменения существующего кода
    def process(self, amount: float) -> bool:
        # Обработка Bitcoin
        return True

class PaymentProcessor:
    def process(self, payment_method: PaymentMethod, amount: float):
        return payment_method.process(amount)

L — Liskov Substitution Principle (LSP)

Объекты подклассов должны корректно заменять объекты базового класса.

# ❌ Нарушение LSP
class Bird:
    def fly(self) -> str:
        return "Flying"

class Penguin(Bird):
    def fly(self) -> str:
        raise Exception("Penguin cannot fly!")  # Нарушение контракта
# ✅ Соблюдение LSP
class Bird:
    pass

class FlyingBird(Bird):
    def fly(self) -> str:
        return "Flying"

class Penguin(Bird):
    def swim(self) -> str:
        return "Swimming"

# Теперь можно безопасно использовать подклассы вместо базового класса
def let_bird_fly(bird: FlyingBird):
    return bird.fly()

I — Interface Segregation Principle (ISP)

Не заставляй клиентов зависеть от интерфейсов, которые они не используют.

# ❌ Нарушение ISP
class Worker(ABC):
    @abstractmethod
    def work(self):
        pass
    
    @abstractmethod
    def eat(self):
        pass

class Robot(Worker):
    def work(self):
        return "Working"
    
    def eat(self):
        raise Exception("Robot cannot eat")  # Бесполезный метод
# ✅ Соблюдение ISP
class Workable(ABC):
    @abstractmethod
    def work(self):
        pass

class Eatable(ABC):
    @abstractmethod
    def eat(self):
        pass

class Human(Workable, Eatable):
    def work(self):
        return "Working"
    
    def eat(self):
        return "Eating"

class Robot(Workable):
    def work(self):
        return "Working"

D — Dependency Inversion Principle (DIP)

Зависимости должны быть от абстракций, а не от конкретных реализаций.

# ❌ Нарушение DIP
class UserService:
    def __init__(self):
        self.db = PostgreSQL()  # Конкретная зависимость

# ✅ Соблюдение DIP
class UserRepository(ABC):
    @abstractmethod
    def get_user(self, user_id: int):
        pass

class UserService:
    def __init__(self, repository: UserRepository):
        self.repository = repository  # Зависимость от абстракции

Почему SOLID важен

  1. Тестируемость — легче написать unit тесты
  2. Гибкость — просто менять реализации
  3. Масштабируемость — проще добавлять функционал
  4. Читаемость — код понятнее
  5. Поддерживаемость — проще исправлять баги

Золотое правило

Не применяй SOLID везде. Это принципы, а не законы. Для маленького скрипта они могут быть лишней сложностью. Используй их в большых проектах, где нужна гибкость и тестируемость.