Этот класс нарушает Принципы единой ответственности? - PullRequest
2 голосов
/ 20 апреля 2019

Я написал класс UserService (на уровне логики, а не на уровне персистентности) о пользователе. и он содержит эти методы

  • Создать
  • патч
  • удалить
  • get_one
  • get_list

Этот класс с этими методами нарушает SRP?

class UserService:

    repository: Repository

    def create(...):
        self.repository.save(...)

    def patch(...):
        self.repository.patch(...)

    def delete(...):
        self.repository.delete(...)

    def get_one(...):
        return self.repository.get(...)[0]

    def get_list(...):
        return self.repository.save(...)

Если у этого много обязанностей, как я могу распределить класс?

1 Ответ

1 голос
/ 14 мая 2019

Принцип единой ответственности сложен.

Давайте начнем с определения того, что является ответственностью в контексте программной системы и сферы этой ответственности.

Обязанности бывают разнымиразные формы.Все, что вы думаете, может быть ответственностью, и все в вашем коде может иметь ответственность.

  • У ваших модулей есть обязанности.Если у вас есть Модуль выставления счетов , этот модуль отвечает за обработку счетов.

  • Теперь, если вы копаете глубже, вы Модуль биллинга может содержать несколько слоев.Каждый слой несет определенную ответственность. Презентация , Бизнес-логика и т. Д.

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

  • Теперь перейдем к функциям и коду внутри.Там вы можете иметь несколько утверждений, если, для, = и т. Д. Каждое утверждение делает что-то, что является ответственностью.Если вы проанализируете свои утверждения, вы заметите, сколько обязанностей выполняет функция / метод.

Если у вас есть UserRepository, и единственное, что он делает, - это общение с БД или посредник между вами.приложение и ORM, то у него есть ответственность .Это не значит, что у вас Repository будет один метод.Чтобы придерживаться SRM, в вашем UserRepository должны быть только методы, связанные с обменом данными с БД, связанные с users.В нем не должно быть какой-либо бизнес-логики.

Если у вас есть UserService, и у него есть только операции, связанные с пользователями, то эта служба соответствует SRP, поскольку ее ответственность состоит в том, чтобы иметь операции, связанные с Users.

Теперь вот чрезвычайно сложная часть SRP.

Чтобы ваш UserService мог выполнить свою работу, ему нужно позвонитьUserRepository.Если эта служба создает пользователей, а затем добавляет их в базу данных, не означает ли это, что UserService несет ответственность за сохранение новых пользователей ?

Мы видим, что у нас есть два отличительныхобязанности здесь.

  • ответственность , зная, как сделать вещь .UserRepository знает, как взаимодействовать с ORM или БД и сохранять новых пользователей.

  • Ответственность , говорящего о том, когда что-то должно быть сделано .UserService знает, когда User должен быть сохранен не как или где его следует сохранить .

У вас есть два разныхобязанности.Если ваше постоянство изменится, потому что вы измените как и / или где , вы измените только реализацию Репозитория, но Сервис не будет затронут.Если ваша бизнес-логика меняется, вы меняете , когда , поэтому служба будет меняться, но не репозиторий.

Еще одна вещь, связанная с этим, - это когда интерфейс объекта становится большим.

Люди начинают задаваться вопросом, придерживается ли этот большой интерфейс единственной ответственности - нет?

Если все методы являются связными, это так.Это означает, что размер чего-либо не означает, что это нарушает SRP.Это может нарушать другие принципы, такие как Принцип разделения интерфейса , но это не означает, что оно нарушает SRP.Это просто сложно использовать, читать, изменять и т. Д. В этом случае вы можете разбить его на несколько более мелких вещей.

Вот пример.Допустим, вы храните настройки для своего приложения.Вы можете разработать единый интерфейс ISettingsProvider, который имеет свойства для всех настроек и приведет к интерфейсу с 50 методами.Если мы определим ответственность как сохранение настроек , этот интерфейс не нарушает SRP.Если мы определим ответственность как сохранение настроек для определенной части приложения , то этот интерфейс нарушит ее.

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

Дело в том, что это древовидная структура.Верхняя сфера его применения шире и состоит из более мелкозернистых областей и так далее.В зависимости от того, где вы смотрите, ваши компоненты / объекты / модули могут придерживаться SRP.

Если у вас есть Модуль биллинга в одном огромном классе, с точки зрения системы, модуль идеально подходит для SRP.С точки зрения ответственности внутри модуля, класс, который реализует модуль, будет иметь бизнес-логику, код связи с БД, построение запросов и т. Д., И этот класс будет нарушать SRP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...