From: Chuck Remes Date: 2011-09-15T01:37:10+09:00 Subject: Re: [Q] recommended way to support multiple APIs from one codebase On Sep 14, 2011, at 5:54 AM, Robert Klemme wrote: > On Tue, Sep 13, 2011 at 11:41 PM, Chuck Remes wrote: >> I am the author of the ffi-rzmq gem. It wraps the 0mq [1] (libzmq) library 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 patch version information, so I know I can detect the correct version at runtime and load the appropriate code. >> >> My question stems from one of organization. The 3.x and 4.x APIs share many of the same characteristics as the 2.x API, so I'd like to be able to share 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 sharable pieces into a module that I can include, use if/else to require entire files, etc. I have *so many* choices for how to approach this that I'm frozen. >> >> The approach I am leaning towards right now requires the creation of a base class that conforms to the version 2.x API. The 3.x and 4.x APIs will reopen it and override the appropriate methods to inject the correct method signature and behavior. So, as the gem loads it will always load the version2 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 methods. > > 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 like the suggestion of using modules and "include"ing them based upon a runtime check. Thanks to you and Christian for the feedback. I appreciate it. cr