Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rescuing Ruby

Greg Brockman
February 21, 2014

Rescuing Ruby

If you ask someone on the street what is wrong with Ruby, you will probably hear "it's too slow." However, if you talk to enough people, you will start to uncover a deeper, more insidious set of issues, such as "Ruby's conventions are poorly suited to building maintainable projects" or "there's no tooling for statically catching even the simplest bugs."

Since most people are not even aware of these issues, no one is working on improving them. No matter how fast the Ruby interpreter becomes, we will still be silently losing community members who are best positioned to ensure that Ruby continues to be relevant as languages like Go and Clojure become increasingly serious competitors.

Fortunately, with enough of a cultural shift, it is not too late to change Ruby's course. We need to write static analysers that catch what is possible within the constraints of Ruby's dynamicism. We need to standardise on a style guide and publish projects for people to emulate. In this talk, I will elaborate on these issues, and present my view on what else we as a community need to change in order to maintain Ruby's position in the long run.

Greg Brockman

February 21, 2014
Tweet

More Decks by Greg Brockman

Other Decks in Technology

Transcript

  1. “Highly productive web language which can also be systems code

    in a pinch”? ! (Python’s web libraries are getting quite good.)
  2. “A good place to write prototyping code before writing in

    a ‘serious’ language like C++”? ! (Go is making it easy to write “serious” code, so prototyping languages are becoming less compelling.)
  3. “Home of the most innovative web frameworks”? ! (Node.js is

    where the next generation of web frameworks, such as Meteor, are being written.)
  4. So, what can we do to reverse the trend and

    prevent Ruby becoming another Perl? ! This talk proposes one possible set of (occasionally radical) changes, but what’s most important is that we as a community don’t just sit idly by. ! All examples are just isolated illustrations — I don’t mean to point fingers.
  5. # Thrift IDL: # # namespace rb Example.Thrift # #

    service ExampleInterface { # string example(1: string arg); # } ! class ExampleServer < Chalk::Thrift::Server::Base interface Example::Thrift::ExampleInterface set :port, 1337 ! def example(arg) 'hi' end end
  6. Run `bundle install` to install missing gems. How much time

    do we spend staring at this: The Bundler API is great, but there’s a lot of work to be done on the implementation.
  7. Change 4: Add standard ways of doing standard tasks (logging,

    config, etc). Just having this for Rails isn’t enough.
  8. loop do begin break if @stopping || @network_is_down run_once [...]

    rescue Exception => e puts e.class.name puts e.message puts e.backtrace end end Right now the path of least resistance looks like this:
  9. class MyClass include Chalk::Log ! # Prints: # # Saying

    something: what="hello" def hello log.info('Saying something', what: 'hello') end end
  10. Right::AWS: ! ! ! ! ! ! Rails 3: Example

    via http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/ class String def camelize() self.dup.split(/_/).map{ |word| word.capitalize }.join('') end end ! ! ! class String def camelize(first_letter = :upper) case first_letter when :upper then ActiveSupport::Inflector.camelize(self, true) when :lower then ActiveSupport::Inflector.camelize(self, false) end end end
  11. Go Oracle: ! ▶ Found a call path from root

    to (*github.com/stripe-ctf/ octopus/harness.Harness).querier ! ▶ (*github.com/stripe-ctf/octopus/harness.Harness).querier ▶ static method call from (*github.com/stripe-ctf/octopus/harness.Harness).Start ▶ static method call from (*github.com/stripe-ctf/octopus/director.Director).Start ▶ static method call from github.com/stripe-ctf/octopus.main func (h *Harness) querier() { […] }
  12. While it’s impossible to get 100% coverage, we can write

    tools for all the sane cases. (If your analyzer can’t understand it, a human probably can’t either.) ! Proof-of-concept: https://github.com/gdb/ruby-static- checker
  13. def method_missing(*m) regex = m.first.to_s.match(/^find_(all_)?(country_| countries_)?by_(.+)/) super unless regex !

    countries = self.find_by($3, m[1], $2) $1 ? countries : countries.last end ! […] ! def find_by(attribute, value, obj = nil) self.find_all_by(attribute.downcase, value).map do | country| obj.nil? ? country : self.new(country.last) end end
  14. “Be liberal in what you accept, and conservative in what

    you send” ! — RFC 1122 ! Good for internet protocols. Less good for the application layer. <foo type="yaml"> --- :hello: world </foo> (https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2013-0156)
  15. Imagine being able to connect to your production code and

    drop into exceptioned contexts, extract a runnable core dump, or gather statistics.