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

Refactoring with Science

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers. →

Refactoring with Science

Using data and Science to refactor with greater confidence.

Wynn Netherland

February 21, 2014

Transcript

116 slides
  1. Write lots of TESTS. ! ❯ testrb test/integration/api/repos_test.rb Loading suite

    in dotcom mode ... Run options: # Running tests: Finished tests in 30.638101s, 4.7979 tests/s, 64.7886 assertions/s. 147 tests, 1985 assertions, 0 failures, 0 errors, 0 skips ruby -v: ruby 2.1.0p0-github (development) [x86_64-darwin13.0]
  2. !

  3. !

  4. 2009 ! # General configuration settings, required for all recipes!

    set :application, "project-name" set :domain, "project-domain" set :extra_domains, %w() # Add something like www.project-domain.com role :app, domain role :web, domain role :db, domain, :primary => true ! # set :user, "user" ! # Deployment Settings set :repository, "repository url" set :deploy_to, "/absolute/path/to/location/your/server" set :deploy_via, :checkout set :config_files, %w() ! # SSH Keys for caching (you must generate these first.) ssh_options[:keys] = %w(~/.ssh/mykey1 ~/.ssh/mykey2) ! # Change this to :thin if you want to use Thin instead. set :app_server, :mongrel ! # Change this to :merb if you want to use Merb instead. (experimental) set :app_framework, :rails ! # ============================================================= # Application Server Settings (Thin or Mongrel) # ============================================================= set :app_servers, 1 set :app_server_port, 7007 set :app_environment, 'production' set :app_server_address, '127.0.0.1' set :app_server_conf, "#{shared_path}/config/thin.yml" ! # ============================================================= # Nginx Settings
  5. !

  6. ! %

  7. !

  8. ! The following deployments are based on actual events. Branch

    names and SHAs have been changed to protect the innocent.
  9. ! hubot where can I deploy? > Environments for github

    ----------------------------------------------------- production: unlocked lab-one: locked 6 hours ago by jasonrudolph lab-two: unlocked sekret-lab: unlocked playground: unlocked
  10. ! hubot deploy github/api-my-feature to production > Merge master into

    api-my-feature for pengwynn - hubot github/github@deadbeef
  11. !

  12. ! hubot deploy github/api-my-feature to production > pengwynn is deploying

    github/api-my-feature (beefdead..deadbeef) to production pengwynn's production deployment of github is NOW )))! (22s)
  13. !

  14. !

  15. !

  16. !

  17. !

  18. ! > pengwynn: it looks like you merged "api-my-feature" branch

    into master, so I've unlocked production.
  19. ! > pengwynn is deploying github/master to production pengwynn is

    deploying github/master to lab-one pengwynn is deploying github/master to lab-two pengwynn is deploying github/master to sekret-lab
  20. ! 1

  21. !

  22. !

  23. require "dat/science" ! class MyApp::Widget def allows?(user) experiment = Dat::Science::Experiment.new

    \ "widget-permissions" do |e| ! e.control { old_method } # old way e.candidate { new_method } # new way end ! experiment.run end end
  24. require "dat/science" ! class MyApp::Widget def allows?(user) experiment = Dat::Science::Experiment.new

    \ "widget-permissions" do |e| ! e.control { old_method } # old way e.candidate { new_method } # new way end ! experiment.run end end
  25. require "dat/science" ! class MyApp::Widget def allows?(user) experiment = Dat::Science::Experiment.new

    \ "widget-permissions" do |e| ! e.control { old_method } # old way e.candidate { new_method } # new way end ! experiment.run end end
  26. require "dat/science" ! class MyApp::Widget def allows?(user) experiment = Dat::Science::Experiment.new

    \ "widget-permissions" do |e| ! e.control { old_method } # old way e.candidate { new_method } # new way end ! experiment.run end end
  27. require "dat/science" ! class MyApp::Widget def allows?(user) experiment = Dat::Science::Experiment.new

    \ "widget-permissions" do |e| ! e.control { old_method } # old way e.candidate { new_method } # new way end ! experiment.run end end
  28. require "dat/science" ! class MyApp::Widget def allows?(user) experiment = Dat::Science::Experiment.new

    \ "widget-permissions" do |e| ! e.control { old_method } # old way e.candidate { new_method } # new way end ! experiment.run end end
  29. require "dat/science" ! class MyApp::Widget def allows?(user) science "widget-permissions" do

    |e| e.control { model.check_user(user).valid? } e.candidate { user.can? :read, model } end end end
  30. require "dat/science" ! class MyApp::Widget def allows?(user) science "widget-permissions" do

    |e| e.control { model.check_user(user).valid? } e.candidate { user.can? :read, model } end end end
  31. require "dat/science" ! class Blog::Post def permalink(user) science "permalink" do

    |e| e.control { post[:permalink] } e.candidate { post.slug } e.comparator {|a, b| a.downcase == b.downcase } end end end
  32. require "dat/science" ! class Blog::Post def permalink(user) science "permalink" do

    |e| e.control { post[:permalink] } e.candidate { post.slug } e.comparator {|a, b| a.downcase == b.downcase } end end end
  33. require "dat/science" ! module Myapp class Experiment < Dat::Science::Experiment def

    enabled? rand(100) < 10 # Run 10% of the time end end end
  34. require "dat/science" ! module Myapp class Experiment < Dat::Science::Experiment def

    publish MyApp.instrument "science.#{event}", payload end end end
  35. require "dat/science" ! module Myapp class Experiment < Dat::Science::Experiment def

    publish MyApp.instrument "science.#{event}", payload end end end
  36. require "dat/science" ! class Blog::Post def permalink(user) science "permalink" do

    |e| e.context :post => post e.control { post[:permalink] } e.candidate { post.slug } e.comparator {|a, b| a.downcase == b.downcase } end end end
  37. require "dat/science" ! class Blog::Post def permalink(user) science "permalink" do

    |e| e.context :post => post e.control { post[:permalink] } e.candidate { post.slug } e.comparator {|a, b| a.downcase == b.downcase } end end end
  38. module GitHub class Experiment < Dat::Science::Experiment class << self #

    Public: enable mad science mode: returns the candidate values by default # instead of the control. def mad_science=(val) @mad_science = val end ! # Internal: whether or not to always run the candidate instead of the # control. def candidate_instead_of_control? @mad_science end end … end
  39. module GitHub class Experiment < Dat::Science::Experiment class << self #

    Public: enable mad science mode: returns the candidate values by default # instead of the control. def mad_science=(val) @mad_science = val end ! # Internal: whether or not to always run the candidate instead of the # control. def candidate_instead_of_control? @mad_science end end … end

More Decks by Wynn Netherland

Other Decks in Programming