Sooey

2014-02-08 00:52:55 +0900

本日は5ヶ月ぶりくらいに散髪しました。このサイトは、こうした日記っぽいエントリを書けるようにあまりブログっぽい作りにはしていないのです(ブログエントリのタイトル駆動ではない)。

いわゆるブログ的なプラットフォームを使っているひとたちは日常のしょうもないことを書く時、タイトルや落とし所をどう捻り出してるのか気になります。それともそんな無意味なことは書かないのか。

以下、今日見つけたURLたち。

Continuous Deployment at Square: Hard & Soft Skills to Avoid Outages

1月にEtsyで開かれたContinuous Delivery NYCというミートアップで、Squareのニューヨークオフィス所属のエンジニアさんが発表したスライドと動画。Continuous Deploymentにおいて、障害を起こさないためのテクニックを紹介しているようです。

How do I test an application_controller on a rails app - Blog do Time

rspec-railsのanonymous controllerという仕組みを利用すると、ApplicationControllerに記述したコントローラー横断的なコードのテストが綺麗に書けるよ、という話。current_userメソッドなんかのテストをあるべき所に書けるというのはよさそう。

同じような話として、最近はapp/{controllers|models}/concerns/*.rbのテストをどこでやるか、というのが個人的な悩みどころです。

before_action an anti-pattern? | Transcending Frontiers

Railsのコントローラーにおいて、なんでもかんでもbefore_actionでやるような設計はアンチパターンではないか、という話。

before_actionでメソッドの呼び出しを宣言的に記述するのと、アクションメソッド内でそれらのメソッドを単純に呼ぶのとで、それぞれのメリット・デメリットを挙げたうえで、「アクションの実行を回避させるようなフロー制御をbefore_actionで書くのはいいと思う。それ以外の、単にデータをロードするためだけのメソッドなどはアクションメソッド内に書こう。コードが少し長くなるけど、そのほうが読みやすくて理解もメンテナンスも簡単だ」とのことです。

# Bad
before_action :find_post, only: :show

def show
  ...
end

# Good
def show
  find_post
  ...
end

コードで示すとこういうこと。

Orchard | Docker hosting

Dockerで任意のプロセスを実行することができるクラウドサービス。課金は1時間単位で、料金はスペック毎に何段階か。PiCloudを思い出したけど、あれよりはレイヤーが下な感じ。

Hakiri: Ruby on Rails Security

Railsアプリの脆弱性チェックをしてくれるサービス。14日間トライアルありで、5プロジェクト月額$19.99から。Gemfile.lockベースのチェックだけなら、同サイトのFacets — Scan Gemfile for Security Issuesで無料で行えます。

2013-12-21 02:50:08 +0900

Railsアプリが大きくなっていくにつれてうまく機能しなくなっていくパターンというものがあり、それに関してReverb.comが簡単に5つのアーキテクチャアンチパターンとしてブログにまとめていました。

Reverb.comはミュージシャンのためのマーケットプレイスサービスです。

紹介されている内容は、ドメインレイヤーのコードがRailsの想定する枠組みの外に配置されている構造を前提としいます。具体的には、ドメインレイヤーのクラスをActionControllerやActiveRecordといったRailsのアーキテクチャの範疇からは独立したものとして構築している形を指しているようです。

(1) 責務を抱えすぎたサービスオブジェクト (Service objects with many responsibilities)

  • 名詞+Serviceのような命名は責務の肥大化を招く
    • UserService
    • ProductService
  • 単一のことだけをやるユースケースクラスとして定義したほうがよい
    • Reverb::Accounts::ForgotPassword
    • Reverb::Orders::FinalizeCheckout
  • 単一のユースケースからしか使われていないメソッドを探し出してクラスに移動させる
  • あるユースケースのためだけのメソッドをActiveRecordモデルにどんどん追加していくのはやめる

参考:The Clean Architecture | 8th Light

(2) 名前空間に分けられていないドメインレイヤーのクラス (Un-namespaced classes in the domain layer)

  • Reverb.comのドメインレイヤーはapp/reverb以下に236個以上のクラスとして定義されている
  • 責務によってapp/reverb/checkoutapp/reverb/offersのように分類している
  • サービスクラス名と同じように名前空間もドメインコンセプトにしたがって命名している(Railsにおける慣習的な命名はしない)

(3) 機能を共有するためのモジュールインクルード (Including modules to share functionality)

  • ミックスインによるコードの共有は役立つこともあるが常用すべきでない
  • メソッドがどこで定義されているのかを見つけたり、クラス定義をざっと読んでパブリックなAPIを理解するのが難しくなってしまう
  • パブリックメソッドを含んだミックスインはオブジェクトの表面を広げるので、そのクラスを利用するコードとの結合を強めてしまう
  • ミックスインの代わりに、関連するオブジェクトへのデリゲートを明示的に行うようにする

(4) あらゆる種類の動的なメソッド呼び出し (Any kind of dynamic method invocation)

  • send、特にメソッド名を動的に指定するような呼び出しはgrepもリファクタリングもしづらい
  • Reverbではアプリケーションコード内(だいたい25,000行)で、method_missingは1度も使っていない
  • こうしたテクニックはメンテナンス時の頭痛の元となる
  • 凝ったDSLを作ろうとしない限りは不要だし、そういうものは外部のgemとして作るほうがいい
  • これを徹底するため、コードベースにsendの呼び出しがないことをテストするRSpec Matcherを使っている

(5) Railsのヘルパー (Rails Helpers)

  • グローバルにアクセスできるメソッドを定義してしまうので使わない
  • button_tolink_toを組み合わせて適切なCSSクラスを持ったボタンを定義するような用途はそれほど問題にはならない
  • link_to_userといったようなドメイン固有の知識を含む使い方はよくない
  • Draperなどを使ってメソッドをデコレーター内に含めるようにする

コメント欄ではサービスクラスに対して「クラスよりモジュール関数にしたほうがよいのでは」、「サービスクラスのメソッド名はForgotPassword.forgot_passwordForgotPassword.executeとどっちのスタイル?」といったやりとりもされているので、読んでおくと面白いかも。

2013-12-07 15:49:25 +0900

rack-mini-profiler 0.9.0.preの話。

Railsアプリで使っているrack-mini-profilerの設定を変更して、

  • デフォルトでは無効
  • URLに?pp=enabledを付ければ以降のセッション中は有効

という挙動にするため、GitHub上にあるREADMEのConfiguration Optionsを参考にconfig/initalizers/mini_profiler.rb

# Have Rack::MiniProfiler start disabled - you can use query string option to re-enable later
Rack::MiniProfiler.config.enabled = false

と記述してみたところ、

NoMethodError: undefined method `enabled=' for #<Rack::MiniProfiler::Config:0x007ff12a1305b0>

と例外が発生してしまう。

ソースコードをよく見てみるとHEADのREADMEで言及されているオプションは2013年12月5日にリリースされた0.9.0.preから利用可能になったもののようで、今のところのstable releaseである0.1.31では使えないみたい。

なので、Gemfileを

gem 'rack-mini-profiler', '0.9.0.pre'

と書き換えて最新版を使うようにしたことで、上記の設定が使えるようになった。