スコープをモデルの外でチェインするのはやめておけ(翻訳)|TechRacho(テックラッチョ)〜エンジニアの「?」を「!」に〜|BPS株式会社エンジニアの「?」を「!」に。原著者の許諾を得て翻訳・公開いたします。スコープをモデルの外でチェインするのはやめておけ(翻訳)Railsアプリで、次のようにモデルのデータベーススキーマの内部にまで立ち入っている(コントローラ)コードをまれによく見かけます。endendこのコードにはいくつか問題点があります。コントローラがモデルのデータベース構造に関する知識を持ちすぎています。背後の詳細な情報が上位の層に漏れると、背後の構造が変更しにくくなります。メソッド呼び出しがチェインしているので、モックを使ったテストが死ぬほどやりづらくなります。このような実装の詳細はモデル内にカプセル化されなければなりません。ActiveRecordのスコープの助けを借りて何とかしてみましょう。endend生SQLやモデル属性の知識はモデル内にカプセル化されました。これで一件落着...したのでしょうか?テストの書きやすさはほんの少しだけましになりましたが、異なるスコープを組み合わせる長いメソッドチェインはまだ残っています。コントローラをテストするには、またしてもモック軍団を出動させなければなりません。endendテストコードはexpectationだらけで、しかもかなり脆くなっています。テスト対象コードが正常だったとしても、スコープの順序がちょっと変わっただけでテストは失敗してしまいます。スコープが複雑になると他にも問題が生じることがあります。スコープはいくらでも自由に組み合わせられますが、その組み合わせから正しいSQLが生成されるとは限りません。その組み合わせを全部テストしていたら心が削られてしまいます。私は、スコープをモデルの外でがんがんチェインするのではなく、スコープの組み合わせをモデル内で単一のスコープやクラスメソッドにまとめるのが好みです。この方が処理を可能な限り内部化できますし、データベースクエリの最適化などの作業もずっとやりやすくなります。endendスコープはPerson.left_handed_male_adultsクラスメソッドの内部にラップされています。必要ならこのクラスメソッド自身をスコープとして定義することも可能な点にご注目ください。2つの方法の大きな違いは、スコープがActiveRecordリレーションを返すことを保証するかどうかです。スコープの組み合わせはぐっとシンプルになり、しかもテストに対して頑丈になります。endend関連するモデルの外でスコープをチェインするのを避ければ、コードベースにおける結合を弱められ、それによってメンテナンスやリファクタリングもやりやすくなります。あらゆるスコープはpublicなので、このスコープもその気になればチェインできます。スコープをモデルの外でチェインしたくなる衝動をぐっとこらえられれば、話は簡単になるのです。コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。チュートリアル第2版の監修および半分程度を翻訳、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れて更新翻訳中。enno.jpを運営。実は最近Go言語が好きで、Goで書かれたRubyライクなGoby言語のメンテナーでもある。仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。Storageを使ってはいけない(翻訳)#Tags#会社紹介#自社サービス#勉強会#Rails#PHP#デザイン#実績#週刊RailsウオッチCONTACTお気軽にご相談ください。(翻訳)CONTACTTechRachoでは、パートナーシップをご検討いただける方からのご連絡をお待ちしております。お気軽にご意見・ご相談ください。