Вы находитесь на странице: 1из 13

Service Object в Ruby

Алексей Гром
Что такое Service Object и для чего он нужен?

Service Object используется в RoR для того что бы выполнять одно-


единственное действие в логике и сохранить наши контроллеры
простыми и удобными для чтения

Service Object может помочь решать некоторые проблемы:


1. Контроллеры и модели разрастаются. Количество строк кода в одном
файле может вырасти до нескольких тысяч
2. Непонятно, где искать код, в модели или в контроллере
3. Невозможно или затруднительно протестировать отдельные участки кода
контроллера, через консоль или через автоматические тесты.
Service должен быть объектом

Это правило позволит нам:


1. Передать в конструктор входные параметры
2. Сохранить их в свойства объекта, чтобы в дальнейшем не передавать их из
метода в метод
Пример его реализации

class GoodService
def initialize(param1, param2, param3)
@param1 = param1
@param2 = param2
@param3 = param3
end

def call
value = inner_method1
inner_method2(value)
end

private

def inner_method1
deep_method1
end

def inner_method2(value)
deep_method2(value)
end
end
Service Object должен быть простым

Это правило позволит нам:


1. Cохранить конструкторы простыми и понятными, когда мы их реализуем
2. Сделать конструктор ответственным только за сохранение аргументов в
переменных экземпляра службы
Пример реализации Service Object

class DeleteUser
def initialize(user_id:)
@user_id = user_id
end

def call
# …
end

private

attr_reader :user_id
def user
@user ||= User.find(user_id)
end
end
Делайте аргументы метода Call проще

Если в Service Object находится более одного аргумента, то


1. Можно сделать key word, чтобы сделать аргументы более
всеобъемлющими.
2. Если Service Object принимает только один аргумент, использование
аргумента key word делает код более читабельным.
Пример его реализации

ServiceObject.new(user, dependency, input).call

ServiceObject.new(user,dependency).call(input)
Надо быть уверенным что call будет понятен всем

1. Метод call — это сердце нашего Service Object, поэтому лучше


всего просто описывать все шаги и сводить дополнительную
логику к минимуму.
Пример его реализации

class DeleteUser
# …

def call
delete_user_comments
delete_user && send_user_deletion_notification
end

# …
end
Какие должны быть возвращаемые значения
Service Object?
1. Код результата
2. False в случае не корректной работы service или валидных
данных в случае успеха
3. Объект результата, включающий в себя всё вышеперечисленное.
Чего не надо делать с Service Object

1. Не создавать универсальные Service Object


Service Object это единичные business actions и надо обязательно
разбивать функциональность

2. Не выносите код Callback ActiveRecord в Service object если


• Это удаление лишних пробелов в начале и в конце строк.
• Это заполнение вспомогательных полей в таблице, которые нужны для
оптимизации запросов.
Ruby Trainee

Aliaksei Hrom
Skype: aliaksei.hrom
E-mail: a.hrom@andersenlab.com

Оценить