Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
71 lines (49 sloc) 2.57 KB

Rails 3 Refactoring

Robert C. Martin (Agile Software Devlopment): SOLID

S: Single Resp Prin.

  • Rails 0.x: ActionView::Base had too many responsibilities (details, templates, context, etc)

  • Rails 1.0: Reduce responsibilities, separate classes out, (Template handlers (builder, rjs, haml, erb): single responsibility)

  • Rails 2.2: view paths extracted (multiple places for view templates, allows Rails Engines)

  • Rails 3.0: View paths split into 'view paths' and 'resolvers'

    • Resolvers make it so views don't have to come from the filesystem (could be web service, database)
    • Added lookup context too, so less back and forth between view and controller
  • Rails 3.1: AV::Renderer in from of ActionView -- only single responsibility per class

    • Allows you to use something other than ActionView (e.g. Merb's views)
    • Allows you to use the renderer in Sinatra

    class BasicController <actionControlle::Base include ActionView::Context ...

  • Single reponsibilities: easier to separate out pieces and use them, and also replace them

  • Easier to understand each piece

  • Not as easy to take in the whole piece (top-down comprehension)

O: Open/closed Prin.

  • Extend class behavior without modifying the class

  • Class open for etension, closed for modification

    • Latter isn't enforced by Ruby
  • Don't break other people that depend on a library (e.g. modifying ActiveRecord::Base)

    • Lots of poeple do --- makes it hard to run multiple rails apps on a single process

D: Dependency Inversion Prin.

"Depend on abstractions, not on concretions"

  • Duck typing, basically. Depend on abstractions (e.g. what methods are available), rather than a single concrete class.

    match '/foo', to: 'posts#index' match '/foo', to: PostsController.action(:index) # Missed this last part, but it's a rack app!

  • Controllers have a middleware stack

  • Remove hard-coded dependencies (e.g. pass as an optional parameter)

  • Defining hooks (done in Railties)

L: Liskov Subs Prin.

"Derived classes must be substitutable for their base classes"

  • Need to respond to the same interface

  • What about a new version of Rails?

  • Static language: check to interface

    include ActiveModel::Lint::Tests # kind of the same idea

I: Interface Seg. Prin

  • Simplest protocol possible
  • How to ensure?
    • When you test, odn't use the conrete class -- use a Mock that only implements what you're expecting! (It's testing the 'concrete' interface, in a way)

Modularity driven by principles