blog.waterlow.work

Ruby, Rails, js, etc...

Rails アンチパターン - 継続的な大災害(Continual Catastrophe)

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

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

前回は6 Using Third-Party Codeの1つめ「Recutting the Gem」についてまとめました。

waterlow2013.hatenablog.com

今回は10 Building for Failureの1つめ「Continual Catastrophe」についてまとめていきます。

Continual Catastrophe

サンプルとして以下のようなスクリプトを挙げる。

cd /data/tmp/
rm-rf*

/data/tmp/がない場合に、ディレクトリ移動せず2行目が実行されたらどうなるか。ディレクトリが存在しない場合そこで終了するのが望ましい。(bashには-eや&&演算子がある)

Solution: Fail Fast

以下のようなコードがあるとする。

class Portfolio < ApplicationRecord
  def self.close_all!
    all.each do |portfolio|
      unless portfolio.photos.empty?
        raise "Can't close a portfolio with photos."
      end
      portfolio.close!
    end
  end
end

これは途中でエラーになった場合に中途半端にcloseされてしまうので、初めにチェックするようにする。

class Portfolio < ApplicationRecord
  def self.close_all!
    all.each do |portfolio|
      unless portfolio.photos.empty?
        raise "Can't close a portfolio with photos."
      end
    end

    all.each do |portfolio|
      portfolio.close!
    end
  end
end

更に早くチェックする方法として、UIからclose_allできないようにする,コントローラでリクエストを弾くなどがあげられる。

Fail Fastのメリットは

  • 大災害を防げる
  • はじめにチェックが宣言的に書かれているのでわかりやすい
  • よくわからんところでぬるぽがでるのはうんざりだ!

たとえばARのfind_byとかも、レコードあり前提であればfind_by!で適切なエラーで失敗させるのがわかりやすいかなと思います。(ただし、例外を制御フローに組み込むのは絶対NG)createとかも同様ですね。(controllerのcreate, update内は別)

まとめ

その通りだなと思っていました。(それ以上の感想がない…。)