Rails, сервисные объекты: передать весь объект или просто ID

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

Для этого я использую сервисные объекты, которые выполняют действия над данным объектом. Однако одна из дилемм, с которыми я сталкиваюсь, заключается в том, передам ли я весь объект службе или просто ID.

Классическим примером является обновление адреса электронной почты пользователя. Причина, по которой я бы использовал сервисный объект вместо простого метода в модели, заключается в том, что это электронное письмо также должно синхронизироваться с внешними сторонними системами, которые не принадлежат пользовательской модели.

class User::UpdateEmail
  # Passing entire user object
  def self.update_for_user(user, new_email)
    if user.update_attributes(email: new_email)
      # do some API calls to update email in external services
      true
    else
      false
    end
  end

  # Just passing user ID
  def self.update_for_user_id(user_id, new_email)
    user = User.find(user_id)
    if user.update_attributes(email: new_email)
      # do some API calls to update email in external services
      true
    else
      false
    end
  end
end

Есть ли какая-то польза от одного против другого? Кажется, что они оба "делают" одно и то же, и это выглядит как личное предпочтение для меня, но мне любопытно, если бы я столкнулся с ситуацией, когда я передаю весь пользовательский объект, и каким-то образом он устаревает, пока объект службы работает в теме.

Если я передам всего пользователя, то класс, который вызывает объект службы, должен будет выполнить проверку, чтобы убедиться, что пользователь существует и т. Д., Тогда как если я просто передам user_id, то объект службы теперь должен обеспечить действительный объект, и т.п.

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

0 ответов

Ну... это зависит:

Если вы используете фоновые задания, вы должны передавать только идентификаторы! Если вы этого не делаете... возможно, возражаете и всегда спрашиваете себя, кто / что за это отвечает.

Если объект, которому вы передаете вещь, является ответственным и должен знать об этом, то, возможно, этот объект должен позаботиться о его поиске, и будет достаточно просто идентификатора. Поиск будет происходить в этом ответственном объекте.

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

Вы должны суметь судить об этом деле в каждом конкретном случае, нет 1-general-rule-or-solutionза исключением того, что каждый объект должен нести единственную ответственность. И даже это можно согнуть или сломать в рубине

В общем:

Постарайтесь, чтобы вещи были слабо связанными, ясными и простыми, с каждой отдельной ответственностью. Избегайте связывать воедино вещи, которые не должны знать друг о друге или быть связанными вместе.

Рекомендую прочитать:
Practical Object-Oriented Designin Ruby, автор: Sandy Metz.
В нем есть хорошие примеры и ясно объясняются эти концепции.

Другие вопросы по тегам