Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rules of Three

Rules of Three

Lightning talk at WindyCityRails 2012, Sept. 7 2012

David Demaree

September 07, 2012
Tweet

More Decks by David Demaree

Other Decks in Programming

Transcript

  1. THE PROBLEM It’s really easy to convince yourself that today’s

    code will be more complex in the future, and design for that.
  2. THE PROBLEM It’s really easy to convince yourself that today’s

    code will be more complex in the future, and design for that.
  3. The Rule of Three “Code can be copied once, but

    that when the same code is used three times, it should be extracted into a new procedure.” http://en.wikipedia.org/wiki/Rule_of_three_(computer_programming) 1 2 3 A A A A
  4. def foo # Does some stuff ... if @user.status ==

    :active @user.status = :inactive @user.save! end end OK
  5. def foo # Does some stuff ... if @user.status ==

    :active @user.status = :inactive @user.save! end end OK def bar # Does some other stuff ... if @user.status == :active @user.status = :inactive @user.save! end end ❓ STILL OK
  6. def foo # Does some stuff ... if @user.status ==

    :active @user.status = :inactive @user.save! end end OK def bar # Does some other stuff ... if @user.status == :active @user.status = :inactive @user.save! end end ❓ STILL OK def baz # Does yet other stuff ... if @user.status == :active @user.status = :inactive @user.save! end end ⚠ JANKY
  7. def deactivate_user(user) if user.status == :active user.status = :inactive user.save!

    end end def foo # Does some stuff ... deactivate_user(@user) end def bar # Does some other stuff ... deactivate_user(@user) end def baz # Does yet other stuff ... deactivate_user(@user) end
  8. def deactivate_user(user) if user.status == :active user.status = :inactive user.save!

    end end def foo # Does some stuff ... deactivate_user(@user) end def bar # Does some other stuff ... deactivate_user(@user) end def baz # Does yet other stuff ... deactivate_user(@user) end This is better code BUT Resist the temptation to do this until you really have repeated yourself three times
  9. class User < ActiveRecord::Base def adobe_profile AdobeId::Profile.new(self.adobe_profile_id) end def connected_to_adobe_profile?

    !self.adobe_profile_id.nil? end end def connect_to_adobe_profile(profile_obj) self.adobe_profile_id = profile_obj.id self.email_unique = false save end ❓
  10. class User < ActiveRecord::Base def adobe_profile AdobeId::Profile.new(self.adobe_profile_id) end def connected_to_adobe_profile?

    !self.adobe_profile_id.nil? end end def connect_to_adobe_profile(profile_obj) self.adobe_profile_id = profile_obj.id self.email_unique = false save end ❓ def disconnect_adobe_profile self.adobe_profile_id = nil self.email_unique = true save end ⚠
  11. module UserAdobeProfile def adobe_profile AdobeId::Profile.new(self.adobe_profile_id) end def connected_to_adobe_profile? !self.adobe_profile_id.nil? end

    # Anything else pertaining to users' # Adobe profiles … end class User < ActiveRecord::Base include UserAdobeProfile end
  12. I believe writing a truly reusable class is an order

    of magnitude harder than writing a single use class. Sometimes the right thing to do is resist the urge to write "general purpose" solutions. “ ” http://www.codinghorror.com/blog/2004/09/the-delusion-of-reuse.html JEFF ATWOOD:
  13. It will not surprise you to learn that WE ARE

    HIRING http://bit.ly/typekitrailsjob or just come talk to me