Pro Yearly is on sale from $80 to $50! »

Seattle.rb - Refactoring & BDD Presentation

Seattle.rb - Refactoring & BDD Presentation

A presentation on code refactoring that I gave at Seattle.rb in October, 2012. There is also a behavioral driven development example from my work on the CapGun http://capgun.io/ service.

74c036cfbef785b139d06ccad4687b44?s=128

Mike Mondragon

October 09, 2012
Tweet

Transcript

  1. Refactoring Mike Mondragon @monde Tuesday, January 8, 13

  2. Thank you Seattle.rb Tuesday, January 8, 13

  3. Refactoring? Tuesday, January 8, 13

  4. “Refactoring” Tuesday, January 8, 13

  5. “Refactoring” •Examples •Definition & Principles •Symptoms (Code Smells) •Testing •Catalog

    Tuesday, January 8, 13
  6. Why Refactor? •My code sucks •I don’t know what I’m

    doing •I don’t know what this code is doing Tuesday, January 8, 13
  7. Why Refactor? •Their code sucks •They don’t know what they

    are doing •I don’t know what their code is doing Tuesday, January 8, 13
  8. The less your problem is understood, the more complicated your

    solution is likely to be. Somebody Said This Tuesday, January 8, 13
  9. Refactoring •Modify code in small steps •Write tests for code

    that is affected •Write human readable code Tuesday, January 8, 13
  10. package.data.size == 0 package.data.size < 12 package.data.size == 12 Example

    Tuesday, January 8, 13
  11. Example Logic defining the state of the object is contained

    outside of it package.data.size == 0 package.data.size < 12 package.data.size == 12 Tuesday, January 8, 13
  12. package.data.size == 12 || package.data.size == 13 Example • Hard

    to find all places of code implementing outside logic • Object doesn’t control it’s own logical state Tuesday, January 8, 13
  13. Cat Picture -- (DO NOT WANT) Tuesday, January 8, 13

  14. Query? Method Pattern •Object tells you it’s state •Method is

    intention revealing •Is human readable •Examples: obj.nil? ... num.zero? Tuesday, January 8, 13
  15. Example Write tests first it "can be empty" do @package.empty?.must_equal

    true end it "can't be partial" do @package.partial?.must_equal false end it "can't be complete" do @package.complete?.must_equal false end Tuesday, January 8, 13
  16. Example Fail is good 1) Error: test_0001_can_be_empty(Package): NoMethodError: undefined method

    `empty?' for #<Package:0x007fc304d960b0> spec.rb:16:in `block (2 levels) in <main>' 2) Error: test_0002_can_t_be_partial(Package): NoMethodError: undefined method `partial?' for #<Package:0x007fc304d954a8> spec.rb:20:in `block (2 levels) in <main>' 3) Error: test_0003_can_t_be_complete(Package): NoMethodError: undefined method `complete?' for #<Package: 0x007fc304d93f18> spec.rb:24:in `block (2 levels) in <main>' Tuesday, January 8, 13
  17. Example Implementation, State Is In A Single Location def empty?

    data.size.zero? end def partial? !empty? && data.size < 12 end def complete? data.size == 12 || data.size == 13 end Tuesday, January 8, 13
  18. I heard you like state so much, I put some

    ... Tuesday, January 8, 13
  19. Example Passing but ... # Running tests: Package#test_0002_can_t_be_partial = 0.49

    s = . Package#test_0001_can_be_empty = 0.54 s = . Package#test_0003_can_t_be_complete = 0.98 s = . Finished tests in 2.007646s, 1.4943 tests/s, 1.4943 assertions/s. 3 tests, 3 assertions, 0 failures, 0 errors, 0 skips wtf? 2 seconds Tuesday, January 8, 13
  20. Example Production data hardcoded into implementation :( def data JSON.parse(HTTParty.get(

    'http://goo.gl/4L1Zd' )) end Tuesday, January 8, 13
  21. Example Mock or override #data method in specs module SpecEmpty

    def data [] end end Tuesday, January 8, 13
  22. Example Mock or override #data method in specs - clears

    away distractions before do @package = Package.new @package.extend(SpecEmpty) end it "can be empty" do @package.empty?.must_equal true end Tuesday, January 8, 13
  23. Example Passing and ... # Running tests: Package::empty#test_0002_can_t_be_partial = 0.00

    s = . Package::empty#test_0001_can_be_empty = 0.00 s = . Package::empty#test_0003_can_t_be_complete = 0.00 s = . Finished tests in 0.000742s, 4043.1267 tests/s, 4043.1267 assertions/s. 3 tests, 3 assertions, 0 failures, 0 errors, 0 skips fast! ~0 seconds Tuesday, January 8, 13
  24. Simple Mistakes Compound Upon Themselves • logic was external to

    object • external logic is hard to maintain/find • we had no tests • external data implementation had to be addressed in testing Tuesday, January 8, 13
  25. Pro-Tips • Refactoring Favors Behavior Rather Than Logic • Writing

    code that can be unit tested changes your writing style • If a method can’t be unit tested it must be refactored • Factor out interaction with frameworks from code that is tested Tuesday, January 8, 13
  26. Cat Picture Tuesday, January 8, 13

  27. Outside-In Let your tests drive your implementation Tuesday, January 8,

    13
  28. Green Field Project Tuesday, January 8, 13

  29. Green Field Project Tuesday, January 8, 13

  30. This green field is already in production Tuesday, January 8,

    13
  31. Green Field Project Tuesday, January 8, 13

  32. http://capgun.io/ Tuesday, January 8, 13

  33. capgun.io API for web thumbs and web screens using headless

    webkit via PhantomJS/CasperJS Tuesday, January 8, 13
  34. CapGun Started Here Tuesday, January 8, 13

  35. So MANY Choices! • Sessions • Authentication • JSON rendering

    • Data Store(s) • ORM • framework(s) Tuesday, January 8, 13
  36. Start Somewhere Feature: Order Estimates As an API client In

    order to list information about orders I want to be able to query the order API Background: Given I am a valid API user And I send and accept JSON Scenario: getting an estimate for a base screen capping job When I send a POST request to "/api/v1/orders/estimate" with the following body: |{ "url": "http://example.com/cucumber#test" }| Then the response should be "200" And the JSON response should not have "order/job" And the JSON response should have an estimate of 1 credits Tuesday, January 8, 13
  37. Start Somewhere describe "Estimate" do describe "json" do should "estimate

    capping a URL for 1 credit" do post '/estimate.json', '{"url":"http://www.seattlerb.org/"}' JSON.parse(last_response.body).should == { 'order' { 'id' '4fd20a1288f560177600000a' 'url' 'http://www.seattle.rb/' 'cost' 1 } } end end end Tuesday, January 8, 13
  38. Write Code That Is Used Immediately, Do Not Future Proof

    It class Order def cost end end describe Order do describe "defaults" do it "should cost 1 credit" do subject.cost.should == 1 end end end Tuesday, January 8, 13
  39. Dog Food ASAP! Tuesday, January 8, 13

  40. Dog Food ASAP! http://tumblr.capgun.io/ Tuesday, January 8, 13

  41. • Write Specs • Fail • Write Code • Pass

    • ???? • Profit Iterate Tuesday, January 8, 13
  42. Outside-In / BDD is really just “poor man’s pair programming”

    *TM Tuesday, January 8, 13
  43. Thank You! Tuesday, January 8, 13

  44. Mike Mondragon •http://plasti.cx/ •@monde Twitter •@monde Github •@monde coderwall Tuesday,

    January 8, 13
  45. Image Attribution @monde Gavatar by Mike Mondragon https://secure.gravatar.com/avatar/74c036cfbef785b139d06ccad4687b44?s=420&d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-user-420.png Phil Hagelberg

    Seattle.rb shirt by veganstraightedge http://www.flickr.com/photos/veganstraightedge/7843002706/in/set-72157631203475428 Amazon cover of “Refactoring” book http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672 Wallace the cat cradled like a baby - Mike Mondragon Xzibit head shot - The Internet Wallace - THE INTERNETS is watching - Mike Mondragon on icanhazcheezburger Green field @ wallpaperstock.net http://wallpaperstock.net/green-field_wallpapers_8739_1024x768_1.html Palouse wheat field - unknown Palouse wheat field - unknown Tilled field - unknown CapGun logo - Mike Mondragon Skitch screen cap of CapGun panel - Mike Mondragon Tilled field - unknown Kitten asleep in food dish http://catlovingcare.com/2042/blog/loosing-weight-tips-for-fat-cats/2009/12/ Skitch screen cap of http://tublr.capgun.io/ - Mike Mondragon CapGun.io result for Seattlerb.org - Mike Mondragon Wallace the cat profile - Mike Mondragon Tuesday, January 8, 13