Slide 1

Slide 1 text

No content

Slide 2

Slide 2 text

WAZZAAAAAAAAA

Slide 3

Slide 3 text

WAZZAAAAAAAAA Corded? CRT?

Slide 4

Slide 4 text

Aaron Patterson @tenderlove

Slide 5

Slide 5 text

AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.

Slide 6

Slide 6 text

Interfaces & Adapters

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

“The Next Twitter”

Slide 9

Slide 9 text

“Disrupting the way you eat toast”

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

☑Adequate Everything. Adequately.

Slide 12

Slide 12 text

“You get what we think you paid for”

Slide 13

Slide 13 text

SEO Optimization

Slide 14

Slide 14 text

First Search Engine

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

Leif Erikson

Slide 19

Slide 19 text

Leif Erikson (Later invented Cell Phones)

Slide 20

Slide 20 text

Google

Slide 21

Slide 21 text

Yahoo!

Slide 22

Slide 22 text

Bing

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

Alexander Searchkeyword

Slide 26

Slide 26 text

Alexander Searchkeyword

Slide 27

Slide 27 text

Doing Client Work.

Slide 28

Slide 28 text

Technical Co-Founding As A Service

Slide 29

Slide 29 text

recruiterspam.com

Slide 30

Slide 30 text

Unfactoring

Slide 31

Slide 31 text

Rails.queue

Slide 32

Slide 32 text

Using the Queue job = MyJob.new Rails.queue << job

Slide 33

Slide 33 text

Consumer Thread.new { while job = Rails.queue.pop job.run end }

Slide 34

Slide 34 text

Problems.

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

“What about exceptions?”

Slide 37

Slide 37 text

“What about exceptions?” “It’s queue specific.”

Slide 38

Slide 38 text

No content

Slide 39

Slide 39 text

“What about serialization?”

Slide 40

Slide 40 text

“What about serialization?” “It’s queue specific.”

Slide 41

Slide 41 text

No content

Slide 42

Slide 42 text

“What about job construction?”

Slide 43

Slide 43 text

“What about job construction?” “It must be marshallable.”

Slide 44

Slide 44 text

Job Construction user = User.find 1 job = Job.new user Rails.queue << job

Slide 45

Slide 45 text

Job Construction user = User.find 1 job = Job.new user Rails.queue << job NOPE

Slide 46

Slide 46 text

Job Construction user = User.find 1 job = Job.new user.id Rails.queue << job

Slide 47

Slide 47 text

Job Definition class Job def initialize(user_id) @user_id = user_id end def run user = User.find @user_id # .... end end

Slide 48

Slide 48 text

Too Many Open Questions.

Slide 49

Slide 49 text

Rails.queue

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

minitest/spec

Slide 52

Slide 52 text

describe "whatever" do setup do # ... end it "does some stuff" do 1.must_equal 1 end describe "some other stuff" do it "does some other stuff" do 'foo'.must_match /foo/ end end end

Slide 53

Slide 53 text

class SomeTest < ActiveSupport::TestCase setup { # ... } test "some thing" do # ... end end Rails Tests

Slide 54

Slide 54 text

MiniTest::Spec class SomeTest < MiniTest::Spec setup { # ... } it "some thing" do # ... end end

Slide 55

Slide 55 text

Refactor class SomeTest < MiniTest::Spec class << self alias :test :it end setup { # ... } test "some thing" do # ... end end

Slide 56

Slide 56 text

AS::TestCase class ActiveSupport::TestCase < MiniTest::Spec class << self alias :test :it end end class SomeTest < ActiveSupport::TestCase setup { # ... } test "some thing" do # ... end end

Slide 57

Slide 57 text

mt/spec superclass > MiniTest::Spec.ancestors => [MiniTest::Spec, MiniTest::Unit::TestCase, ... ]

Slide 58

Slide 58 text

Free goodies! describe "whatever" do it "does some stuff" do 1.must_equal 1 end describe "some other stuff" do it "does some other stuff" do 'foo'.must_match /foo/ end end end

Slide 59

Slide 59 text

minitest/spec

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

Meta-Programming

Slide 62

Slide 62 text

What is it?

Slide 63

Slide 63 text

Code that writes Code

Slide 64

Slide 64 text

Defining Methods

Slide 65

Slide 65 text

attr_accessor class Foo attr_accessor :bar end

Slide 66

Slide 66 text

attr_accessor class Foo def bar; @bar; end def bar=(bar); @bar = bar; end end

Slide 67

Slide 67 text

eval class Foo eval "def bar; :hi; end" end Foo.new.bar # => :hi

Slide 68

Slide 68 text

class_eval class Foo end Foo.eval "def bar; :hi; end" # => error Foo.class_eval "def bar; :hi; end" # => ok! Foo.new.bar # => :hi

Slide 69

Slide 69 text

define_method class Foo define_method(:bar) { :hi } end Foo.new.bar # => :hi

Slide 70

Slide 70 text

eval vs d_m ❤ How code is parsed ❤ Method environment

Slide 71

Slide 71 text

Parser (eval) # test.rb class Foo 10.times { |i| class_eval "def b_#{i}; :hi; end", __FILE__, __LINE__ } end # x.d ruby$target:::parse-begin /copyinstr(arg0) == "test.rb"/ { printf("%s:%d\n", copyinstr(arg0), arg1); } R uby 2.0!

Slide 72

Slide 72 text

DTrace Run $ sudo dtrace -q -s x.d -c'ruby test.rb' test.rb:1 test.rb:3 test.rb:3 test.rb:3 test.rb:3 test.rb:3 test.rb:3 test.rb:3 test.rb:3 test.rb:3 test.rb:3 $

Slide 73

Slide 73 text

Parser (def_m) # test.rb class Foo 10.times { |i| define_method("b_#{i}") { :hi } } end # x.d ruby$target:::parse-begin /copyinstr(arg0) == "test.rb"/ { printf("%s:%d\n", copyinstr(arg0), arg1); } R uby 2.0!

Slide 74

Slide 74 text

DTrace Run $ sudo dtrace -q -s x.d -c'ruby test.rb' test.rb:1 $

Slide 75

Slide 75 text

Environment class Foo hello = "world!" define_method("foo") { hello } class_eval "def bar; hello; end" end x = Foo.new x.foo # => "world!" x.bar # => NameError

Slide 76

Slide 76 text

Definition Speed class Foo if ENV['CLASS_EVAL'] 100_000.times do |i| class_eval("def x_#{i}; end") end else 100_000.times do |i| define_method("x_#{i}") { } end end end

Slide 77

Slide 77 text

$ DEF_METH=1 time -p ruby test.rb real 0.63 user 0.56 sys 0.05 $ CLASS_EVAL=1 time -p ruby test.rb real 3.62 user 3.52 sys 0.09

Slide 78

Slide 78 text

Method Call Speed require 'benchmark/ips' GC.disable class Foo class_eval("def foo; end") define_method("bar") { } end Benchmark.ips do |x| F = Foo.new x.report("define_method") { F.bar } x.report("class_eval") { F.foo } end

Slide 79

Slide 79 text

Calculating ------------------------------------- define_method 100965 i/100ms class_eval 107181 i/100ms ------------------------------------------------- define_method 4801218.4 (±6.3%) i/s - 23928705 in 5.008944s class_eval 7386563.1 (±8.9%) i/s - 36548721 in 5.003122s Iterations / sec

Slide 80

Slide 80 text

Call + Work require 'benchmark/ips' GC.disable class Foo class_eval("def foo; 2.times.map { 'foo' } end") define_method("bar") { 2.times.map { "foo" } } end Benchmark.ips do |x| F = Foo.new x.report("define_method") { F.bar } x.report("class_eval") { F.foo } end

Slide 81

Slide 81 text

Iterations / sec Calculating ------------------------------------- define_method 42364 i/100ms class_eval 44085 i/100ms ------------------------------------------------- define_method 612296.0 (±7.1%) i/s - 3050208 in 5.007636s class_eval 558666.2 (±12.1%) i/s - 2689185 in 5.181042s

Slide 82

Slide 82 text

Memory $ CLASS_EVAL=1 time -l ruby test.rb 3.63 real 3.53 user 0.08 sys 126648320 maximum resident set size 0 average shared memory size 0 average unshared data size 0 average unshared stack size $ DEFN=1 time -l ruby test.rb 0.63 real 0.57 user 0.06 sys 69734400 maximum resident set size 0 average shared memory size 0 average unshared data size 0 average unshared stack size

Slide 83

Slide 83 text

Measure ISeq require 'objspace' N = (ENV['N'] || 100_000).to_i class Foo N.times do |i| if ENV['CLASS_EVAL'] class_eval("def x_#{i}; end") else define_method("x_#{i}") { } end end end GC.start p ObjectSpace.memsize_of_all(RubyVM::InstructionSequence) R uby 1.9.3+

Slide 84

Slide 84 text

Results $ CLASS_EVAL=1 ruby test.rb 38659482 $ DEFN=1 ruby test.rb 259482 $ N=200000 DEFN=1 ruby test.rb 259482

Slide 85

Slide 85 text

define_method

Slide 86

Slide 86 text

define_method ISeq def a1 def a3 def a2

Slide 87

Slide 87 text

class_eval

Slide 88

Slide 88 text

class_eval ISeq def a1 def a3 def a2 ISeq ISeq

Slide 89

Slide 89 text

Closure Leaks class Foo x = "X" * 1024 define_method("x") { } end class Bar x = "X" * 1024 class_eval("def x; end") end

Slide 90

Slide 90 text

Cleaning up a MetaMess

Slide 91

Slide 91 text

BAD Code that writes BAD Code

Slide 92

Slide 92 text

@module.module_eval <<-END_EVAL def #{name}(*args) if #{optimize_helper?(route)} && args.size == #{route.required_parts.size} && !args.last.is_a? (Hash) && optimize_routes_generation? options = #{options.inspect} options.merge!(url_options) if respond_to? (:url_options) options[:path] = "#{optimized_helper(route)}" ActionDispatch::Http::URL.url_for(options) else url_for(handle_positional_args(args, #{options.inspect}, #{route.segment_keys.inspect})) end end END_EVAL

Slide 93

Slide 93 text

@module.module_eval <<-END_EVAL def #{name}(*args) # ... end END_EVAL Creates Methods

Slide 94

Slide 94 text

Conditionals @module.module_eval <<-END_EVAL def #{name}(*args) if #{optimize_helper?(route)} && args.size == #{route.required_parts.size} && ! args.last.is_a?(Hash) && optimize_routes_generation? # ... else # ... end end END_EVAL

Slide 95

Slide 95 text

I heard you like Conditionals

Slide 96

Slide 96 text

Identify Variables

Slide 97

Slide 97 text

Extract Static Data

Slide 98

Slide 98 text

+ def if_#{name}(t, options, path) + options.merge!(url_options) + options[:path] = path + ActionDispatch::Http::URL.url_for(options) + end + def #{name}(*args) if #{optimize_helper?(route)} options = #{options.inspect} - options.merge!(url_options) - options[:path] = "#{optimized_helper(route)}" - ActionDispatch::Http::URL.url_for(options) + if_#{name}(self, options, "#{optimized_helper(route)}") else - url_for(...) + UrlHelp.new.url_else(...)

Slide 99

Slide 99 text

+ def if_#{name}(t, options, path) + options.merge!(url_options) + options[:path] = path + ActionDispatch::Http::URL.url_for(options) + end + def #{name}(*args) if #{optimize_helper?(route)} options = #{options.inspect} - options.merge!(url_options) - options[:path] = "#{optimized_helper(route)}" - ActionDispatch::Http::URL.url_for(options) + if_#{name}(self, options, "#{optimized_helper(route)}") else - url_for(...) + UrlHelp.new.url_else(...)

Slide 100

Slide 100 text

+ def url_if(t, options, path) + options.merge!(t.url_options) if t.respond_to?(:url_options) + options[:path] = path + ActionDispatch::Http::URL.url_for(options) + end + def handle_positional_args(t, args, options, segment_keys) inner_options = args.extract_options! result = options.dup @@ -192,17 +198,10 @@ module ActionDispatch def define_url_helper(route, name, options) @module.remove_possible_method name @module.module_eval <<-END_EVAL, __FILE__, __LINE__ + 1 - - def if_#{name}(t, options, path) - options.merge!(url_options) if t.respond_to?(:url_options) - options[:path] = path - ActionDispatch::Http::URL.url_for(options) - end Remove From Eval eval

Slide 101

Slide 101 text

Create Objects

Slide 102

Slide 102 text

class UrlHelper def self.create(options) new options end def initialize @options = options end def url_else(t, args, seg) # ... end def url_if(t, path) # ... end end

Slide 103

Slide 103 text

@module.module_eval <<-END_EVAL def #{name}(*args) if #{optimize_helper?(route)} # ... options = #{options.inspect} UrlHelp.new.url_if(self, options, "#{optimized_helper(route)}") else UrlHelp.new.url_else(self, args, # ... ) end end END_EVAL

Slide 104

Slide 104 text

Eliminate Conditionals

Slide 105

Slide 105 text

Factory Method class UrlHelper def self.create(route, options) if optimize_helper?(route) OptimizedUrlHelper.new(route, options) else new route, options end end # ... end

Slide 106

Slide 106 text

Final Meta-Code helper = UrlHelper.create(route, options.dup) @module.module_eval do define_method(name) do |*args| helper.call self, args end end

Slide 107

Slide 107 text

Recap Extract Functions Build Objects Eliminate Conditional

Slide 108

Slide 108 text

Avoid a MetaMess

Slide 109

Slide 109 text

When you’ve gone too far.

Slide 110

Slide 110 text

# * :terminator - Determines when a before filter will halt the # callback chain, preventing following callbacks from being called and # the event from being triggered. This is a string to be eval'ed. The # result of the callback is available in the +result+ variable. # # define_callbacks :validate, terminator: 'result == false'

Slide 111

Slide 111 text

This is a string to be eval'ed.

Slide 112

Slide 112 text

THIS PARAMETER IS CRAZY TOWN.

Slide 113

Slide 113 text

Avoid Conditionals

Slide 114

Slide 114 text

Keep It Simple.

Slide 115

Slide 115 text

Mamba Time

Slide 116

Slide 116 text

My Weight

Slide 117

Slide 117 text

Health Walk.

Slide 118

Slide 118 text

Find your Mamba Time

Slide 119

Slide 119 text

Be the Best Mamba Timer

Slide 120

Slide 120 text

Office Hours

Slide 121

Slide 121 text

@gorbypuff

Slide 122

Slide 122 text

Thank You!