古典的記事「Skinny Controller, Fat Model」を読む
こちらの記事
Buckblog: Skinny Controller, Fat Model
この記事を読んで得られる知識、技術
- Railsにおいて、どこに何を書くのか?
- 特にコントローラに何を書くか、モデルに何を書くか、の基礎となる指針
どんな記事か?
18 October 2006 と古い記事だが、Railsにおける設計の古典的、かつ著名な記事。
2018年現在では、Fat Modelに関する問題点、そして解決法も出てきた。
しかし、記事内で指摘されていることは、そっくりそのまま「Railsチュートリアル」や「every Rails RSpecによるRailsテスト入門」にも登場する実装例で、現在も有効な考え方。簡単でサクサク読めて分かりやすいので一読の価値あり。
具体的な内容は?
最終的に、一目見ただけで理解できる、メンテナンス性の高いコード!ができるよというもの。
「Skinny Controller, Fat Model」のタイトル通り、Modelが太っていく様子が見られる。
英語読むの面倒だから簡潔にまとめて?
Viewのリファクタリング
before
問題点はViewの中でガチャガチャ文字列を合わせたり計算したり、ノイズがあること。
<% @people.each do |person| %> <div id="person"> <span class="name"> <!-- 改善できる箇所その1 --> <%= person.last_name %>, <%= person.first_name %> </span> <span class="age"> <!-- 改善できる箇所その2 --> <%= (Date.today - person.birthdate) / 365 %> </span> </div> <% end %>
After
よく使われる処理を、抽象的で分かりやすいデータをViewに提供する責務があるモデルに集約する。
<% @people.each do |person| %> <div id="person"> <span class="name"> <%= person.name %> </span> <span class="age"> <%= person.age %> </span> </div> <% end %>
Person Model
class Person < ActiveRecord::Base # ... # これ、everyday Railsで出てきた! def name "#{last_name}, #{first_name}" end def age (Date.today - person.birthdate) / 365 end end
Controllerのリファクタリング
before
問題点は、一目見た時に何をしているのか理解できない。そのため、可読性や保守性が著しく低い。
class PeopleController < ActionController::Base def index @people = Person.find( :conditions => ["added_at > ? and deleted = ?", Time.now.utc, false], :order => "last_name, first_name") @people = @people.reject { |p| p.address.nil? } end end
after
分かりやすいメソッドに抽出することで、一目で理解できる。
find_recentではなくfind_activeやfind_activatedの方が良さそうな気もするが主目的によるか...
class PeopleController < ActionController::Base def index @people = Person.find_recent end end
Person Model
クラスメソッドで定義する
class Person < ActiveRecord::Base def self.find_recent people = find( :conditions => ["added_at > ? and deleted = ?", Time.now.utc, false], :order => "last_name, first_name") people.reject { |p| p.address.nil? } end # ... end