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

Wow Code, Such Read! (NR Ruby UnConf)

Wow Code, Such Read! (NR Ruby UnConf)

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 an internal Ruby unconf at New Relic.
Blog post: http://kwugirl.blogspot.com/2016/05/wow-code-such-read.html

Katherine Wu

February 23, 2017
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
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  10. @kwugirl
    the problem

    View Slide

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

    View Slide

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

    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
    {
    :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

  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
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  17. @kwugirl

    View Slide

  18. @kwugirl
    $ cd src/

    View Slide

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

    $ cd rails/

    View Slide

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

    $ cd rails/
    $ git checkout v4.2.0

    View Slide

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

    View Slide

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

    View Slide

  23. @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

  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
    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

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

    View Slide

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

    View Slide

  29. @kwugirl
    don’t get lost

    View Slide

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

    View Slide

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

    View Slide

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

    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
    2. remember your question
    3. enlist help
    1. see the code

    View Slide

  36. @kwugirl
    pair programming

    View Slide

  37. @kwugirl
    pair programming
    ??????????
    ??????????
    ??????????

    View Slide

  38. @kwugirl

    View Slide

  39. @kwugirl
    What are you looking for?

    View Slide

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

    View Slide

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

    View Slide

  42. @kwugirl
    Kernel#caller

    View Slide

  43. @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

  44. @kwugirl
    Method#source_location

    View Slide

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

    View Slide

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

    View Slide

  47. @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

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

    View Slide

  49. @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

  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
    2. remember your question
    3. enlist help
    1. see the code

    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
    reading ruby source

    View Slide

  63. @kwugirl
    gentle intro

    View Slide

  64. @kwugirl
    gentle intro

    View Slide

  65. @kwugirl
    which files?

    View Slide

  66. @kwugirl
    which files?

    View Slide

  67. @kwugirl
    github.com/ruby/ruby

    View Slide

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

    View Slide

  69. @kwugirl
    pretty flat directory

    View Slide

  70. @kwugirl
    pretty flat directory

    View Slide

  71. @kwugirl
    std library in lib/

    View Slide

  72. @kwugirl
    extension.rdoc

    View Slide

  73. @kwugirl
    parse.y

    View Slide

  74. @kwugirl
    other helpful points

    View Slide

  75. @kwugirl
    other helpful points
    rb_

    View Slide

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

    View Slide

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

    View Slide

  78. @kwugirl
    bugs.ruby-lang.org

    View Slide

  79. @kwugirl
    resources

    View Slide

  80. @kwugirl
    resources
    readingcodegood.com

    View Slide

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

    View Slide

  82. @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

  83. @kwugirl
    resources

    View Slide

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

    View Slide

  85. @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

  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”
    Ruby Under A Microscope

    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
    Definitive Guide to Ruby’s C API: 

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

    View Slide

  88. @kwugirl
    Julia Evans
    jvns.ca

    View Slide

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

    View Slide

  90. @kwugirl
    Net::HTTP is maybe 2000 lines of
    code, not including comments.
    It has ~1000 lines of 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…
    I can read 2000 lines of code,
    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,
    mostly!
    Julia Evans
    jvns.ca

    View Slide

  93. @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