Rails アンチパターン - スケールへの壁(Scaling Roadblocks)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は5 Servicesの2つめ「Sluggish Services」についてまとめました。

waterlow2013.hatenablog.com

今回は8 Scaling and Deployingの1つめ「 Scaling Roadblocks」についてまとめます。

Scaling Roadblocks

Railsアプリケーションを運用するのに、本番サーバ1台でなんとかなるのにわざわざクラスタ化などのコストの高い対応を初めからする必要はない。 ただ、コストが低いもの、もしくは後で対応するとコストが高くなるものは初めに対応しておいてもよさそう。

Solution: Build to Scale from the Start

例えばimageの配信はローカルのファイルではなくS3においておくというのはそこまでコストはかからない。 gemも存在している。carieerwaveやpaperclip、shrineなど。

まとめ

最近はRailsアプリはコンテナ化しておくのが割と普通になっている感じがしていて、時代が変わったなと思いました。 asset-syncやcdnなども、やっておいてもよさそうだなと思いました。

Rails アンチパターン - 怠けものサービス(Sluggish Services)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は7 Testingの2つめ「Lost in Isolation」についてまとめました。

waterlow2013.hatenablog.com

今回は5 Servicesの2つめ「Sluggish Services」についてまとめます。

Sluggish Services

リモートサービス(外部APIなど)によっては、パフォーマンスやたまにエラーになる、メンテナンスになるなど、自分のアプリケーションに大きな影響を及ぼす。

Solution: Set Your Timeouts

失敗時にリトライするか、失敗しても問題ないようなサービスの場合はタイムアウトを設定することでパフォーマンスを改善することができる。
net/httpやfaradayなどの一般的なhttpクライアントはタイムアウトを設定してその時間だけ待ったら特定のエラーをあげてくれる。

Solution: Move the Task to the Background

リモートサービスのレスポンスがおそすぎる場合や、リトライを精密に行う必要がある場合には、ユーザにフィードバックを即時で返さなくていい場合に限り、処理を非同期にするという方法がある。
2017年現在だと非同期処理のgemはdelayed_job, resqueue, sidekiq, shoryukenなどがある。

まとめ

今回は特に言うことなく、外部サービスとのやりとりはタイムアウトを設けて非同期ジョブにするというのはよくある話です。
外部とのやり取り含め、バックグラウンドに持っていくことでパフォーマンス改善できるところは結構ありそう。 複雑化とのトレードオフではありますが。

Rails アンチパターン - モックにより失われた物(Lost in Isolation)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は4 Controllersの5つめ「Controller of Many Faces」についてまとめました。

waterlow2013.hatenablog.com

今回は7 Testingの2つめ「Lost in Isolation」についてまとめます。

Lost in Isolation

モックを使ってテストを書いていると、unit testとしてテストできるようになるがつなぎの部分はテストされない。 メソッド名が変わったり引数が変わったりという変更に対して追従することができない。

Solution: Watch Your Integration Points

integration testをやろう。Rails5.1のSystem Tests、feature spec やturnip等がある。 開発の順序としては以下のようになる。

  1. まずintegration testを書き、それをパスするだけの実装をする
  2. 次にfunctional testを書き、それをパスするだけの実装をする
  3. 最後にunit testを書き、それをパスするだけの実装をする

まとめ

自分は何が何でもintegration testは書くべきという派です。 feature specはテストが遅くなるため導入の是非はあるのですが、そもそもfeature specを導入できないくらいの規模になってしまっているRailsアプリケーションは大きすぎるのかなという感じです。個人的な意見です。

あと「テスト戦略」については難しいと思っていて、functional testは書かない人も多いみたいです。 なんかテスト戦略関連のことがのっている本を読みたいなと思いました。

【Ruby/Rails勉強法】表参道.rbに行けなかったので勝手にまとめる #omotesandorb

はじめに

2017年6月1日に表参道rbが開催されました。 https://omotesandorb.connpass.com/event/58274/ 参加したかったのですが無理だったので、自分が勉強に使っていたものと、もし勉強法についてアドバイスする機会があれば何を伝えるかということを勝手にまとめていきたいと思います。

勉強に使っていたもの

本や情報など巷にあるものはだいぶ成熟してきた感じがあります。
各自合ったものを選べばよいと思いますが、自分が使ったものは以下です。

Ruby技術者認定試験

当時はRuby1.8系だったのですが、技術者認定のSilverとGoldを取得しました。Goldのほうは自分にとっては難しく2回も落ちてしまいました。
Rubyのメソッドや仕様をみっちり覚えることになった感じです。いまは覚えてない。

Railsチュートリアル

動くものを作ることができたのが良かったです。 回数重ねるたびに色々発見があるのもいいですね。

書籍集

blog.inouetakuya.info

blog.jnito.com

この辺の中で自分に合いそうなものを試しながら読んでました。

るびまのコード添削記事

Rubyist Magazine - あなたの Ruby コードを添削します 【第 1 回】 pukipa.rb

かなり古い記事なのですが、Rubyらしい書き方や考え方など参考になりました。おすすめ。

もしアドバイスするなら

モチベーション、モチベーション、モチベーション…

言語を勉強するのには基本的には時間と労力がかかるので、モチベーションをたもちつつ継続的にやるということを優先しましょう。 そのための回り道、非効率な勉強法などは、他の人にとやかく言われても気にせずいきましょう。 自分の場合はRailsを始めると少なからずjQueryをやることになるわけですが、Railsをやっていない人から「そんなんいいからReactやれ」みたいなことを言われてへこんだ記憶があります笑

インプットとアウトプット

一般的には学習プロセスでは"アウトプット"を大事にした方がいいという話をよく聞きます。 自分は"アウトプット"あまり得意ではないです。周りを見ても、"アウトプット"得意な人と苦手な人がいるなーという印象です。 色々と考えてきて、"アウトプット"と言うのは「人に見せる形にしろ」ということではなく「手を動かさずにわかった気になるな」くらいに捉えるようになりました。 写経でもいいしコピペしてきたものをちょっといじってみるでも良いですが、バズった記事が流れてきたのをみてふーんと思っただけでは勉強したことにはならないよということです(ブーメラン)。

情報の取捨選択

最近はいろいろ情報がありすぎて、普通にググっても求める情報が出てこないことも多いです。
例えば「form_for form_tag 違い」とか調べるとああ、、、となります。 (activerecordのモデルに紐付かないformを作る場合でも、form_objectを作ってform_forという選択肢にたどりつかない。) 情報の出処をはっきりさせて、自分で選ぶリテラシーを身に着けましょう。 Ruby/Railsの場合もすごい人がたくさんいて、〇〇gemを作った人、〇〇ブログの人、〇〇コミュニティーの人、〇〇株式会社の人などいろいろです。 twitterなりqiitaなりでfollowしていくといいと思います。

スキルの取捨選択

Code Fellows | This is Why Learning Rails is Hard

Ruby on Railsを構成する技術要素は非常に多く、また追加もされています。特にフロントエンドやawsやコンテナ技術などもRailsサービスを公開する上で必要になるかもしれません。
全てを学んでいくのは難しいので、自分の強みや需要などを加味しながら学ぶべきスキルを決め、そこに向かって行く必要があります。モチベーションのところと若干矛盾していまうのですが、自分の興味と世間の需要あわせて考える必要がありますね。

自分は「こなれた感じのRails開発者」になりたいと思っています。どんなものかというと場合によってhelperやform_objectを使い分けながら薄いview、controllerと責務分割されたmodelを作れるエンジニアをイメージしています。 現場のRailsはおもったよりも汚いことが多いので需要はあるんじゃないかと思います。 長期的な技術スタックはもう少し考えないといけないですね。

まとめ

  • 勉強法や資料はいろいろ、出揃っている感じある
  • モチベーション大切
  • アウトプットはすきなように
  • 情報、スキルの取捨選択

(やはり後半が長くなってしまった。。。そして、アドバイスRubyRailsが含まれていない。。。)

Rails アンチパターン - 色んな顔を持つコントローラ(Controller of Many Faces)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は4 Controllersの4つめ「Monolithic Controllers」についてまとめました。

waterlow2013.hatenablog.com

今回は4 Controllersの5つめ「Controller of Many Faces」についてまとめます。

Controller of Many Faces

内容はMonolithic Controllersパート2という感じです。

コントローラの認証の部分は責務過多になりがちです。よくあるのはUsersControllerにloginlogoutというアクションを実装してしまうケースです。
認証はユーザのセッションを管理しているため、操作対象のリソースをuserモデルにする必要がないということに気づきます。

Solution: Refactor Non-RESTful Actions into a Separate Controller

解決策としては、SessionsControllerをつくり以下のようにアクションをもたせます。

class SessionsController < ApplicationController
  def new
    # ...
  end

  def create
    # ...
  end

  def destroy
    # ...
  end
end

newがログイン画面、createがログイン、destroyがログアウトになります。

狭義のREST

newとeditは、実はRESTfulなアクションではありません。たとえばweb apiとしてRailsを使ったときに2つのアクションはなくなります。getアクションとして返すものはなく、RailsのviewのUIのためのアクションであることがわかります。 ただし、これ自体悪いことではなく、逆に自分のアプリケーションを作る際に、controllerに定義していいアクションとして更にプレビュー画面用のアクションを追加することもできます。

まとめ

この章で出てきたSessionsController#new, #create, #destroyは本当にあるある(device gemやRailsチュートリアル)なので覚えておきたいし広めていきたいなと思いました。

Rails アンチパターン - モノリシックなコントローラ(Monolithic Controllers)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は7 Testの1つめ「Fixture Blues」についてまとめました。

waterlow2013.hatenablog.com   今回は4 Controllersの4つめ「Monolithic Controllers」についてまとめます。

Monolithic Controllers

解決策有りきなのだが、REST原則に乗っていないコントローラをRESTに乗せる。 以下のようなサンプルがあったとする。

class AdminController
  def users
    #...
    if not params[:operation].nil?
      if params[:operation] == "reset_password"
        # ...
      end
      if params[:operation] == "activate_user"
        #...
      end
      if params[:operation] == "show_user"
        #...
      end
    end
    user_order = 'username'
    if not params[:user_sort_field].nil?
      user_order = params[:user_sort_field]
      # ...
    end
  end
end

URLは以下になります。

POST /admin/users?operation=reset_password?id=x
POST /admin/users?operation=delete_user?id=x
POST /admin/users?operation=activate_user?id=x
GET /admin/users?operation=show_user?id=x
GET /admin/users

usersはアクションではなくリソース名であるべきなのでうつす。また、operationの中身をアクションに移動する。 urlは以下のように変わる。

POST /admin/users/:id/password
DELETE /admin/users/:id
POST /admin/users/:id/activation
GET /admin/users/:id
GET /admin/users

コードも変わる

class UsersController < ApplicationController
  def index
    # ...
  end

  def destroy
    # ...
  end

  def show
    # ...
  end
end

class PasswordsController < ApplicationController
  def create
    # ...
  end
end

class ActivationsController < ApplicationController
  def create
    # ...
  end
end

config/routes.rbは以下のようになる。

namespace :admin do
  resources :users do
    resource :passwords
    resource :activations
  end
end

まとめ

index, new, create, edit, update, show, destroy以外のアクションがある場合や、アクションが7つに含まれていても1つのアクションが大きくなっている場合はRESTに寄せつつコントローラを分け、先に書いた7つのアクションに乗せるのがいいと思います。

DHHのコントローラの作り方の記事にも書いてましたね! postd.cc

Rails アンチパターン - Fixtureの憂鬱(Fixture Blues)

引き続きRails AntiPatternsという本を読んでいます。

https://www.amazon.co.jp/dp/B004C04QE0/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

前回は4 Controllersの3つめ「Bloated Sessions」についてまとめました。 waterlow2013.hatenablog.com

今回は7 Testの1つめ「Fixture Blues」についてまとめます。

Fixture Blues

fixtureはRailsにデフォルトで組み込まれているテストデータ作成機能だが、以下のような難点がある。

  • 共通化すると変更したときに壊れやすい。
  • 毎回作っているとfixtureが大量にできてしまう。

Solution: Make Use of Factories

  • FactoryGirl gemを使おう。
  • 各フィールド のオーバーライドが容易なので、fixture量産しなくていい。

正直fixtureをそこまでちゃんと使ったことがいので、fixture vs factoryに関しては何も言えません。rspec bookもfactory girlを取り上げつつも反対する意見があることも書かれています。 fixture vs factoryに関してはググると色々出てきますが、以下の記事がわかりやすいかも。 blog.jnito.com

Solution: Refactor into Contexts

  • testunitでもcontext分けが出来るようになるgemの紹介と、context入れると明示的でかつDRYになるという話。特にテストデータのセットアップ。

これもrspecしか使ったことがないので、良さに関してはよくわからず…。

rspecにおけるdescribe, context辺の使い方は以下のwillnet氏のrspec coding stileを読むと良さそう。 github.com

まとめ

Rspecやfactory gilrに関してまだまだ知らない事があるなと思ったのでドキュメント読んだりして身につけていく必要があるなと思いました。 あとはfixtureやminitestもどこかでやりたい。