SlideShare a Scribd company logo
Skinny Controllers,
Skinny Models
M3 Tech Talk #m3dev
Kazuhiro Sera @seratch
RubyKaigi 2013
•  LT しました(rspec-kickstarter)
•  席に戻ったら Gemfile に追加!
•  今日は Refactoring Fat Models with
Patterns という講演の内容とその実践に
ついて紹介します
•  興味を持った方は、動画が公開されている
ので後で観てみてください
https://vimeo.com/68611168
Skinny Controllers, Skinny Models
@brynary
•  Bryan Helmkamp
•  Code Climate 創業者
•  顧客の Ruby コードを解析して品質・セ
キュリティ改善を支援するサービス
•  OSS なら無料、以下は Gistub の例
•  https://codeclimate.com/github/
seratch/gistub/
Code Climate: Rating
Code Climate: Code Smell
Code Climate: Classes
ブログエントリ
•  7 Patterns to Refactor Fat ActiveRecord
Models
•  http://blog.codeclimate.com/blog/
2012/10/17/7-ways-to-decompose-fat-
activerecord-models/
•  さらに改善されたコード例を GitHub で公開
している(RubyKaigi での発表で使用)
•  https://github.com/codeclimate/
refactoring-fat-models
Rails ActiveRecord
•  Pro: シンプルさ
•  Con: DB のテーブルと 1:1 を強いられる
Rails アプリでの失敗例
•  適切にデザインされたオブジェクト指向の
コードはラビオリに例えられる
•  時折、カルゾーネみたいに一カ所に詰め込
んだ Rails コードを見かける・・
Skinny Models
•  Fat Models とよく言われるが Model も
Skinny であるべきなんでは?
Fat Models との戦い
•  Controller が肥大化するよりはマシ?
•  既存の AR(ActiveRecord) model に責
務を持たせていくとどんどん肥大化
•  最悪のケースは神オブジェクトが誕生
•  @brynary は、定番の実装パターンをうま
く Rails の model のリファクタリングに
適用する方法を提案している
アンチパターン
•  ただし、安易に mixin として module に
切り出すのはアンチパターン
•  mixin は形を変えた継承
•  がらくたを突っ込む引き出し(コードを
module に移して include するだけ)
•  たくさん mixin された class だとどんな
オブジェクトか把握するのが大変になる
7 つの実装パターン
•  Value Objects
•  Service Objects
•  Form Objects
•  Query Objects
•  View Objects
•  Policy Objects
•  Decorators
Value Objects
•  おなじみ Value Object
•  immutable な値を保持するクラス
•  保持する値によって比較可能
•  何らかのロジックを持つ attribute(また
はその小さな集合)が適している
•  具体例:PhoneNumber、Money、
Ratingなど
Service Objects
•  複数の model を利用する場合
•  外部のサービス、API と連携する場合
•  複雑なロジックを実装する場合
•  既存の model の主たる責務でない場合
•  Strategy パターンを適用したい場合
•  普通 ActiveModel ではない
Form Objects
•  一つのフォームで複数の AR model を更
新したい場合に有効
•  ActiveModel にする
•  Form の save の内部で複数の AR model
の save を呼び出す
•  標準の accepts_nested_attributes_for
は @brynary 的には非推奨
•  複雑になったら永続化処理を Service に
Query Objects
•  バッチ用 or 複雑な条件の SQL を AR の
scope やクラスメソッドにせず Query
Object として分離
•  初期化時に AR::Relation オブジェクトを
渡すようにすると合成可能になる
•  TrialQuery.new(Account.where(…)).fin
d_each do ¦e¦ … end
View Objects
•  View のためのロジックを AR model に
書かない(エラーメッセージ生成など)
•  AR model を保持するクラスを定義し
render にはこちらを渡すようにする
•  helper に AR model を渡す実装よりも、
リファクタリングが促進される
•  多様な UI に対応する場合にも有効
Policy Objects
•  AR model を参照はするが主たるドメイ
ンではないロジック(分析のための判定
など)を分離する
•  例:メール配信対象?アクティブユーザ?
•  AR model を保持するクラスとして定義
•  他との違い:Policy は read な処理だけ
Service は write も含む、Query は SQL
実行と result set を yield に渡すだけ
Decorators
•  Decorator パターンを適用して callback
地獄を回避する
•  例:save メソッドを数珠つなぎにする
(AR の Order#save で orders テーブル
に insert -> DHW に通知 -> 受付完了
メールを送信)
実践してみた
•  実際にパターンを使って Gistub のリファ
クタリングをしてみた
パターンを実践する前
パターンを実践した後
やったこと
•  使ったパターンは Service Objects だけ
•  単に Controller から Service に切り出し
ただけだと、今度はその新しい Service
のスコアが悪かった(当たり前)
•  複雑度の高すぎるメソッドを名前を付け
られる単位に分割
•  コードの重複を共通化
改善の過程
今日から出来ること
•  盲目的に AR のクラスメソッドにしない
•  AR でないモデルもどんどんつくる
•  Controller に AR model 呼び出しをズラ
ズラ書くより Service にする
•  複雑なフォームは Form を導入する
•  AR に表示用ロジックを持たず View
Object でラップして表示処理に渡す
まとめ
•  既に実践されているものも多いが、パター
ンに名前がついて言語化されることは大事
•  最初はシンプルでよい(パターンのやりす
ぎは over engineering)
•  アプリが育っていく中で規模に応じたリ
ファクタリングは必要になっていく
•  ただし、十分なコードカバレッジは必須
アプリ規模とアーキテクチャ
Q&A
M3 Tech Talk #m3dev
Kazuhiro Sera @seratch
Any Question?

More Related Content

PDF
DevOpsハッカソン参加レポート
PDF
多分モダンなWebアプリ開発
PDF
Connect(); // 2015 Latest information
PDF
JAWS-UGアーキテクチャ専門支部 ServerlessConfレポート
PDF
Scala が支える医療系ウェブサービス #jissenscala
PDF
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
PDF
What is Serverless?
PPTX
CakePHP3で学ぶAPIマネジメント #phpconfuk
DevOpsハッカソン参加レポート
多分モダンなWebアプリ開発
Connect(); // 2015 Latest information
JAWS-UGアーキテクチャ専門支部 ServerlessConfレポート
Scala が支える医療系ウェブサービス #jissenscala
ビズリーチの新サービスをScalaで作ってみた 〜マイクロサービスの裏側 #jissenscala
What is Serverless?
CakePHP3で学ぶAPIマネジメント #phpconfuk

What's hot (20)

PDF
2016/05/01 Visual Studio with Cordova
PPTX
2016/12/17 ASP.NET フロントエンドタスク入門
PDF
Single Command Deployのための gradle-aws-plugin講座
PDF
The Internal of Serverless Plugins
PDF
退屈なブラウザ作業をpuppeteerにやらせたいお話
PPTX
実践サーバレスアーキテクチャ
PDF
JavaからScalaへ
PDF
App Service の DevOps と Visual Studio Team Services 最新アップデート
PDF
Isomorphic web development with scala and scala.js
PDF
メルカリの開発スピードと品質を支える Selenium on Azure Kubernetes Service
PDF
今なぜサーバーレスなのか
PPTX
10分でわかるOpenAPI V3
PDF
One ASP.NET, OWIN & Katana
PPTX
Android ReactNative UITesting
PDF
OWIN って何?
PDF
Swaggerで始めるモデルファーストなAPI開発
PPTX
Visual Studio 2019 Updates Pickup!
PDF
Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech
PPTX
日本で DevOps を ロケットスタートする方法
PDF
おれおれブログシステムにServiceWorkerを導入してみた #serviceworker
2016/05/01 Visual Studio with Cordova
2016/12/17 ASP.NET フロントエンドタスク入門
Single Command Deployのための gradle-aws-plugin講座
The Internal of Serverless Plugins
退屈なブラウザ作業をpuppeteerにやらせたいお話
実践サーバレスアーキテクチャ
JavaからScalaへ
App Service の DevOps と Visual Studio Team Services 最新アップデート
Isomorphic web development with scala and scala.js
メルカリの開発スピードと品質を支える Selenium on Azure Kubernetes Service
今なぜサーバーレスなのか
10分でわかるOpenAPI V3
One ASP.NET, OWIN & Katana
Android ReactNative UITesting
OWIN って何?
Swaggerで始めるモデルファーストなAPI開発
Visual Studio 2019 Updates Pickup!
Consumer Driven Contractsで REST API/マイクロサービスをテスト #m3tech
日本で DevOps を ロケットスタートする方法
おれおれブログシステムにServiceWorkerを導入してみた #serviceworker
Ad

Viewers also liked (20)

PDF
テストの運用について #m3dev
PPTX
Writeexcelについて
PPTX
Coursera experience
PDF
Phone Home: A client-side error collection system
PDF
Guess the Country - Playing with Twitter Streaming API
PDF
3分 gem クッキング
PDF
ScalaCache: simple caching in Scala
PDF
問題が起こった時、変えるのは人かそれともプロセスか?
PDF
Branching Strategies: Feature Branches vs Branch by Abstraction
PDF
Load testing with gatling
PDF
Skinny Framework 1.0.0
PDF
マイクロサービス運用の所感 #m3dev
PDF
Rails 3 Beautiful Code
PPT
Comment répondre à la demande contraceptive?
PDF
Rails 3 overview
PDF
Pourquoi Ruby on Rails est génial? (d'un point de vue non technique)
PDF
MvcのFatモデルに立ち向かう
PDF
一生、エンジニアであり続けるために必要なこと「負けてからのエンジニアライフ」
PDF
桐島、Rubyやめるってよ
PDF
Contributing to Scala OSS from East Asia #ScalaMatsuri
テストの運用について #m3dev
Writeexcelについて
Coursera experience
Phone Home: A client-side error collection system
Guess the Country - Playing with Twitter Streaming API
3分 gem クッキング
ScalaCache: simple caching in Scala
問題が起こった時、変えるのは人かそれともプロセスか?
Branching Strategies: Feature Branches vs Branch by Abstraction
Load testing with gatling
Skinny Framework 1.0.0
マイクロサービス運用の所感 #m3dev
Rails 3 Beautiful Code
Comment répondre à la demande contraceptive?
Rails 3 overview
Pourquoi Ruby on Rails est génial? (d'un point de vue non technique)
MvcのFatモデルに立ち向かう
一生、エンジニアであり続けるために必要なこと「負けてからのエンジニアライフ」
桐島、Rubyやめるってよ
Contributing to Scala OSS from East Asia #ScalaMatsuri
Ad

Similar to Skinny Controllers, Skinny Models (20)

PDF
A HUGE CHANGE RAILS 5 IS APPROACHING FAST
PDF
Ruby on Rails 4.0 勉強会資料
PDF
Hyper → Highspeed → Development
PDF
名前重要 超重要
ODP
Fabrication
PDF
DDD 20121106 SEA Forum November
PDF
serviceクラスをやめようサブクラスを使おう
PPTX
Arcana study meeting by tenta
PDF
リソースモデリングパターンの提案 #sendagayarb
PDF
魂のコーディング
PDF
ドメイン駆動設計 の 実践 Part3 DDD
PDF
nomlab_okayamaruby_subslide
PDF
Railsハイパー実践講座-第35回NaCl勉強会
PDF
リーンなコードを書こう:実践的なオブジェクト指向設計
PDF
Introduction of record_with_operator
PDF
Pyramid入門
PDF
「エクストリームエンジニアへの道(Swift編)」
PDF
「バグあるある」と「仕様変更あるある」一挙大放出SP!
PDF
全部入り!WGPで高速JavaScript+HML5体験
PDF
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くか
A HUGE CHANGE RAILS 5 IS APPROACHING FAST
Ruby on Rails 4.0 勉強会資料
Hyper → Highspeed → Development
名前重要 超重要
Fabrication
DDD 20121106 SEA Forum November
serviceクラスをやめようサブクラスを使おう
Arcana study meeting by tenta
リソースモデリングパターンの提案 #sendagayarb
魂のコーディング
ドメイン駆動設計 の 実践 Part3 DDD
nomlab_okayamaruby_subslide
Railsハイパー実践講座-第35回NaCl勉強会
リーンなコードを書こう:実践的なオブジェクト指向設計
Introduction of record_with_operator
Pyramid入門
「エクストリームエンジニアへの道(Swift編)」
「バグあるある」と「仕様変更あるある」一挙大放出SP!
全部入り!WGPで高速JavaScript+HML5体験
DDDはオブジェクト指向を利用してどのようにメンテナブルなコードを書くか

More from Kazuhiro Sera (20)

PDF
All I learned while working on a Scala OSS project for over six years #ScalaM...
PDF
Skinny Meetup Tokyo 2 日本語スライド
PDF
Skinny 2 Update
PDF
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
PDF
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
PDF
Future on Servlet #scala_ks
PDF
Servlet と Future の関わり方 #scala_ks
PDF
Scala on Rails #rakutentech
PDF
Solid And Sustainable Development in Scala
PDF
Beginning Scala with Skinny Framework #jjug_ccc
PDF
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
PDF
Skinny Framework Progress Situation
PDF
Skinny Framework 進捗どうですか? #fud_scala
PDF
めんどくさくない Scala #kwkni_scala
PDF
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
PDF
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
PDF
テストを書くのが嫌いな君へ #m3dev
PDF
ScalikeJDBC Tutorial for Beginners
PDF
A Test Code Generator for RSpec Users
PDF
Crucible @ M3, Inc.
All I learned while working on a Scala OSS project for over six years #ScalaM...
Skinny Meetup Tokyo 2 日本語スライド
Skinny 2 Update
Seasar ユーザだったプログラマが目指す OSS の世界展開 #seasarcon
Java エンジニアチームが始めやすい Scala コーディングスタイル #ichigayageek
Future on Servlet #scala_ks
Servlet と Future の関わり方 #scala_ks
Scala on Rails #rakutentech
Solid And Sustainable Development in Scala
Beginning Scala with Skinny Framework #jjug_ccc
[Japanese] Skinny Framework で始める Scala #jjug_ccc #ccc_r24
Skinny Framework Progress Situation
Skinny Framework 進捗どうですか? #fud_scala
めんどくさくない Scala #kwkni_scala
歌舞伎座.tech 1 LT - ScalikeJDBC Async & Skinny Framework #kbkz_tech
Kabukiza.tech 1 LT - ScalikeJDBC-Async & Skinny Framework #kbkz_tech
テストを書くのが嫌いな君へ #m3dev
ScalikeJDBC Tutorial for Beginners
A Test Code Generator for RSpec Users
Crucible @ M3, Inc.

Skinny Controllers, Skinny Models