From: Robert Klemme Date: 2012-04-06T00:08:06+09:00 Subject: Re: Design pattern question On Thu, Apr 5, 2012 at 4:25 PM, James French wrote: > Using  the Jay Fields link and slightly modifying I've got something I'm happy with. Thanks for the help Robert, as always :) > > module SourceControl >  def self.init(subject) >    subject.public_methods(false).each do |meth| >      (class << self; self; end).class_eval do >        define_method meth do |*args| >          subject.send meth, *args >        end >      end >    end >  end > end That's just a mechanism to generate delegation. And you redefine methods all the time. I don't think meta programming is necessary at all here. > class SourceControlAPI > >  def checkout(repository, dest, options={}) >  end > >  def update(path, options={}) >  end Those are not really needed. And if you want to have them then I'd make them either contain a default implementation if there exists one or throw an exception which explains that this method must be implemented for the class. > end > > class SVN < SourceControlAPI > >  def checkout(repository, dest, options={}) >    puts "Checking out from SVN" >  end > >  def update(path, options={}) >  end > > end > > SourceControl.init(SVN.new) > SourceControl.checkout('foo', 'bar') You are hiding specific state in a constant. I don't like that because it will prevent accessing multiple different source control systems in the same program or from multiple threads. I find that requirement to be able to invoke all the methods through the constant leads to a situation where you severely cripple modularity and reusability without really gaining something. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/