В чем заключается принцип единственной ответственности (SRP) в ООП?

Ответ

Принцип единственной ответственности (Single Responsibility Principle, SRP) — это один из пяти принципов SOLID, который гласит, что каждый класс должен иметь только одну причину для изменения.

Это означает, что класс должен быть ответственен только за одну, четко определенную часть функциональности. Следование этому принципу делает код более модульным, понятным, легко тестируемым и менее хрупким при внесении изменений.

Нарушение принципа

Класс User отвечает и за хранение данных, и за их сохранение в базу данных. Причины для изменения: изменилась структура пользователя или способ сохранения.

# Плохая практика: класс имеет несколько ответственностей
class User:
    def __init__(self, name: str, email: str):
        self.name = name
        self.email = email

    def save_to_db(self):
        # Логика сохранения пользователя в базу данных
        print(f"Saving {self.name} to DB")

Соблюдение принципа

Ответственность разделена: User хранит данные, а UserRepository управляет их сохранением.

# Хорошая практика: каждая сущность отвечает за свое
class User:
    def __init__(self, name: str, email: str):
        self.name = name
        self.email = email

class UserRepository:
    def save(self, user: User):
        # Логика сохранения пользователя в базу данных
        print(f"Saving {user.name} to DB")

Теперь, если изменится способ сохранения, правки нужно будет вносить только в UserRepository, не затрагивая класс User.

Ответ 18+ 🔞

Э, слушай, а вот этот ваш SRP, Single Responsibility Principle, он же как бы... Ну, внатуре, проще пареной репы, если не выёбываться.

Представь себе чувака, который и картошку чистит, и в окно плюёт, и ещё пытается телик смотреть одной жопой. Получается пиздец, а не работник. Так и класс — он должен делать что-то одно, ну, в идеале. Одна работа — одна причина, чтобы его потом, блядь, переделывать.

Вот смотри, как бывает, когда принцип нахуй игнорируют:

# Типичный мультитаскер, который всё проебёт
class User:
    def __init__(self, name: str, email: str):
        self.name = name
        self.email = email

    def save_to_db(self):
        # А вот тут он уже полез в базу, сука, как будто больше некому
        print(f"Saving {self.name} to DB")

Видишь? Этот User — он и данные таскает, и в базу их же пихает. Вообрази: завтра начальство скажет — «а давайте не в PostgreSQL, а в MongoDB, ёпта!». И пошёл ты перелопачивать кучу мест, где этот save_to_db вызывается. Или там структуру юзера поменяли — опять везде лезть. Одна сплошная головная боль, как после вчерашнего.

А теперь смотри, как надо бы, по-человечески:

# Юзер — он просто сущность, контейнер для данных, и всё
class User:
    def __init__(self, name: str, email: str):
        self.name = name
        self.email = email

# А это уже отдельный пацан, который знает, куда эти данные пристраивать
class UserRepository:
    def save(self, user: User):
        # Вот тут вся магия сохранения, и только тут
        print(f"Saving {user.name} to DB")

Вот теперь красота! User — просто хранит инфу, как мешок. Захотел поменять поля — правишь только его. UserRepository — знает, как этот мешок в базу запихнуть. Решили переехать с одной СУБД на другую? Да похуй! Меняешь только репозиторий, а юзер даже не чихнёт.

И главное — причин для изменений теперь по одной на каждого. Не будет этой ебаной кучи-малы, когда всё связано и разъебывается от одного чиха. Чисто, модульно, и тестировать легко. В общем, SRP — это не просто буквы, а, блядь, здравый смысл, обёрнутый в теорию.