good predictors of whether a project is in good shape. Once and only once ... Lots of little pieces - Good code invariably has small methods and small objects. Only by factoring the system into many small pieces of state and function can you hope to satisfy the “once and only once” rule. ... Replacing objects - Good style leads to easily replaceable objects. In a really good system, every time the user says “I want to do this radically different thing,” the developer says, “Oh, I’ll have to make a new kind of X and plug it in.” ... Kent Beck – Smalltalk Best Practice Patterns
table) • Helpers (one per controller) • Controllers (~ one per DB table) • Views (~ 7 * controller) The number of objects is somehow fixed Objects are rarely reusable
IconBuffet had 10 controllers and 76 actions. Now, without adding or removing any features, IconBuffet has 13 controllers and 58 actions. There are seven standard Rails actions: index, new, create, show, edit, update, and destroy. Everything else—oddball actions—are usually a clue that you’re doing RPC.
# ... end def self.expand_search_aliases(keywords_string) # ... end def self.expand_alias keywords, key, value # ... end def self.join_with_translations_table # ... end # ... end
|keywords| FullTextSearch.new(keywords).to_scope } # ... end class FullTextSearch def to_scope { :conditions => ... } end private def whitelist_characters_for_search # ... end # ... end Cure: use composition
:id => "1234", :first_name => "Arthur") get "/users/display?id=1234" assert_select "table" do assert_select "td#user_first_name", "Arthur" end end <table> <tr class="even"> <td><strong>First Name</strong></td> <td id="user_first_name"><%= @user.first_name %></td> </tr> </table> Red Green
<tr class="odd"> <td><strong>Last Name</strong></td> <td id="user_last_name"><%= @user.last_name %></td> </tr> <tr class="even"> <td><strong>Email</strong></td> <td id="user_email"><%= @user.email %></td> </tr> </table> it "displays information for a given user" do Factory.create(:user, :id => "1234", :first_name => "Arthur", :last_name => "Fonzarelli", :email => "[email protected]") get "/users/display?id=1234" assert_select "table" do assert_select "td#user_first_name", "Arthur" assert_select "td#user_last_name", "Fonzarelli" assert_select "td#user_email", "[email protected]" end end Red Green Red Green Red Green aaaaaaaaagh!!
2.Run all tests and see the new one fail. 3.Make a little change. 4.Run all tests and see them all succeed. 5.Refactor to remove duplication. Kent Beck, Test Driven Development: By Example Not "refactor at will"!
• Split models, delegate to objects and modules • Refactor views! Use helpers everywhere • Use plugins • Develop your own DSL • Think general! Not specific! Abstract! • Have fun!!!