肥大化したActiveRecordモデルをリファクタリングする7つの方法(翻訳) のサービスクラスは確かに便利ですが、とりあえずで使うと今度はサービスクラスが肥大化したりサービスクラスが乱立したりします
そこでサービスクラスを作る前に後々困らないように考えます
1. 実装を狭めるルールを決める
単一責務に誘導することで肥大化を防ぐ方法がよく語られています
-
.call
実行だけ許可して他を隠蔽する - 動詞から始めるクラス名に制限する
参考
- Rails のサービスクラスでのマイルールとちょっとしたコツ
- Railsにおけるサービスクラスのオリジナルルール
- gem smart_init (本記事で用いる)
- gem trailblazer(規模が大きいため本記事では言及しない)
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)
感想
ベストプラクティスがなくベタープラクティスを手探りで探ってる感