SlideShare une entreprise Scribd logo
1  sur  149
Télécharger pour lire hors ligne
Saturday, June 18, 2011
Saturday, June 18, 2011
bitcoin
                               ==
                          con-currency?


Saturday, June 18, 2011
Saturday, June 18, 2011
José!    Me!




Saturday, June 18, 2011
WWFMD?
Saturday, June 18, 2011
Public Service
                          Announcements


Saturday, June 18, 2011
SIGSEGV is bad



Saturday, June 18, 2011
neversaydie



Saturday, June 18, 2011
begin
                  # something dangerous
                rescue NeverSayDie
                  # fix memory
                end




Saturday, June 18, 2011
"Not working in
                          production mode"


Saturday, June 18, 2011
DO NOT USE THIS
                            SOFTWARE


Saturday, June 18, 2011
ruby -w



Saturday, June 18, 2011
def hello
                  x = Object.new   # warning
                  10 + 10
                end




Saturday, June 18, 2011
warning: assigned but unused variable - x




Saturday, June 18, 2011
How deprecation
                   notices SHOULD be
                         written


Saturday, June 18, 2011
class Foo
                  def deprecated
                    if $VERBOSE
                       warn "hey bro, don't call this"
                    end
                    10
                  end
                end




Saturday, June 18, 2011
RSpec Problem



Saturday, June 18, 2011
warning: useless use of == in void context




Saturday, June 18, 2011
it "passes" do
                  10.should == 10
                  11.should == 11
                end




Saturday, June 18, 2011
def check(thing)
                end

                def deprecated
                  check 10.should == 10
                  check 11.should == 10
                end




Saturday, June 18, 2011
@tenderlove



Saturday, June 18, 2011
AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies.
Saturday, June 18, 2011
Ruby Core Team



Saturday, June 18, 2011
Rails Core Team



Saturday, June 18, 2011
Saturday, June 18, 2011
White Guy




Saturday, June 18, 2011
Story about
                          Geethika and
                          pinochle, java, etc




Saturday, June 18, 2011
Story about
                            Geethika and
                            pinochle, java, etc




                          It's TYRA!
Saturday, June 18, 2011
<3 <3 <3

Saturday, June 18, 2011
"Congratulations, you just
                  made us not consider Rails
                 for anything anymore despite
                      our coders liking it."



Saturday, June 18, 2011
SWEDEN!

Saturday, June 18, 2011
IKEA!
Saturday, June 18, 2011
MEATBALLS!
Saturday, June 18, 2011
SWEDISH FISH!
Saturday, June 18, 2011
Made in Canada!
Saturday, June 18, 2011
Made in Canada!
Saturday, June 18, 2011
How do you catch
                           such tiny fish?


Saturday, June 18, 2011
Will you share your
                            Swedish Fish
                            Fishing spot?


Saturday, June 18, 2011
Talk about
                                      Rails,
                                      Talk about
                                      work projects


                          Mountain Dew
                             and my
                          Trail of Tears


Saturday, June 18, 2011
Legacy Code

Saturday, June 18, 2011
What is
                          Legacy Code?


Saturday, June 18, 2011
Untested



Saturday, June 18, 2011
Old



Saturday, June 18, 2011
Maintainers
                                      are gone




                          Not Understood



Saturday, June 18, 2011
Importance of
                           Legacy Code


Saturday, June 18, 2011
Old code contains
                             Knowledge


Saturday, June 18, 2011
Solves Today's
                            Problems


Saturday, June 18, 2011
All Legacy Code is
                               Not Equal


Saturday, June 18, 2011
Tenderlove
                          Tear Formula




Saturday, June 18, 2011
Code Burden
          Tears




                              Time



Saturday, June 18, 2011
Tears cried at time T




Saturday, June 18, 2011
Volume at time T




Saturday, June 18, 2011
Last Week



Saturday, June 18, 2011
I LOVE hacking
                             old code


Saturday, June 18, 2011
Techniques




Saturday, June 18, 2011
Techniques

                            Universal


                             Testing


                            Extending

Saturday, June 18, 2011
Universal



Saturday, June 18, 2011
Liskov substitution
                               principle


Saturday, June 18, 2011
A subclass can be
                          used in place of it's
                             superclass


Saturday, June 18, 2011
Object


                          Animal


                          Person



Saturday, June 18, 2011
class Animal
                end

                class Person < Animal
                end




Saturday, June 18, 2011
def leg_count(animal)
                  animal.legs
                end

                def account_number(person)
                  person.account_number
                end




Saturday, June 18, 2011
Single Responsibility
                       Principal


Saturday, June 18, 2011
Each class has one
                            and only one
                            responsibility


Saturday, June 18, 2011
Each class has one
                           reason to change


Saturday, June 18, 2011
Method Extraction



Saturday, June 18, 2011
class WebClient
                  def get(url)
                    url = URI.parse url
                    Net::HTTP.get(url.host, url.path)
                  end
                end




Saturday, June 18, 2011
class WebClient
                  def get(url)
                    url = URI.parse url
                    http_get
                  end

                  private
                  def http_get
                    Net::HTTP.get(url.host, url.path)
                  end
                end


Saturday, June 18, 2011
I don't like it, but
                                         it helps us to
                class WebClient          reason
                  def get(url)
                    url = URI.parse url
                    http_get(url.host, url.path)
                  end

                  private
                  def http_get(host, path)
                    Net::HTTP.get(host, path)
                  end
                end


Saturday, June 18, 2011
Object#extend



Saturday, June 18, 2011
class Foo
                  def metaclass
                    class << self; self; end
                  end
                end

                x = Foo.new
                p x.metaclass.ancestors

                x.extend(Module.new { })
                p x.metaclass.ancestors


Saturday, June 18, 2011
[Foo, Object, Kernel, BasicObject]


                [#<Module:0x81c98>, Foo, Object, Kernel, BasicObject]




Saturday, June 18, 2011
Code Seams



Saturday, June 18, 2011
Testing



Saturday, June 18, 2011
Load Path Hacking



Saturday, June 18, 2011
$LOAD_PATH


Saturday, June 18, 2011
ruby -Ifoo script.rb



Saturday, June 18, 2011
require 'net/http'

                class WebClient
                  def get(url)
                    url = URI.parse url
                    Net::HTTP.get(url.host, url.path)
                  end
                end




Saturday, June 18, 2011
[aaron@higgins project (master)]$ find .
                .
                ./test
                ./test/lib
                ./test/lib/net
                ./test/lib/net/http.rb
                ./web.rb




Saturday, June 18, 2011
test/lib/net/http.rb

     module Net
       class HTTP
         def self.get(host, path)
           "hello world"
         end
       end
     end


Saturday, June 18, 2011
ruby -I test/lib web.rb




Saturday, June 18, 2011
require 'web'
                require 'minitest/autorun'

                class WebTest < MiniTest::Unit::TestCase
                  def test_get
                    client   = WebClient.new
                    response = client.get 'http://www.reddit.com/r/ruby'
                    assert_equal 'hello world', response
                  end
                end




Saturday, June 18, 2011
RSpec and
             People don't know about -I     test/unit will
                                            set your -I for
                                            you




                          require File.expand_path(
                            File.join('..', 'foo'))




Saturday, June 18, 2011
Heavy Handed



Saturday, June 18, 2011
Good for Small APIs



Saturday, June 18, 2011
Constant Hacking



Saturday, June 18, 2011
require 'net/http'

                class WebClient
                  def get(url)
                    url = URI.parse url
                    Net::HTTP.get(url.host, url.path)
                  end
                end




Saturday, June 18, 2011
class MyHTTP
                  def self.get(host, path)
                    "hello world"
                  end
                end

                WebClient.const_set(:Net, Module.new)
                WebClient::Net.const_set(:HTTP, MyHTTP)




Saturday, June 18, 2011
class WebTest < MiniTest::Unit::TestCase
             def setup
               WebClient.const_set(:Net, Module.new)
               WebClient::Net.const_set(:HTTP, MyHTTP)
             end

                def teardown
                  WebClient.send(:remove_const, :Net)
                end

             def test_get
               client   = WebClient.new
               response = client.get 'http://www.reddit.com/r/ruby'
               assert_equal 'hello world', response
             end
           end



Saturday, June 18, 2011
class WebClient
                  def get(url)
                    url = URI.parse url
                    ::Net::HTTP.get(url.host, url.path)
                  end
                end




Saturday, June 18, 2011
Localized
                          Still must    changes to
                          mock          one class
                          entire API




                              Heavy Handed



Saturday, June 18, 2011
Subclass Testing



Saturday, June 18, 2011
class WebClient
                  def get(url)
                    url = URI.parse url
                    Net::HTTP.get(url.host, url.path)
                  end
                end




Saturday, June 18, 2011
require 'net/http'

                class WebClient
                  def get(url)
                    url = URI.parse url
                    http_get(url.host, url.path)
                  end

                  private
                  def http_get(host, path)
                    Net::HTTP.get(host, path)
                  end
                end


Saturday, June 18, 2011
Class.new



Saturday, June 18, 2011
class WebTest < MiniTest::Unit::TestCase
             def test_get
               client   = Class.new(WebClient) {
                 def http_get(host, path)
                   'hello world'
                 end
               }.new

               response = client.get 'http://www.reddit.com/r/ruby'
               assert_equal 'hello world', response
             end
           end




Saturday, June 18, 2011
Annoying
                          Constructors


Saturday, June 18, 2011
Many
                                                                 parameters,
                class Column
                  def initialize(name, default, sql_type = nil,don't care=about
                                                                 null      true)
                                                               some of them
                    @name      = name
                    @sql_type = sql_type
                    @null      = null
                    @limit     = extract_limit(sql_type)
                    @precision = extract_precision(sql_type)
                    @scale     = extract_scale(sql_type)
                    @type      = simplified_type(sql_type)
                    @default   = extract_default(default)
                    @primary   = nil
                    @coder     = nil
                  end
                  ....
                end




Saturday, June 18, 2011
Just Pass nil



Saturday, June 18, 2011
def test_type_cast_true
                  c = Column.new(nil, 1, 'int')

                  assert_equal 't', @conn.type_cast(true, nil)
                  assert_equal 1, @conn.type_cast(true, c)
                end




Saturday, June 18, 2011
Can't construct,
                                       but want to
                                       break
                                       dependencies




                          Not Constructible



Saturday, June 18, 2011
Too hard to
                                                construct




                pool = ActiveRecord::Base.connection_pool




Saturday, June 18, 2011
pool = ActiveRecord::Base.connection_pool.dup

                pool.extend(Module.new {
                   def checkin conn
                     @checkins << conn
                     conn.object_id
                   end
                })




Saturday, June 18, 2011
Detecting Changes



Saturday, June 18, 2011
Measure http_get
     class WebClient
       def get(url)
         url = URI.parse url
         http_get(url.host, url.path)
       end

       private
       def http_get(host, path)
         Net::HTTP.get(host, path)
       end
     end
Saturday, June 18, 2011
via Class.new



Saturday, June 18, 2011
def test_http_get_count
                  call_count = 0
                  client = Class.new(WebClient) {
                    define_method(:http_get) { |host, path|
                      call_count += 1
                      "hello world"
                    }
                  }.new

                  assert_equal 0, call_count
                  client.get 'http://www.reddit.com/r/ruby'
                  assert_equal 1, call_count
                end


Saturday, June 18, 2011
def test_http_get_count
                  call_count = 0
                  client = Class.new(WebClient) {
                    define_method(:http_get) { |host, path|
                      call_count += 1
                      "hello world"
                    }
                  }.new

                  assert_equal 0, call_count
                  client.get 'http://www.reddit.com/r/ruby'
                  assert_equal 1, call_count
                end


Saturday, June 18, 2011
Decide to call
                def test_http_get_count          super or not
                  call_count = 0
                  client = Class.new(WebClient) {
                    define_method(:http_get) { |host, path|
                      call_count += 1
                      "hello world"
                    }
                  }.new

                  assert_equal 0, call_count
                  client.get 'http://www.reddit.com/r/ruby'
                  assert_equal 1, call_count
                end


Saturday, June 18, 2011
via Module.new



Saturday, June 18, 2011
def test_http_get_count
                  client = WebClient.new

                      call_count = 0
                      client.extend(Module.new {
                         define_method(:http_get) { |host, path|
                           call_count += 1
                           "hello world"
                         }
                      })

                  assert_equal 0, call_count
                  client.get 'http://www.reddit.com/r/ruby'
                  assert_equal 1, call_count
                end


Saturday, June 18, 2011
def test_http_get_count
                  client = WebClient.new

                      call_count = 0
                      client.extend(Module.new {
                         define_method(:http_get) { |host, path|
                           call_count += 1
                           "hello world"
                         }
                      })

                  assert_equal 0, call_count
                  client.get 'http://www.reddit.com/r/ruby'
                  assert_equal 1, call_count
                end


Saturday, June 18, 2011
def test_http_get_count
                  client = WebClient.new

                      call_count = 0
                      client.extend(Module.new {
                         define_method(:http_get) { |host, path|
                           call_count += 1
                           "hello world"
                         }
                      })

                  assert_equal 0, call_count
                  client.get 'http://www.reddit.com/r/ruby'
                  assert_equal 1, call_count
                end


Saturday, June 18, 2011
Extending



Saturday, June 18, 2011
Huge Methods!



Saturday, June 18, 2011
def table_rows
                  rows[table_name] = fixtures.map do |label, fixture|
                     if model_class && model_class < ActiveRecord::Base
                       reflection_class.reflect_on_all_associations.each do |association|
                         case association.macro
                         when :belongs_to
                           # Do not replace association name with association foreign key if they are named the
                same
                           fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s

                          if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
                            if association.options[:polymorphic] && value.sub!(/s*(([^)]*))s*$/, "")
                              # support polymorphic belongs_to as "label (Type)"
                              row[association.foreign_type] = $1
                            end

                             row[fk_name] = ActiveRecord::Fixtures.identify(value)
                           end
                         when :has_and_belongs_to_many
                           if (targets = row.delete(association.name.to_s))
                             targets = targets.is_a?(Array) ? targets : targets.split(/s*,s*/)
                             table_name = association.options[:join_table]
                             rows[table_name].concat targets.map { |target|
                               { association.foreign_key             => row[primary_key_name],
                                 association.association_foreign_key => ActiveRecord::Fixtures.identify
                (target) }
                             }
                           end
                         end
                       end
                    end
                    row
                  end
                  rows
                end


Saturday, June 18, 2011
Extract Methods



Saturday, June 18, 2011
def belongs_to_row(association, row)
                  # Do not replace association name with association foreign key if
                they are named the same
                  fk_name = (association.options[:foreign_key] || "#
                {association.name}_id").to_s

                  if association.name.to_s != fk_name && value = row.delete
                (association.name.to_s)
                    if association.options[:polymorphic] && value.sub!(/s*(([^)]
                *))s*$/, "")
                      # support polymorphic belongs_to as "label (Type)"
                      row[association.foreign_type] = $1
                    end

                          row[fk_name] = ActiveRecord::Fixtures.identify(value)
                end




Saturday, June 18, 2011
def habtm_row(association, row)
                  if (targets = row.delete(association.name.to_s))
                    targets = targets.is_a?(Array) ? targets : targets.split(/s*,
                s*/)
                    table_name = association.options[:join_table]
                    rows[table_name].concat targets.map { |target|
                      { association.foreign_key             => row
                [primary_key_name],
                        association.association_foreign_key =>
                ActiveRecord::Fixtures.identify(target) }
                    }
                  end
                end




Saturday, June 18, 2011
def table_rows
                  rows[table_name] = fixtures.map do |label, fixture|
                    row = fixture.to_hash

                          if model_class && model_class < ActiveRecord::Base

                            # If STI is used, find the correct subclass for association reflection
                            reflection_class =
                              if row.include?(inheritance_column_name)
                                row[inheritance_column_name].constantize rescue model_class
                              else
                                model_class
                              end

                            reflection_class.reflect_on_all_associations.each do |association|
                              case association.macro
                              when :belongs_to
                                belongs_to_row(association, row)
                              when :has_and_belongs_to_many
                                habtm_row(association, row)
                              end
                            end
                          end

                    row
                  end
                  rows
                end




Saturday, June 18, 2011
Extract Object



Saturday, June 18, 2011
class RowFilter
                  def rows
                    fixtures.map do |label, fixture|
                      row = fixture.to_hash
                      if model_class && model_class < ActiveRecord::Base
                        # If STI is used, find the correct subclass for association reflection
                        reflection_class =
                           if row.include?(inheritance_column_name)
                             row[inheritance_column_name].constantize rescue model_class
                           else
                             model_class
                           end

                        reflection_class.reflect_on_all_associations.each do |association|
                          case association.macro
                          when :belongs_to
                            belongs_to_row(association, row)
                          when :has_and_belongs_to_many
                            habtm_row(association, row)
                          end
                        end
                      end
                      row
                    end
                  end
                end




Saturday, June 18, 2011
class RowFilter
                  attr_reader :fixtures, :model_class

                  def initialize(fixtures, model_class)
                    @fixtures = fixtures
                    @model_class = model_class
                  end
                end




Saturday, June 18, 2011
def table_rows
                  filter = RowFilter.new(fixtures, model_class)
                  rows[table_name] = filter.rows
                  rows
                end




Saturday, June 18, 2011
Huge Classes!



Saturday, June 18, 2011
Look at Method
                              Names


Saturday, June 18, 2011
Look at shared
                          instance variables


Saturday, June 18, 2011
Group Similar
                            Methods


Saturday, June 18, 2011
Use SRP to create a
                       new class


Saturday, June 18, 2011
Then Delegate.



Saturday, June 18, 2011
All API calls



Saturday, June 18, 2011
Once we had
                                           extracted the HTTP
                class WebClient            methods to their
                                           own functions, could
                  def get(url)             reason about HTTP
                    url = URI.parse url    api.
                    http_get(url.host, url.path)
                  end

                  private
                  def http_get(host, path)
                    Net::HTTP.get(host, path)
                  end
                end


Saturday, June 18, 2011
class WebClient
                  def initialize(client = Net::HTTP)
                    @client = client
                  end

                      def get(url)
                        url = URI.parse url
                        http_get(url.host, url.path)
                      end

                  private
                  def http_get(host, path)
                    @client.get(host, path)
                  end
                end


Saturday, June 18, 2011
class TestHTTP < Struct.new(:data)
                  def get(host, path)
                    data[[host, path]]
                  end
                end




Saturday, June 18, 2011
class WebTest < Test::Unit::TestCase
                  def test_get_home
                    mockhttp = TestHTTP.new({
                       ['localhost', '/~aaron/'] => 'hello'
                    })
                    wc = WebClient.new mockhttp
                    assert_equal 'hello',
                       wc.get('http://localhost/~aaron/')
                  end
                end




Saturday, June 18, 2011
We define
                          expectations


Saturday, June 18, 2011
Not Bound to HTTP



Saturday, June 18, 2011
Legacy code can
                            make you cry


Saturday, June 18, 2011
But it doesn't have to



Saturday, June 18, 2011
Don't be afraid!



Saturday, June 18, 2011
Ruby is your
                 mocking framework


Saturday, June 18, 2011
Credits & More Info




Saturday, June 18, 2011
Open Questions?



Saturday, June 18, 2011
Do you like
                  mocking / stubbing?


Saturday, June 18, 2011
How do these testing
                 tools impact your API?



Saturday, June 18, 2011
Do you like hearts?



Saturday, June 18, 2011
How about kittens?



Saturday, June 18, 2011
<3 <3 <3

Saturday, June 18, 2011

Contenu connexe

Similaire à Nordic Ruby 2011

RailsConf Keynote - History of Ruby
RailsConf Keynote - History of RubyRailsConf Keynote - History of Ruby
RailsConf Keynote - History of RubyDr Nic Williams
 
Cornell Food Executives - Rebecca Ryan Presentation
Cornell Food Executives - Rebecca Ryan PresentationCornell Food Executives - Rebecca Ryan Presentation
Cornell Food Executives - Rebecca Ryan PresentationRebecca Ryan
 
OmniAuth: From the Ground Up (RailsConf 2011)
OmniAuth: From the Ground Up (RailsConf 2011)OmniAuth: From the Ground Up (RailsConf 2011)
OmniAuth: From the Ground Up (RailsConf 2011)Michael Bleigh
 
Social media technique and Social Activism
Social media technique and Social ActivismSocial media technique and Social Activism
Social media technique and Social ActivismPatchara Kerdsiri
 
American Fraternal Alliance -- Keynote & Breakout
American Fraternal Alliance -- Keynote & BreakoutAmerican Fraternal Alliance -- Keynote & Breakout
American Fraternal Alliance -- Keynote & BreakoutNametag Scott Ginsberg
 
Rubyを持て、世界に出よう
Rubyを持て、世界に出ようRubyを持て、世界に出よう
Rubyを持て、世界に出ようHiro Asari
 
ShowNearby Client Pitch (Wunderman)
ShowNearby Client Pitch (Wunderman)ShowNearby Client Pitch (Wunderman)
ShowNearby Client Pitch (Wunderman)HEINEKEN
 

Similaire à Nordic Ruby 2011 (14)

Julian ios slides
Julian ios slidesJulian ios slides
Julian ios slides
 
RailsConf Keynote - History of Ruby
RailsConf Keynote - History of RubyRailsConf Keynote - History of Ruby
RailsConf Keynote - History of Ruby
 
RailsConf 2011 Keynote
RailsConf 2011 KeynoteRailsConf 2011 Keynote
RailsConf 2011 Keynote
 
Commands
CommandsCommands
Commands
 
Bitcoin for Noobs
Bitcoin for NoobsBitcoin for Noobs
Bitcoin for Noobs
 
Cornell Food Executives - Rebecca Ryan Presentation
Cornell Food Executives - Rebecca Ryan PresentationCornell Food Executives - Rebecca Ryan Presentation
Cornell Food Executives - Rebecca Ryan Presentation
 
OmniAuth: From the Ground Up (RailsConf 2011)
OmniAuth: From the Ground Up (RailsConf 2011)OmniAuth: From the Ground Up (RailsConf 2011)
OmniAuth: From the Ground Up (RailsConf 2011)
 
layering theme
layering themelayering theme
layering theme
 
Social media technique and Social Activism
Social media technique and Social ActivismSocial media technique and Social Activism
Social media technique and Social Activism
 
American Fraternal Alliance -- Keynote & Breakout
American Fraternal Alliance -- Keynote & BreakoutAmerican Fraternal Alliance -- Keynote & Breakout
American Fraternal Alliance -- Keynote & Breakout
 
Web Operations Career
Web Operations CareerWeb Operations Career
Web Operations Career
 
Rubyを持て、世界に出よう
Rubyを持て、世界に出ようRubyを持て、世界に出よう
Rubyを持て、世界に出よう
 
ShowNearby Client Pitch (Wunderman)
ShowNearby Client Pitch (Wunderman)ShowNearby Client Pitch (Wunderman)
ShowNearby Client Pitch (Wunderman)
 
HiRoshima.R #1 1-2
HiRoshima.R #1 1-2HiRoshima.R #1 1-2
HiRoshima.R #1 1-2
 

Dernier

WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure servicePooja Nehwal
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Alan Dix
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Drew Madelung
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxOnBoard
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitecturePixlogix Infotech
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024Scott Keck-Warren
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slidevu2urc
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhisoniya singh
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationRidwan Fadjar
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slidespraypatel2
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsEnterprise Knowledge
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...shyamraj55
 

Dernier (20)

WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure serviceWhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
WhatsApp 9892124323 ✓Call Girls In Kalyan ( Mumbai ) secure service
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...Swan(sea) Song – personal research during my six years at Swansea ... and bey...
Swan(sea) Song – personal research during my six years at Swansea ... and bey...
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Maximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptxMaximizing Board Effectiveness 2024 Webinar.pptx
Maximizing Board Effectiveness 2024 Webinar.pptx
 
Understanding the Laravel MVC Architecture
Understanding the Laravel MVC ArchitectureUnderstanding the Laravel MVC Architecture
Understanding the Laravel MVC Architecture
 
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
#StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024SQL Database Design For Developers at php[tek] 2024
SQL Database Design For Developers at php[tek] 2024
 
Histor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slideHistor y of HAM Radio presentation slide
Histor y of HAM Radio presentation slide
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | DelhiFULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
FULL ENJOY 🔝 8264348440 🔝 Call Girls in Diplomatic Enclave | Delhi
 
My Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 PresentationMy Hashitalk Indonesia April 2024 Presentation
My Hashitalk Indonesia April 2024 Presentation
 
Slack Application Development 101 Slides
Slack Application Development 101 SlidesSlack Application Development 101 Slides
Slack Application Development 101 Slides
 
IAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI SolutionsIAC 2024 - IA Fast Track to Search Focused AI Solutions
IAC 2024 - IA Fast Track to Search Focused AI Solutions
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
Automating Business Process via MuleSoft Composer | Bangalore MuleSoft Meetup...
 

Nordic Ruby 2011

  • 3. bitcoin == con-currency? Saturday, June 18, 2011
  • 5. José! Me! Saturday, June 18, 2011
  • 7. Public Service Announcements Saturday, June 18, 2011
  • 8. SIGSEGV is bad Saturday, June 18, 2011
  • 10. begin # something dangerous rescue NeverSayDie # fix memory end Saturday, June 18, 2011
  • 11. "Not working in production mode" Saturday, June 18, 2011
  • 12. DO NOT USE THIS SOFTWARE Saturday, June 18, 2011
  • 14. def hello x = Object.new # warning 10 + 10 end Saturday, June 18, 2011
  • 15. warning: assigned but unused variable - x Saturday, June 18, 2011
  • 16. How deprecation notices SHOULD be written Saturday, June 18, 2011
  • 17. class Foo def deprecated if $VERBOSE warn "hey bro, don't call this" end 10 end end Saturday, June 18, 2011
  • 19. warning: useless use of == in void context Saturday, June 18, 2011
  • 20. it "passes" do 10.should == 10 11.should == 11 end Saturday, June 18, 2011
  • 21. def check(thing) end def deprecated check 10.should == 10 check 11.should == 10 end Saturday, June 18, 2011
  • 23. AT&T, AT&T logo and all AT&T related marks are trademarks of AT&T Intellectual Property and/or AT&T affiliated companies. Saturday, June 18, 2011
  • 24. Ruby Core Team Saturday, June 18, 2011
  • 25. Rails Core Team Saturday, June 18, 2011
  • 28. Story about Geethika and pinochle, java, etc Saturday, June 18, 2011
  • 29. Story about Geethika and pinochle, java, etc It's TYRA! Saturday, June 18, 2011
  • 30. <3 <3 <3 Saturday, June 18, 2011
  • 31. "Congratulations, you just made us not consider Rails for anything anymore despite our coders liking it." Saturday, June 18, 2011
  • 36. Made in Canada! Saturday, June 18, 2011
  • 37. Made in Canada! Saturday, June 18, 2011
  • 38. How do you catch such tiny fish? Saturday, June 18, 2011
  • 39. Will you share your Swedish Fish Fishing spot? Saturday, June 18, 2011
  • 40. Talk about Rails, Talk about work projects Mountain Dew and my Trail of Tears Saturday, June 18, 2011
  • 42. What is Legacy Code? Saturday, June 18, 2011
  • 45. Maintainers are gone Not Understood Saturday, June 18, 2011
  • 46. Importance of Legacy Code Saturday, June 18, 2011
  • 47. Old code contains Knowledge Saturday, June 18, 2011
  • 48. Solves Today's Problems Saturday, June 18, 2011
  • 49. All Legacy Code is Not Equal Saturday, June 18, 2011
  • 50. Tenderlove Tear Formula Saturday, June 18, 2011
  • 51. Code Burden Tears Time Saturday, June 18, 2011
  • 52. Tears cried at time T Saturday, June 18, 2011
  • 53. Volume at time T Saturday, June 18, 2011
  • 55. I LOVE hacking old code Saturday, June 18, 2011
  • 57. Techniques Universal Testing Extending Saturday, June 18, 2011
  • 59. Liskov substitution principle Saturday, June 18, 2011
  • 60. A subclass can be used in place of it's superclass Saturday, June 18, 2011
  • 61. Object Animal Person Saturday, June 18, 2011
  • 62. class Animal end class Person < Animal end Saturday, June 18, 2011
  • 63. def leg_count(animal) animal.legs end def account_number(person) person.account_number end Saturday, June 18, 2011
  • 64. Single Responsibility Principal Saturday, June 18, 2011
  • 65. Each class has one and only one responsibility Saturday, June 18, 2011
  • 66. Each class has one reason to change Saturday, June 18, 2011
  • 68. class WebClient def get(url) url = URI.parse url Net::HTTP.get(url.host, url.path) end end Saturday, June 18, 2011
  • 69. class WebClient def get(url) url = URI.parse url http_get end private def http_get Net::HTTP.get(url.host, url.path) end end Saturday, June 18, 2011
  • 70. I don't like it, but it helps us to class WebClient reason def get(url) url = URI.parse url http_get(url.host, url.path) end private def http_get(host, path) Net::HTTP.get(host, path) end end Saturday, June 18, 2011
  • 72. class Foo def metaclass class << self; self; end end end x = Foo.new p x.metaclass.ancestors x.extend(Module.new { }) p x.metaclass.ancestors Saturday, June 18, 2011
  • 73. [Foo, Object, Kernel, BasicObject] [#<Module:0x81c98>, Foo, Object, Kernel, BasicObject] Saturday, June 18, 2011
  • 79. require 'net/http' class WebClient def get(url) url = URI.parse url Net::HTTP.get(url.host, url.path) end end Saturday, June 18, 2011
  • 80. [aaron@higgins project (master)]$ find . . ./test ./test/lib ./test/lib/net ./test/lib/net/http.rb ./web.rb Saturday, June 18, 2011
  • 81. test/lib/net/http.rb module Net class HTTP def self.get(host, path) "hello world" end end end Saturday, June 18, 2011
  • 82. ruby -I test/lib web.rb Saturday, June 18, 2011
  • 83. require 'web' require 'minitest/autorun' class WebTest < MiniTest::Unit::TestCase def test_get client = WebClient.new response = client.get 'http://www.reddit.com/r/ruby' assert_equal 'hello world', response end end Saturday, June 18, 2011
  • 84. RSpec and People don't know about -I test/unit will set your -I for you require File.expand_path( File.join('..', 'foo')) Saturday, June 18, 2011
  • 86. Good for Small APIs Saturday, June 18, 2011
  • 88. require 'net/http' class WebClient def get(url) url = URI.parse url Net::HTTP.get(url.host, url.path) end end Saturday, June 18, 2011
  • 89. class MyHTTP def self.get(host, path) "hello world" end end WebClient.const_set(:Net, Module.new) WebClient::Net.const_set(:HTTP, MyHTTP) Saturday, June 18, 2011
  • 90. class WebTest < MiniTest::Unit::TestCase def setup WebClient.const_set(:Net, Module.new) WebClient::Net.const_set(:HTTP, MyHTTP) end def teardown WebClient.send(:remove_const, :Net) end def test_get client = WebClient.new response = client.get 'http://www.reddit.com/r/ruby' assert_equal 'hello world', response end end Saturday, June 18, 2011
  • 91. class WebClient def get(url) url = URI.parse url ::Net::HTTP.get(url.host, url.path) end end Saturday, June 18, 2011
  • 92. Localized Still must changes to mock one class entire API Heavy Handed Saturday, June 18, 2011
  • 94. class WebClient def get(url) url = URI.parse url Net::HTTP.get(url.host, url.path) end end Saturday, June 18, 2011
  • 95. require 'net/http' class WebClient def get(url) url = URI.parse url http_get(url.host, url.path) end private def http_get(host, path) Net::HTTP.get(host, path) end end Saturday, June 18, 2011
  • 97. class WebTest < MiniTest::Unit::TestCase def test_get client = Class.new(WebClient) { def http_get(host, path) 'hello world' end }.new response = client.get 'http://www.reddit.com/r/ruby' assert_equal 'hello world', response end end Saturday, June 18, 2011
  • 98. Annoying Constructors Saturday, June 18, 2011
  • 99. Many parameters, class Column def initialize(name, default, sql_type = nil,don't care=about null true) some of them @name = name @sql_type = sql_type @null = null @limit = extract_limit(sql_type) @precision = extract_precision(sql_type) @scale = extract_scale(sql_type) @type = simplified_type(sql_type) @default = extract_default(default) @primary = nil @coder = nil end .... end Saturday, June 18, 2011
  • 100. Just Pass nil Saturday, June 18, 2011
  • 101. def test_type_cast_true c = Column.new(nil, 1, 'int') assert_equal 't', @conn.type_cast(true, nil) assert_equal 1, @conn.type_cast(true, c) end Saturday, June 18, 2011
  • 102. Can't construct, but want to break dependencies Not Constructible Saturday, June 18, 2011
  • 103. Too hard to construct pool = ActiveRecord::Base.connection_pool Saturday, June 18, 2011
  • 104. pool = ActiveRecord::Base.connection_pool.dup pool.extend(Module.new { def checkin conn @checkins << conn conn.object_id end }) Saturday, June 18, 2011
  • 106. Measure http_get class WebClient def get(url) url = URI.parse url http_get(url.host, url.path) end private def http_get(host, path) Net::HTTP.get(host, path) end end Saturday, June 18, 2011
  • 108. def test_http_get_count call_count = 0 client = Class.new(WebClient) { define_method(:http_get) { |host, path| call_count += 1 "hello world" } }.new assert_equal 0, call_count client.get 'http://www.reddit.com/r/ruby' assert_equal 1, call_count end Saturday, June 18, 2011
  • 109. def test_http_get_count call_count = 0 client = Class.new(WebClient) { define_method(:http_get) { |host, path| call_count += 1 "hello world" } }.new assert_equal 0, call_count client.get 'http://www.reddit.com/r/ruby' assert_equal 1, call_count end Saturday, June 18, 2011
  • 110. Decide to call def test_http_get_count super or not call_count = 0 client = Class.new(WebClient) { define_method(:http_get) { |host, path| call_count += 1 "hello world" } }.new assert_equal 0, call_count client.get 'http://www.reddit.com/r/ruby' assert_equal 1, call_count end Saturday, June 18, 2011
  • 112. def test_http_get_count client = WebClient.new call_count = 0 client.extend(Module.new { define_method(:http_get) { |host, path| call_count += 1 "hello world" } }) assert_equal 0, call_count client.get 'http://www.reddit.com/r/ruby' assert_equal 1, call_count end Saturday, June 18, 2011
  • 113. def test_http_get_count client = WebClient.new call_count = 0 client.extend(Module.new { define_method(:http_get) { |host, path| call_count += 1 "hello world" } }) assert_equal 0, call_count client.get 'http://www.reddit.com/r/ruby' assert_equal 1, call_count end Saturday, June 18, 2011
  • 114. def test_http_get_count client = WebClient.new call_count = 0 client.extend(Module.new { define_method(:http_get) { |host, path| call_count += 1 "hello world" } }) assert_equal 0, call_count client.get 'http://www.reddit.com/r/ruby' assert_equal 1, call_count end Saturday, June 18, 2011
  • 117. def table_rows rows[table_name] = fixtures.map do |label, fixture| if model_class && model_class < ActiveRecord::Base reflection_class.reflect_on_all_associations.each do |association| case association.macro when :belongs_to # Do not replace association name with association foreign key if they are named the same fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s if association.name.to_s != fk_name && value = row.delete(association.name.to_s) if association.options[:polymorphic] && value.sub!(/s*(([^)]*))s*$/, "") # support polymorphic belongs_to as "label (Type)" row[association.foreign_type] = $1 end row[fk_name] = ActiveRecord::Fixtures.identify(value) end when :has_and_belongs_to_many if (targets = row.delete(association.name.to_s)) targets = targets.is_a?(Array) ? targets : targets.split(/s*,s*/) table_name = association.options[:join_table] rows[table_name].concat targets.map { |target| { association.foreign_key => row[primary_key_name], association.association_foreign_key => ActiveRecord::Fixtures.identify (target) } } end end end end row end rows end Saturday, June 18, 2011
  • 119. def belongs_to_row(association, row) # Do not replace association name with association foreign key if they are named the same fk_name = (association.options[:foreign_key] || "# {association.name}_id").to_s if association.name.to_s != fk_name && value = row.delete (association.name.to_s) if association.options[:polymorphic] && value.sub!(/s*(([^)] *))s*$/, "") # support polymorphic belongs_to as "label (Type)" row[association.foreign_type] = $1 end row[fk_name] = ActiveRecord::Fixtures.identify(value) end Saturday, June 18, 2011
  • 120. def habtm_row(association, row) if (targets = row.delete(association.name.to_s)) targets = targets.is_a?(Array) ? targets : targets.split(/s*, s*/) table_name = association.options[:join_table] rows[table_name].concat targets.map { |target| { association.foreign_key => row [primary_key_name], association.association_foreign_key => ActiveRecord::Fixtures.identify(target) } } end end Saturday, June 18, 2011
  • 121. def table_rows rows[table_name] = fixtures.map do |label, fixture| row = fixture.to_hash if model_class && model_class < ActiveRecord::Base # If STI is used, find the correct subclass for association reflection reflection_class = if row.include?(inheritance_column_name) row[inheritance_column_name].constantize rescue model_class else model_class end reflection_class.reflect_on_all_associations.each do |association| case association.macro when :belongs_to belongs_to_row(association, row) when :has_and_belongs_to_many habtm_row(association, row) end end end row end rows end Saturday, June 18, 2011
  • 123. class RowFilter def rows fixtures.map do |label, fixture| row = fixture.to_hash if model_class && model_class < ActiveRecord::Base # If STI is used, find the correct subclass for association reflection reflection_class = if row.include?(inheritance_column_name) row[inheritance_column_name].constantize rescue model_class else model_class end reflection_class.reflect_on_all_associations.each do |association| case association.macro when :belongs_to belongs_to_row(association, row) when :has_and_belongs_to_many habtm_row(association, row) end end end row end end end Saturday, June 18, 2011
  • 124. class RowFilter attr_reader :fixtures, :model_class def initialize(fixtures, model_class) @fixtures = fixtures @model_class = model_class end end Saturday, June 18, 2011
  • 125. def table_rows filter = RowFilter.new(fixtures, model_class) rows[table_name] = filter.rows rows end Saturday, June 18, 2011
  • 127. Look at Method Names Saturday, June 18, 2011
  • 128. Look at shared instance variables Saturday, June 18, 2011
  • 129. Group Similar Methods Saturday, June 18, 2011
  • 130. Use SRP to create a new class Saturday, June 18, 2011
  • 132. All API calls Saturday, June 18, 2011
  • 133. Once we had extracted the HTTP class WebClient methods to their own functions, could def get(url) reason about HTTP url = URI.parse url api. http_get(url.host, url.path) end private def http_get(host, path) Net::HTTP.get(host, path) end end Saturday, June 18, 2011
  • 134. class WebClient def initialize(client = Net::HTTP) @client = client end def get(url) url = URI.parse url http_get(url.host, url.path) end private def http_get(host, path) @client.get(host, path) end end Saturday, June 18, 2011
  • 135. class TestHTTP < Struct.new(:data) def get(host, path) data[[host, path]] end end Saturday, June 18, 2011
  • 136. class WebTest < Test::Unit::TestCase def test_get_home mockhttp = TestHTTP.new({ ['localhost', '/~aaron/'] => 'hello' }) wc = WebClient.new mockhttp assert_equal 'hello', wc.get('http://localhost/~aaron/') end end Saturday, June 18, 2011
  • 137. We define expectations Saturday, June 18, 2011
  • 138. Not Bound to HTTP Saturday, June 18, 2011
  • 139. Legacy code can make you cry Saturday, June 18, 2011
  • 140. But it doesn't have to Saturday, June 18, 2011
  • 141. Don't be afraid! Saturday, June 18, 2011
  • 142. Ruby is your mocking framework Saturday, June 18, 2011
  • 143. Credits & More Info Saturday, June 18, 2011
  • 145. Do you like mocking / stubbing? Saturday, June 18, 2011
  • 146. How do these testing tools impact your API? Saturday, June 18, 2011
  • 147. Do you like hearts? Saturday, June 18, 2011
  • 149. <3 <3 <3 Saturday, June 18, 2011