$30 off During Our Annual Pro Sale. View Details »

Wow Code, Such Read! (RubyConf Colombia)

Katherine Wu
September 03, 2016

Wow Code, Such Read! (RubyConf Colombia)

Abstract:
When we learn to code, that usually means learning how to *write* code. However in practice, we spend a lot of time *reading* code instead! It’s the way we find answers to questions about how things work. Reading code efficiently is therefore a very valuable skill. This talk will cover how Ruby developers can improve this skill, with tips for comprehending and debugging code faster. We'll also take a look at how you’d go one level deeper and read Ruby’s own source code, even if you don’t know much about C!

This talk was presented at RubyConf Colombia 2016 in Medellín, ~32 minutes: https://youtu.be/u2VrYZDh-4g
Blog post: http://kwugirl.blogspot.com/2016/05/wow-code-such-read.html

Katherine Wu

September 03, 2016
Tweet

More Decks by Katherine Wu

Other Decks in Programming

Transcript

  1. @kwugirl
    Wow Code, Such Read!
    KWu
    Ruby Agent Engineer
    amaze
    understand
    so power

    View Slide

  2. @kwugirl
    the goal:
    get better at
    reading code

    View Slide

  3. be fearless
    in diving into
    code you don’t know
    Edmond Lau
    theeffectiveengineer.com

    View Slide

  4. @kwugirl

    View Slide

  5. @kwugirl
    10.000 hours

    View Slide

  6. @kwugirl
    10.000 hours
    250 weeks

    View Slide

  7. @kwugirl
    10.000 hours
    250 weeks
    ~5 years!

    View Slide

  8. @kwugirl
    productive struggling

    View Slide

  9. @kwugirl
    code archaeology
    https://www.flickr.com/photos/22134952@N04/2850397739

    View Slide

  10. @kwugirl
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  11. @kwugirl
    the problem

    View Slide

  12. @kwugirl
    the problem
    connection.execute("EXPLAIN #{query}")

    View Slide

  13. @kwugirl
    the problem
    connection.execute("EXPLAIN #{query}")
    SELECT "blogs".* FROM "blogs" WHERE
    "blogs"."id" = $1 LIMIT 1
    with

    View Slide

  14. @kwugirl
    the problem
    connection.execute("EXPLAIN #{query}")
    SELECT "blogs".* FROM "blogs" WHERE
    "blogs"."id" = $1 LIMIT 1
    with

    View Slide

  15. @kwugirl
    {
    :sql=>

    "SELECT \"blogs\".* FROM \"blogs\" WHERE \"blogs\".\"id
    \" = $1 LIMIT 1",

    :binds=>
    [[#0x007fd13a879e58 @array=false,
    @cast_type=#QL::OID::Integer:0x007fd13a87afd8 @limit=nil,
    @precision=nil, @range=-2147483648...2147483648,
    @scale=nil>,…,42]]
    }
    ActiveSupport::Notifications.subscribe 'sql.active_record'

    View Slide

  16. @kwugirl
    {
    :sql=>

    "SELECT \"blogs\".* FROM \"blogs\" WHERE \"blogs\".\"id
    \" = $1 LIMIT 1",

    :binds=>
    [[#0x007fd13a879e58 @array=false,
    @cast_type=#QL::OID::Integer:0x007fd13a87afd8 @limit=nil,
    @precision=nil, @range=-2147483648...2147483648,
    @scale=nil>,…,42]]
    }
    ActiveSupport::Notifications.subscribe 'sql.active_record'

    View Slide

  17. @kwugirl
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  18. @kwugirl

    View Slide

  19. @kwugirl
    $ cd src/

    View Slide

  20. @kwugirl
    $ cd src/
    $ git clone [email protected]:rails/rails.git

    $ cd rails/

    View Slide

  21. @kwugirl
    $ cd src/
    $ git clone [email protected]:rails/rails.git

    $ cd rails/
    $ git checkout v4.2.0

    View Slide

  22. @kwugirl
    # Gemfile
    gem 'rails', '4.2.0'

    View Slide

  23. @kwugirl
    # Gemfile
    # gem 'rails', '4.2.0'
    gem 'rails', :path => '../../src/rails'

    View Slide

  24. @kwugirl
    @instrumenter.instrument(
    "sql.active_record",
    :sql => sql,
    :name => name,
    :connection_id => object_id,
    :statement_name => statement_name,
    :binds => binds) { yield }
    def log(sql, name = "SQL", binds = [], statement_name = nil)
    # active_record/connection_adapters/abstract_adapter.rb

    View Slide

  25. @kwugirl
    @instrumenter.instrument(
    "sql.active_record",
    :sql => sql,
    :name => name,
    :connection_id => object_id,
    :statement_name => statement_name,
    :binds => binds) { yield }
    def log(sql, name = "SQL", binds = [], statement_name = nil)
    # active_record/connection_adapters/abstract_adapter.rb

    View Slide

  26. @kwugirl
    @instrumenter.instrument(
    "sql.active_record",
    :sql => sql,
    :name => name,
    :connection_id => object_id,
    :statement_name => statement_name,
    :binds => binds) { yield }
    def log(sql, name = "SQL", binds = [], statement_name = nil)
    # active_record/connection_adapters/abstract_adapter.rb

    View Slide

  27. @kwugirl
    def log(sql, name = "SQL", binds = [], statement_name = nil)
    @instrumenter.instrument(
    "sql.active_record",
    :sql => sql,
    :name => name,
    :connection_id => object_id,
    :statement_name => statement_name,
    :binds => binds) { yield }
    puts "====== HELLO IS IT ME YOU'RE LOOKING FOR?!!?? ======"
    # active_record/connection_adapters/abstract_adapter.rb

    View Slide

  28. @kwugirl
    git blame (can be)
    your friend

    View Slide

  29. @kwugirl
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  30. @kwugirl
    don’t get lost

    View Slide

  31. @kwugirl
    don’t get lost
    learn one thing at a time

    View Slide

  32. @kwugirl
    don’t get lost
    learn one thing at a time
    what are your unknowns?

    View Slide

  33. @kwugirl
    the problem
    connection.execute("EXPLAIN #{query}")
    SELECT "blogs".* FROM "blogs" WHERE
    "blogs"."id" = $1 LIMIT 1
    with

    View Slide

  34. @kwugirl
    the problem
    connection.execute("EXPLAIN #{query}")
    SELECT "blogs".* FROM "blogs" WHERE
    "blogs"."id" = $1 LIMIT 1
    with

    View Slide

  35. @kwugirl
    the problem
    connection.execute("EXPLAIN #{query}")
    SELECT "blogs".* FROM "blogs" WHERE
    "blogs"."id" = $1 LIMIT 1
    with

    View Slide

  36. @kwugirl
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  37. @kwugirl
    pair programming

    View Slide

  38. @kwugirl
    pair programming
    ¿?¿?¿?¿?¿?
    ¿?¿?¿?¿?¿?
    ¿?¿?¿?¿?¿?

    View Slide

  39. @kwugirl

    View Slide

  40. @kwugirl
    What are you looking for?

    View Slide

  41. @kwugirl
    What are you looking for?
    Why?

    View Slide

  42. @kwugirl
    What are you looking for?
    Why?
    How did you know to look there?

    View Slide

  43. @kwugirl
    Kernel#caller

    View Slide

  44. @kwugirl
    active_record/connection_adapters/postgresql_adapter.rb:601:in `exec_cache'
    active_record/connection_adapters/postgresql_adapter.rb:585:in `execute_and_clear'
    active_record/connection_adapters/postgresql/database_statements.rb:161:in `exec_query'
    active_record/connection_adapters/abstract/database_statements.rb:341:in `select'
    active_record/connection_adapters/abstract/database_statements.rb:37:in `select_all'
    active_record/connection_adapters/abstract/query_cache.rb:70:in `select_all'
    active_record/querying.rb:39:in `find_by_sql'
    active_record/relation.rb:639:in `exec_queries'
    active_record/relation.rb:514:in `load'
    active_record/relation.rb:243:in `to_a'
    active_record/relation.rb:617:in `pretty_print'
    Kernel#caller

    View Slide

  45. @kwugirl
    Method#source_location

    View Slide

  46. @kwugirl
    Method#source_location
    $ bundle exec rails console

    View Slide

  47. @kwugirl
    Method#source_location
    $ bundle exec rails console
    irb(main):001:0> method(:try).source_location

    View Slide

  48. @kwugirl
    Method#source_location
    $ bundle exec rails console
    irb(main):001:0> method(:try).source_location
    => ["/…/active_support/core_ext/object/try.rb", 62]

    View Slide

  49. @kwugirl
    method_defined?
    RubyTapas #439 “Method Search”

    View Slide

  50. @kwugirl
    method_defined?
    $ ObjectSpace.each_object(Class).select{|c|
    c.singleton_class.method_defined?(:try_convert)
    }
    => [File, IO, Regexp, Hash, Array, String]
    RubyTapas #439 “Method Search”

    View Slide

  51. @kwugirl
    method_defined?
    $ ObjectSpace.each_object(Class).select{|c|
    c.singleton_class.method_defined?(:try_convert)
    }
    => [File, IO, Regexp, Hash, Array, String]
    RubyTapas #439 “Method Search”

    View Slide

  52. @kwugirl
    method_defined?
    $ ObjectSpace.each_object(Class).select{|c|
    c.singleton_class.method_defined?(:try_convert)
    }
    => [File, IO, Regexp, Hash, Array, String]
    RubyTapas #439 “Method Search”

    View Slide

  53. @kwugirl
    method_defined?
    $ ObjectSpace.each_object(Class).select{|c|
    c.singleton_class.method_defined?(:try_convert)
    }
    => [File, IO, Regexp, Hash, Array, String]
    RubyTapas #439 “Method Search”

    View Slide

  54. @kwugirl
    method_defined?
    $ ObjectSpace.each_object(Class).select{|c|
    c.singleton_class.method_defined?(:try_convert)
    }
    => [File, IO, Regexp, Hash, Array, String]
    RubyTapas #439 “Method Search”

    View Slide

  55. @kwugirl
    the solution
    connection.exec_query("EXPLAIN #{statement.sql}",
    "Explain #{statement.name}",
    statement.binds)
    wow
    beauty
    wonder

    View Slide

  56. @kwugirl
    the solution
    connection.exec_query("EXPLAIN #{statement.sql}",
    "Explain #{statement.name}",
    statement.binds)
    wow
    beauty
    wonder

    View Slide

  57. @kwugirl
    the solution
    connection.exec_query("EXPLAIN #{statement.sql}",
    "Explain #{statement.name}",
    statement.binds)
    wow
    beauty
    wonder

    View Slide

  58. @kwugirl
    success!!1!one!!

    View Slide

  59. @kwugirl
    success!!1!one!!
    $1

    View Slide

  60. @kwugirl
    success!!1!one!!
    $1
    }Explain plan

    View Slide

  61. @kwugirl
    success!!1!one!!
    released in 3.15.2
    $1
    }Explain plan

    View Slide

  62. @kwugirl
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  63. @kwugirl
    reading ruby source

    View Slide

  64. @kwugirl
    gentle intro

    View Slide

  65. @kwugirl
    gentle intro

    View Slide

  66. @kwugirl
    which files?

    View Slide

  67. @kwugirl
    which files?

    View Slide

  68. @kwugirl
    github.com/ruby/ruby

    View Slide

  69. @kwugirl
    github.com/ruby/ruby
    “trunk” not “master”

    View Slide

  70. @kwugirl
    pretty flat directory

    View Slide

  71. @kwugirl
    pretty flat directory

    View Slide

  72. @kwugirl
    std library in lib/

    View Slide

  73. @kwugirl
    extension.rdoc

    View Slide

  74. @kwugirl
    parse.y

    View Slide

  75. @kwugirl
    other helpful points

    View Slide

  76. @kwugirl
    other helpful points
    rb_

    View Slide

  77. @kwugirl
    other helpful points
    rb_
    regex search with ^ to find method definition

    View Slide

  78. @kwugirl
    other helpful points
    rb_
    regex search with ^ to find method definition
    comments

    View Slide

  79. @kwugirl
    bugs.ruby-lang.org

    View Slide

  80. @kwugirl
    resources

    View Slide

  81. @kwugirl
    resources
    readingcodegood.com

    View Slide

  82. @kwugirl
    resources
    readingcodegood.com
    schneems' talk “Dissecting Ruby with Ruby”

    View Slide

  83. @kwugirl
    resources
    readingcodegood.com
    schneems' talk “Dissecting Ruby with Ruby”
    schneems.com/2016/01/25/ruby-debugging-magic-
    cheat-sheet.html

    tenderlovemaking.com/2016/02/05/i-am-a-puts-
    debuggerer.html

    View Slide

  84. @kwugirl
    resources

    View Slide

  85. @kwugirl
    resources
    Jason Clark’s talk “GDB: A Gentle Intro”

    View Slide

  86. @kwugirl
    resources
    Jason Clark’s talk “GDB: A Gentle Intro”
    Hsing-Hui Hsu’s talk “Time flies like an arrow, fruit
    flies like a banana”

    View Slide

  87. @kwugirl
    resources
    Jason Clark’s talk “GDB: A Gentle Intro”
    Hsing-Hui Hsu’s talk “Time flies like an arrow, fruit
    flies like a banana”
    Ruby Under A Microscope

    View Slide

  88. @kwugirl
    resources
    Jason Clark’s talk “GDB: A Gentle Intro”
    Hsing-Hui Hsu’s talk “Time flies like an arrow, fruit
    flies like a banana”
    Ruby Under A Microscope
    Definitive Guide to Ruby’s C API: 

    https://silverhammermba.github.io/emberb/c/

    View Slide

  89. @kwugirl
    Julia Evans
    jvns.ca

    View Slide

  90. @kwugirl
    Net::HTTP is maybe 2000 lines of
    code, not including comments.
    Julia Evans
    jvns.ca

    View Slide

  91. @kwugirl
    Net::HTTP is maybe 2000 lines of
    code, not including comments.
    It has ~1000 lines of comments…
    Julia Evans
    jvns.ca

    View Slide

  92. @kwugirl
    Net::HTTP is maybe 2000 lines of
    code, not including comments.
    It has ~1000 lines of comments…
    I can read 2000 lines of code,
    Julia Evans
    jvns.ca

    View Slide

  93. @kwugirl
    Net::HTTP is maybe 2000 lines of
    code, not including comments.
    It has ~1000 lines of comments…
    I can read 2000 lines of code,
    mostly!
    Julia Evans
    jvns.ca

    View Slide

  94. @kwugirl
    ¿?s

    View Slide

  95. @kwugirl
    appendix

    View Slide

  96. @kwugirl
    doge
    The White Rabbit,
    Alice in Wonderland
    sad Keanu
    pear/pair
    programming
    Lionel Richie +
    Where’s Waldo
    !!1!one!! the “!1” phenomenon
    breadfish
    Slurms MacKenzie,
    Futurama

    View Slide

  97. @kwugirl
    This document and the information herein (including any information that may be incorporated by reference) is provided for informational purposes only and should not
    be construed as an offer, commitment, promise or obligation on behalf of New Relic, Inc. (“New Relic”) to sell securities or deliver any product, material, code,
    functionality, or other feature. Any information provided hereby is proprietary to New Relic and may not be replicated or disclosed without New Relic’s express written
    permission.

    Such information may contain forward-looking statements within the meaning of federal securities laws. Any statement that is not a historical fact or refers to
    expectations, projections, future plans, objectives, estimates, goals, or other characterizations of future events is a forward-looking statement. These forward-looking
    statements can often be identified as such because the context of the statement will include words such as “believes,” “anticipates,” “expects” or words of similar
    import.

    Actual results may differ materially from those expressed in these forward-looking statements, which speak only as of the date hereof, and are subject to change at any
    time without notice. Existing and prospective investors, customers and other third parties transacting business with New Relic are cautioned not to place undue
    reliance on this forward-looking information. The achievement or success of the matters covered by such forward-looking statements are based on New Relic’s current
    assumptions, expectations, and beliefs and are subject to substantial risks, uncertainties, assumptions, and changes in circumstances that may cause the actual
    results, performance, or achievements to differ materially from those expressed or implied in any forward-looking statement. Further information on factors that could
    affect such forward-looking statements is included in the filings we make with the SEC from time to time. Copies of these documents may be obtained by visiting New
    Relic’s Investor Relations website at ir.newrelic.com or the SEC’s website at www.sec.gov.

    New Relic assumes no obligation and does not intend to update these forward-looking statements, except as required by law. New Relic makes no warranties,
    expressed or implied, in this document or otherwise, with respect to the information provided.

    View Slide