AntiPattern: Fat Models
"Fat Model, Skinny Controller"という言葉は聞きますが、too fat modelはそもそもコードが読めなくなるし、Railsのパターン以前にOOPやもっと足下の理念から外れてしまいます。クラスを分ける、モジュールを使う、callbackを使うなどORM自体で搭載されている機能は使用するという解決策を。
AntiPattern: ながーいSQLチェーン
例えば人気のある記事トップ10を引っ張って来る時にコントローラの中で、@posts = Post.where(status: "published", order: "number_visited DESC").limit(10)
とするよりも
モデルの中で
class Post
scope :tops, where(status: "published", order: "number_visited DESC").limit(10)
end
とすれば
@posts = Post.tops
だけですみます。これはテストを書く際にも
before(:each)
published_posts = create(:posts)
Post.stub(:where){published_posts}
tops_posts = published_posts.take(10)
published_posts.stub(:limit).with(10) {top_posts}
end
などというスタッブ・モックチェーンを書かなくても済みます。テストを書く際にメソッドチェーンはしんどい…。"Don't ask codes but tell what to do."というような言葉もありましたが、やはりTDDのプラクティスをうまく実行すればしんどいコードを書かなくても済みそうですね。
AntiPattern: 入り組んだユーザ権限処理(authorization)
authorizationの実装を下の様にするケースが多いそうです。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord::Base | |
has_and_belongs_to_many :roles | |
### Some methods are written here... | |
def can_post? | |
self.has_roles?(%w(admin editor contributor)) | |
end | |
### Some more methods are written here... | |
end |
こうやっていくとだんだんとスパゲッティーになっていくので、こういう書き方は一切辞めて下のように is_guest? is_manager? などと役割役割の名前でauthorizationを実装します。また、役割もデータベースに保存しないでコンスタントとしてハードコードしてしまいます。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class User < ActiveRecord:Base | |
has_many :roles | |
Role::TYPES.each do |role_type| | |
define_method "#{role_type}?" do | |
roles.exists?(name: role_type) | |
end | |
end | |
class Role | |
TYPES = %w(guest contributor manager admin) | |
validates :name, inclusion: (in: TYPES) | |
end | |
end |
No comments:
Post a Comment