Save 37% off PRO during our Black Friday Sale! »

Wow Code, Such Read! (RubyConf Colombia)

40be222374e709cae7543dee233fe2e1?s=47 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

40be222374e709cae7543dee233fe2e1?s=128

Katherine Wu

September 03, 2016
Tweet

Transcript

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

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

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

    Lau theeffectiveengineer.com
  4. @kwugirl

  5. @kwugirl 10.000 hours

  6. @kwugirl 10.000 hours 250 weeks

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

  8. @kwugirl productive struggling

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

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

    the code
  11. @kwugirl the problem

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

  13. @kwugirl the problem connection.execute("EXPLAIN #{query}") SELECT "blogs".* FROM "blogs" WHERE

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

    "blogs"."id" = $1 LIMIT 1 with
  15. @kwugirl { :sql=>
 "SELECT \"blogs\".* FROM \"blogs\" WHERE \"blogs\".\"id \"

    = $1 LIMIT 1", … :binds=> [[#<ActiveRecord::ConnectionAdapters::PostgreSQLColumn: 0x007fd13a879e58 @array=false, @cast_type=#<ActiveRecord::ConnectionAdapters::PostgreS QL::OID::Integer:0x007fd13a87afd8 @limit=nil, @precision=nil, @range=-2147483648...2147483648, @scale=nil>,…,42]] } ActiveSupport::Notifications.subscribe 'sql.active_record'
  16. @kwugirl { :sql=>
 "SELECT \"blogs\".* FROM \"blogs\" WHERE \"blogs\".\"id \"

    = $1 LIMIT 1", … :binds=> [[#<ActiveRecord::ConnectionAdapters::PostgreSQLColumn: 0x007fd13a879e58 @array=false, @cast_type=#<ActiveRecord::ConnectionAdapters::PostgreS QL::OID::Integer:0x007fd13a87afd8 @limit=nil, @precision=nil, @range=-2147483648...2147483648, @scale=nil>,…,42]] } ActiveSupport::Notifications.subscribe 'sql.active_record'
  17. @kwugirl 2. remember your question 3. enlist help 1. see

    the code
  18. @kwugirl

  19. @kwugirl $ cd src/

  20. @kwugirl $ cd src/ $ git clone git@github.com:rails/rails.git
 $ cd

    rails/
  21. @kwugirl $ cd src/ $ git clone git@github.com:rails/rails.git
 $ cd

    rails/ $ git checkout v4.2.0
  22. @kwugirl # Gemfile gem 'rails', '4.2.0'

  23. @kwugirl # Gemfile # gem 'rails', '4.2.0' gem 'rails', :path

    => '../../src/rails'
  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
  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
  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
  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
  28. @kwugirl git blame (can be) your friend

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

    the code
  30. @kwugirl don’t get lost

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

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

    what are your unknowns?
  33. @kwugirl the problem connection.execute("EXPLAIN #{query}") SELECT "blogs".* FROM "blogs" WHERE

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

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

    "blogs"."id" = $1 LIMIT 1 with
  36. @kwugirl 2. remember your question 3. enlist help 1. see

    the code
  37. @kwugirl pair programming

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

  39. @kwugirl

  40. @kwugirl What are you looking for?

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

  42. @kwugirl What are you looking for? Why? How did you

    know to look there?
  43. @kwugirl Kernel#caller

  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
  45. @kwugirl Method#source_location

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

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

  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]
  49. @kwugirl method_defined? RubyTapas #439 “Method Search”

  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”
  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”
  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”
  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”
  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”
  55. @kwugirl the solution connection.exec_query("EXPLAIN #{statement.sql}", "Explain #{statement.name}", statement.binds) wow beauty

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

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

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

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

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

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

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

    the code
  63. @kwugirl reading ruby source

  64. @kwugirl gentle intro

  65. @kwugirl gentle intro

  66. @kwugirl which files?

  67. @kwugirl which files?

  68. @kwugirl github.com/ruby/ruby

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

  70. @kwugirl pretty flat directory

  71. @kwugirl pretty flat directory

  72. @kwugirl std library in lib/

  73. @kwugirl extension.rdoc

  74. @kwugirl parse.y

  75. @kwugirl other helpful points

  76. @kwugirl other helpful points rb_

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

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

    find method definition comments
  79. @kwugirl bugs.ruby-lang.org

  80. @kwugirl resources

  81. @kwugirl resources readingcodegood.com

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

  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
  84. @kwugirl resources

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

  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”
  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
  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/
  89. @kwugirl Julia Evans jvns.ca

  90. @kwugirl Net::HTTP is maybe 2000 lines of code, not including

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

    comments. It has ~1000 lines of comments… Julia Evans jvns.ca
  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
  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
  94. @kwugirl ¿?s

  95. @kwugirl appendix

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