MIS.W 公式ブログ

早稲田大学公認、情報系創作サークル「早稲田大学経営情報学会」(MIS.W)の公式ブログです!

Ruby on Railsを書く上で意識したい事【カウントダウンカレンダー2017冬 11日目】

こんにちは!51代のしくがわです。最近は機械学習とか仮想通貨の話ばかりしていますがこの度Web班長になりました。よろしくお願いします! さて、最近弊サークルでもWeb開発に興味を持っている人が増え始め、Ruby on Railsを書ける人も増えてきているように思うのですが、今回は自分が今までRailsを書いてきて気づいた、「こういうところを意識したほうがいいよ!」みたいなのを紹介して行きたいと思います。 筆者自身、Ruby on Railsを書き始めて1年程度の初心者なので至らない点はあるかと思いますが駄文にお付き合い頂ければ嬉しいです。

まずはじめに

さて、Railsを今まで書いたことがあったり、その他のWebフレームワークを使ったことのある人ならMVCという用語は聞いたことがあるかと思います。RailsMVCの思想に基いて設計されているフレームワークです。故に良いRailsコードを書く上でMVCの役割を意識するのは最も大切な事と言っても過言ではありません。

モデルの役割を意識しよう

モデルの役割はデータベースとのやり取りです。故に、データベースにアクセスするような処理、所謂ビジネスロジックは全てモデルに書くべきです。良くないコードにありがちなのが、コントローラー部分で呼び出したデータを整形していたり、複雑なロジックが含まれているというものです。何故コントローラーにロジックを書くべきでないのか?これは私はコントローラーに過剰なロジックが書かれている場合、コントローラーのテストが肥大化してしまうからだと考えています。テストを書くことの重要性に関しては後述しますが、コントローラー部分で過剰にロジックが書かれていると、「コントローラー部分で本当にテストしなければならない部分」のテストが疎かになってしまいます。結果、保守性の低いコードになってしまいます。こうなると、後に保守に回ったエンジニア達が苦しい思いをするのでやめましょう。

では、どのようにしてモデルにロジックを定義するのがいいんでしょうか?普通にクラスメソッドをモデルクラス内で定義しても構いません、しかしRailsにはscopeという機能が備わっています。 scopeはクラスメソッドとは異なり、「メソッドチェーンが可能である」ことが保証されています。つまり、nilが帰ってくる事がない故にバグの発生を未然に防ぐことが出来ます。個人的にもscopeの書き方は簡潔でカッコよくて好きです。

コントローラーを細くしよう

前述しましたが、良くないコードにありがちなものとして、コントローラーに無駄な処理が沢山書いてあるというのがあります。MVCフレームワークを使ってまもない人達はコントローラーを「色々なロジックを書くところ」だと考えている人が多いのではないでしょうか?こう考えている人が多い故にコントローラーが肥大化してしまうのです。もう一度コントローラーの役割を再定義してみましょう。MVCにおけるコントローラーとは、「ビューとモデル間の接続を仲介する」ものです。言ってみれば、ビューからモデルを直接参照するといった事態を避ける為に存在しているものです。モデル、ビュー間の疎結合を実現するために必要なものなのです。故にコントローラーが肥大化するべきではないのです。 「それなら別にコントローラーなくても良くない?」 読者にはこう考える人がいるかもしれません。極論、コントローラーなんてなくてもWebサービスを作成することが可能です。しかし、複数人のエンジニアが携わる大規模なWebサービスを開発する場合どうでしょうか?大規模なWebサービスは基本的に、大まかにフロントエンドエンジニアやサーバーサイドエンジニア分かれて開発する事が多いです。簡単に言えば、フロントエンドエンジニアはMVCにおけるビューの開発を担当する、サーバーサイドエンジニアはMVCにおけるモデルの開発を担当するエンジニアです。もしコントローラーがない場合、フロントエンドエンジニアの担当範囲であるビューにモデルの操作に関するロジックが直接書かれてしまうことになります。こうなってしまうと、担当範囲を分けた意味がなくなってしまいます。

ビューの肥大化を防ごう

リッチなWebサービスの場合、ビューは肥大化してしまいます。これは仕方がないですよね。しかし、出来る限り肥大化を防ぎ、ビューの保守性を高める方法はRailsには備わっています。それがヘルパーとデコレーターです。一般的に、ビューにロジックを書くことは推奨されません。故に、ビューに書かれるロジック部分はヘルパーとデコレーターに切り分けられるべきです。ヘルパーはRailsのプロジェクトフォルダの作成時に自動で作成されるので名前を聞いたことがある人は多いかと思います。しかしデコレーターは聞いたことがない人も多いのではないのでしょうか?デコレーターは追加でgemをインストールすることで使えるようになります。Draperといったgemが有名ですね。デコレーターはヘルパーに書くとヘルパーが肥大化してしまう原因になってしまう、「モデルから取ってきたデータを整形して表示したい」みたいなものを書く際に使われます。通常、ヘルパーにこういったロジックを書く場合、帰ってくるモデルのデータ毎に似たようなメソッドを定義する必要があります。そういった事を防ぐ為にデコレーターが存在しているのです。ビューのロジックをヘルパー/デコレーターに切り分けることでテストが楽になります。理由は上述のコントローラーテストの話と同様です。 一般に(一般ではないかもしれないですが)、Rubyという言語においては似たような役割を果たすメソッドを複数生やす事が嫌われます。(というか私は嫌いです) 故にデコレーターはRubyそのものの思想に合致した機能であると言えます。余談ですが、一般的にRubyで同じような役割のメソッドを生やす事を防ぐ手段として、動的ディスパッチやゴーストメソッドなんてものがあります。詳しく知りたい人はググって下さい。私的にはrefinementsに次いでRubyの好きな機能です。

テストを書こう

テストを書きましょう。自分だけで使うようなサービスではわざわざテストを書かなくてもいいと思うのですが、複数人が開発に関わるようなサービスではテストを書かないのは罪です。それも、私は実際にRailsコードを書く前にテストすべき機能を洗い出してテストを書くことをおすすめします。所謂テスト駆動開発(TDD)という奴です。テストを書かないで書かれているコードを見て後からテストを書くのは結構地獄です。私自身、テストを書くことの重要性を実感したのは最近なのであまり大口は叩けません.... RubyにはRSpecといったテストフレームワークやFactory Girlといったテストをサポートするgemが充実しています。みなさん、テストをちゃんと書いて下さい。ちなみに、私が以前作ったRailsアプリケーションにはテストが書かれてないです。本当にごめんなさい...

最後に

短くはありますが、今回は1年間Railsを書いてきて私が学んだ事を簡潔に書かせて頂きました。これらを意識すればあなたのRailsレベルは一段階アップするかもしれません。ここまでお読み頂きありがとうございました。明日は幹事長のむさしんさんによる「ReactNative入門」です。お楽しみに!