On Tue, Sep 13, 2011 at 11:41 PM, Chuck Remes <cremes.devlist / mac.com> wrot=
e:
> I am the author of the ffi-rzmq gem. It wraps the 0mq [1] (libzmq) librar=
y for use by all of the major Ruby runtimes.
>
> Recently, the 0mq project developers used their 2.x branch to create a 3.=
x and a 4.x branch. These new branches are changing the API of the library;=
 it will *not* be backward compatible with the version 2.x API.
>
> I would like to continue shipping a single gem that can support libzmq 2.=
x, 3.x and 4.x out of the box without requiring the end user to do anything=
 fancy. The library supports a function call to retrieve major, minor and p=
atch version information, so I know I can detect the correct version at run=
time and load the appropriate code.
>
> My question stems from one of organization. The 3.x and 4.x APIs share ma=
ny of the same characteristics as the 2.x API, so I'd like to be able to sh=
are that code amongst all of the versions. In the places where they differ,=
 I don't know if I should do an if/else kind of structure within the class =
definition, subclass it from another file and make the changes, make the sh=
arable pieces into a module that I can include, use if/else to require enti=
re files, etc. I have *so many* choices for how to approach this that I'm f=
rozen.
>
> The approach I am leaning towards right now requires the creation of a ba=
se class that conforms to the version 2.x API. The 3.x and 4.x APIs will re=
open it and override the appropriate methods to inject the correct method s=
ignature and behavior. So, as the gem loads it will always load the version=
2 API and then as it detects either version 3 or 4 it will require another =
file that essentially reopens the class and overwrites the appropriate meth=
ods.

This approach won't work if there can be two versions at the same
time.  Even if that could never happen at runtime it might be good
during testing.  Generally I would favor an approach where classes are
not reopened.  I think this will also make the code easier to read.  I
can think of various approaches depending on when you can determine
the library version (i.e. at load time of the gem, or whenever a new
root object from the lib is needed).

I don't know the current API so I am inventing

module RZMG
  class CommonForAll
  end

  def self.create(*a)
    FACTORY.new(*a)
  end

  # determine at load time
  FACTORY =3D case rzmg_version
  when /^2/
    require 'rzmg/v2' # loads RZMG::V2 module etc.
    V2::Factory
  when /^3/
    require 'rzmg/v3' # as above
    V3::Factory
  end
end

If you want to detect versions at usage time you could use autoload to
make initial loading quicker.

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/