Edited at

Railsのサービスクラスを作る前に考えるべきこと

肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳) のサービスクラスは確かに便利ですが、とりあえずで使うと今度はサービスクラスが肥大化したりサービスクラスが乱立したりします

そこでサービスクラスを作る前に後々困らないように考えます


1. 実装を狭めるルールを決める

単一責務に誘導することで肥大化を防ぐ方法がよく語られています



  • .call 実行だけ許可して他を隠蔽する

  • 動詞から始めるクラス名に制限する


参考


2. 特定モデルの振る舞いまでサービスクラスにしない

MVC パターンの M は ActiveRecord だけではなくもう少し広いもので、該当モデルの振る舞いなら models フォルダに ActiveRecordクラス以外があっても問題ないという考えによるものです

class User < ActiveRecord::Base

def self.find_or_create_with_hoge(hoge)
# 略: 肥大化し private 関数などに分離しつつ他の処理から隔離したい
end
end

こんな時に FindOrCreateUserWithHogeService を作ると見通しが悪くなります

そこで挙動としてはサービスクラスと同じですが配下に配置するとスッキリします


models/user/find_or_create_with_hoge.rb

class User

class FindOrCreateWithHoge < SmartInit::Base
initialize_with_args :user, :hoge
is_callable

def call
# 略
end

private

def hogehogehoge
# 分割
end
end
end

# 実行するとき
User::FindOrCreateWithHoge.call(user, hoge)



感想

ベストプラクティスがなくベタープラクティスを手探りで探ってる感