Sunday, August 24, 2008

Ruby best practice patterns, by Rein Henrichs

I watched the Ruby best practice patterns presentation, given by Rein Henrichs at the Ruby Hoedown 2008. Personally, I thought it was a very long presentation (including a useless 15-minute long dive-in) to deliver a simple message. His (nevertheless important) message was that a programmer should aim to write communicative code. And the best practice patterns considerably help to reach that goal.



Here are my highlights (divided in 3 sections):

Legacy code and maintainability
  • your code is legacy code as soon as it is written
  • most of our time is spent maintaining that legacy code
  • software costs far more to maintain than to write
  • write code for humans, not for computers


Best practice patterns
  • Definition of "Best practice patterns":
a set of techniques experts currently use to make the best decisions over and over again - Rein Henrichs
  • the best way to learn about patterns is to read through open source code, like gems

A few of his favorite patterns (inspired from Kent Beck's Smalltalk best practice patterns)
  • pattern: composed method

class RemoteCache < Remote

  def deploy!

    update_repository_cache

    copy_repository_cache

  end

end




  • pattern: execute around
Example in Ruby:

#using a block ensures the file is closed when done

File.open("temp_file") do |file|

  file.write(data)

end 




Example in Rails (around filter):


around_filter :log_action



private



def log_action

  logger.debug("before #{self.action_name}")

  yield

  logger.debug("after #{self.action_name}")

end





  • pattern: yield and return
Example in Rails (implementation of the will_paginate plugin):


#using a block for the object creation makes sure

#all operations are done before someone uses it

def self.create(page, per_page, total = nil)

  pager = new(page, per_page, total)

  yield pager

  pager

end



Example in Rails (implementation of returning):


def returning(value)

  yield(value)

  value

end



Example in (forthcoming) Ruby 1.9:


#could be useful for debugging:

# ex.: collection.select{|e|e<4}.tap{puts "size after select: #{size}"}

def tap

  yield(self)

  self

end



  • pattern: method object
Example in Ruby:


#example of usage:

#def dot_file_contents(graph)

#  OutputGenerator.new(graph).generate

#end



class OutputGenerator

  def initialize(graph)

    @graph = graph

    @output = []

  end

  attr_accessor :graph, :output



  def generate

    outout_classes_and_i_methods

    output_i_methods_and_ids

    return output

  end

end


0 comments: