Какие два принципа SOLID максимально похожи друг на друга?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие два принципа SOLID максимально похожи друг на друга?
Отличный вопрос! Большинство говорят, что это SRP и ISP. И они отчасти правы, но полная картина глубже. Разберу все пять принципов и найду максимальную схожесть.
Напомню SOLID
S — Single Responsibility Principle (SRP) O — Open/Closed Principle (OCP) L — Liskov Substitution Principle (LSP) I — Interface Segregation Principle (ISP) D — Dependency Inversion Principle (DIP)
Пары похожих принципов
Пара 1: SRP и ISP (классический ответ)
SRP: Класс должен иметь одну причину для изменения
# Плохо
class User:
def save(self):
"""Сохранение в БД"""
pass
def send_email(self):
"""Отправка письма"""
pass
def generate_report(self):
"""Генерация отчета"""
pass
# Три причины для изменения!
# 1. Изменения в БД
# 2. Изменения в почтовом сервисе
# 3. Изменения в формате отчета
# Хорошо
class User:
def save(self):
pass
class EmailSender:
def send_email(self, user):
pass
class ReportGenerator:
def generate(self, user):
pass
ISP: Интерфейсы должны быть узкими, не «толстыми»
# Плохо (толстый интерфейс)
class Worker:
def work(self):
pass
def eat(self):
pass
class Robot(Worker):
def work(self):
return "working"
def eat(self):
raise NotImplementedError("Robots don't eat") # Плохо!
# Хорошо (узкие интерфейсы)
class Workable:
def work(self):
pass
class Eatable:
def eat(self):
pass
class Human(Workable, Eatable):
pass
class Robot(Workable):
pass
Сходство: Обе говорят о разделении обязанностей. SRP фокусируется на классах, ISP — на интерфейсах.
Пара 2: OCP и LSP (глубже скрыта связь)
OCP: Код открыт для расширения, закрыт для модификации
# Плохо (нужно менять код при добавлении нового типа)
class PaymentProcessor:
def process(self, payment):
if payment.type == 'card':
return self.process_card(payment)
elif payment.type == 'paypal':
return self.process_paypal(payment)
# Добавляем новый метод при каждом новом способе платежа
# Хорошо (расширяем, не меняя)
class Payment:
def process(self):
pass
class CardPayment(Payment):
def process(self):
return "card processed"
class PayPalPayment(Payment):
def process(self):
return "paypal processed"
class PaymentProcessor:
def process(self, payment: Payment):
return payment.process() # Полиморфизм, ничего не меняем!
LSP: Подклассы должны корректно заменять базовый класс
# Нарушение LSP
class Bird:
def fly(self):
return "flying"
class Penguin(Bird):
def fly(self):
raise Exception("Penguins can't fly!") # Нарушение контракта!
# Код, ожидающий Bird
def make_it_fly(bird: Bird):
return bird.fly() # Упадёт на пингвине!
# Правильно
class Bird:
pass
class FlyingBird(Bird):
def fly(self):
return "flying"
class Penguin(Bird): # Не наследуемся от FlyingBird
def swim(self):
return "swimming"
Сходство: Обе говорят о полиморфизме и правильных иерархиях наследования.
Пара 3: SRP, ISP и DIP (триада разделения обязанностей)
DIP: Зависи от абстракций, не от конкретных реализаций
# Плохо (высокий уровень зависит от низкого)
class UserRepository:
def __init__(self):
self.db = PostgresDB() # Прямая зависимость!
def get_user(self, id):
return self.db.query(f"SELECT * FROM users WHERE id = {id}")
# Хорошо (через абстракцию)
from abc import ABC, abstractmethod
class Database(ABC):
@abstractmethod
def query(self, sql):
pass
class UserRepository:
def __init__(self, db: Database): # Инъекция зависимости
self.db = db
def get_user(self, id):
return self.db.query(f"SELECT * FROM users WHERE id = {id}")
class PostgresDB(Database):
def query(self, sql):
pass
class MongoDBConnection(Database):
def query(self, sql):
pass
ИТОГОВЫЙ ОТВЕТ: SRP и ISP — максимально похожи
Почему именно эти два?
SRP (Single Responsibility Principle):
- Один класс → одна обязанность
- Одна причина для изменения
- Применяется на уровне КЛАССА
ISP (Interface Segregation Principle):
- Один интерфейс → одна обязанность
- Узкие интерфейсы вместо толстых
- Применяется на уровне ИНТЕРФЕЙСА
Они практически идентичны по смыслу:
# SRP в действии
class EmailService:
def send_email(self):
pass
# ISP в действии
class IEmailService:
def send_email(self):
pass
# Обе говорят одно: РАЗДЕЛЯЙ ОБЯЗАННОСТИ!
Визуально
Solid принципы:
┌─────────────────────────────────────┐
│ SOLID принципы │
├─────────────────────────────────────┤
│ S ─── SRP (класс) │
│ ╲ │
│ ├─ ISP (интерфейс) ← ОЧЕНЬ │
│ ╱ ПОХОЖИ! │
│ I ─── │
│ │
│ O ─── OCP (полиморфизм) │
│ ╲ │
│ ├─ LSP (наследование) ← ПОХОЖИ │
│ ╱ │
│ L ─── │
│ │
│ D ─── DIP (абстракции) │
└─────────────────────────────────────┘
Как ответить на интервью
**"SRP и ISP максимально похожи. Обе говорят о разделении обязанностей:
- SRP — один класс должен делать одно (Пример: класс User не должен отправлять письма)
- ISP — интерфейсы должны быть узкими (Пример: Robot не должен реализовывать интерфейс Eatable)
Оба принципа решают одну проблему: когда класс или интерфейс отвечает за слишком много, его сложно менять и тестировать. Разделение обязанностей делает код более гибким.
Это как две стороны одной медали: SRP говорит об этом для классов, ISP — для интерфейсов."**
Этот ответ покажет, что ты не просто заучил определения, а понимаешь связи между принципами.