Статьи
May 20, 2022

Принцип единой ответственности в Python

Из этого материала вы узнаете о принципе единой ответственности и о том, как реализовать его в Python.

Что такое SOLID

SOLID – это аббревиатура, состоящая из названий пяти основных принципов проектирования в объектно-ориентированном программировании: 

S — принцип единой ответственности (Single responsibility Principle)

O — принцип открытости / закрытости (Open-closed Principle)

L — принцип подстановки Барбары Лисков (Liskov Substitution Principle)

I — принцип разделения интерфейса (Interface Segregation Principle)

D — принцип инверсии зависимостей (Dependency Inversion Principle)

Поговорим о первом из них.

Введение в принцип единой ответственности

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

Цели применения принципа:

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

В качестве примера рассмотрим класс Person:

class Person:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f'Person(name={self.name})'

    @classmethod
    def save(cls, person):
        print(f'Save the {person} to the database')

if __name__ == '__main__':
    p = Person('John Doe')
    Person.save(p)

У него есть две задачи:

  • управление свойствами сущности «человек»;
  • хранение сущности «человек» в базе данных.

При такой композиции, если вы захотите сохранить информацию о сущности в другое место, например, в файл, вам нужно будет изменить метод save(), который, в свою очередь, изменит весь класс Person.

Чтобы класс соответствовал SRP, вам нужно создать второй, отвечающий за хранение информации о человеке в базе данных. Например:

class Person:
    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return f'Person(name={self.name})'


class PersonDB:
    def save(self, person):
        print(f'Save the {person} to the database')


if __name__ == '__main__':
    p = Person('John Doe')

    db = PersonDB()
    db.save(p)

Таким образом, мы разделяем класс Person на два (Person и PersonDB):

  • Person отвечает за управление свойствами сущности «человек».
  • PersonDB отвечает за хранение данных о сущности в БД.

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

При написании классов следует помещать в один класс методы, имеющие одну причину для изменения. Если у них разные причины для изменения, лучше реализовать их в отдельных классах.

У этой конструкции есть одна проблема – теперь вам придётся иметь дело с двумя классами. Однако вы можете использовать паттерн «Фасад», чтобы класс Person был фасадом для класса PersonDB:

class PersonDB:
    def save(self, person):
        print(f'Save the {person} to the database')


class Person:
    def __init__(self, name):
        self.name = name
        self.db = PersonDB()

    def __repr__(self):
        return f'Person(name={self.name})'

    def save(self):
        self.db.save(person=self)


if __name__ == '__main__':
    p = Person('John Doe')
    p.save()

Заключение

Принцип единой ответственности (SRP) гласит: каждый класс, метод и функция должны выполнять только одну задачу или иметь только одну причину для изменения.

Используйте принцип единой ответственности для разделения классов, методов и функций с одинаковой причиной для изменений.

👉🏻Подписывайтесь на PythonTalk в Telegram 👈🏻

👨🏻‍💻Чат PythonTalk в Telegram💬

🍩 Поддержать канал 🫶

Источник: Python Tutorial
Перевод и адаптация: Екатерина Прохорова