質問: ### 前提・実現したいこと 【前提】 勤怠管理のシステムを改修しております。私はruby,railsはそこまで詳しくありません。 スピード重視で開発してきたようで、勤務時間計算を担当しているモデルが 700行を超えるFATモデルになっております。 今後の機能改修のために、今のうちにリファクタリングしたいと考えています。 (リファクタリングは一気に完了させずに、段階に分けてしようと思っています) このモデルがFATモデルになっている原因は、素人ながら見たところ下記だと思っています。 ・100行を占めるscope(全て特定条件下の勤怠計算を行うもの) ・出勤、半休など無数のステータス毎に計算するために、ビジネスロジックでswitch を使って分岐させていること 【実現したいこと】 勤務時間計算を行うモデルですので、責務はそれほどかけ離れていないと思っています。 そのため、まずはモデルの持つ機能をそのままに、scopeを分離したいと考えています。 ### 発生している問題 リファクタリングの方針をどのようにするか、悩んでおります。 下記についてアドバイスをいただけないでしょうか。 ・scopeを分離する方法 ・またはそれ以外のリファクタリング方法 ### 試したこと scopeの分離は下記をヒントにしています。 肥大化したActiveRecordモデルをリファクタリングする7つの方法 しかし、上記サイトのコードでは毎回.allを実行するため、数万件のデータを扱うには パフォーマンスが悪すぎると感じました。 次に、下記サイトをヒントにしました。 Rubyでメソッドチェイン可能なクエリオブジェクトを書く しかし、上記のサイトのコードでは下記の問題がありました。 ・リファクタリング前よりも、総コード量は増加する。(問題かはわかりませんが。。。) ### 補足情報(言語/FW/ツール等のバージョンなど) Rails 4.2.0
回答: >>・100行を占めるscope(全て特定条件下の勤怠計算を行うもの) おっしゃるように一般的な解決方はご指摘のサイトの通りクエリビルダーを作ることで、ファットモデルに対して有効かと思います。 下記の記事は参考になるかと思います。 https://qiita.com/furaji/items/12cef3ec4d092865af88 >>・出勤、半休など無数のステータス毎に計算するために、ビジネスロジックでswitch を使って分岐させていること 上記はstatusごとに共通の親クラスを持った子クラスを作り、時間計算ロジックやその他を実装していけば良いのではないでしょうか。 コマンドパターンに近いかと思います。 http://morizyun.github.io/ruby/design-pattern-command.html