Hi Paul: This sounds like a great idea. However, I would recommend that when you do write your module, you include some way of determining which version is currently in use.
For example, it's difficult to detect which version of File::Spec is in use, because it's set up so that it does @ISA = ('File::Spec::Unix'); Other classes, including the Win32 one, subclass the Unix class to get its basic functionality too, so doing: File::Spec->isa('File::Spec::Unix') doesn't work properly. For reasons related to module naming, I wouldn't simply do: File::Spec::$^O. Consider the case where Linux and OS/2 both use the same class, Unix (as happens with File::Spec). Then simply appending $^O will mean you need to copy the class for both 'linux' and 'OS2'. File::Spec handles it internally by using a hash mapping to the different modules where appropriate. But this might not work in general (as your class is designed for), since the behaviours of different operating systems are different. File::Spec does it because filehandling on OS2 and Linux are similar, but other behaviours may be different. So, I guess this is just my long-winded way of saying that you should include a method of mapping operating systems to class names, but in a portable manner, so that you can later determine which one is currently in use. I ran into this problem with one of my modules that used File::Spec under Win32, where my program was expecting Unix-style path names. So I needed a way to detect if File::Spec was running under Unix. If not, then the module was to convert the path stuff to Unix-like, which obviously isn't necessary if we're already running under Unix. (This might not be possible under my current understanding of how your module is supposed to work, since it appears to be as zero-configuration as possible. Hopefully there is a way to pass parameters before the call to your module's subclass-finding magic to tell it about such aliases, since there are lots of $^O strings, that might not be strictly necessary) But, getting to what your module should be named, no good ideas really come to mind. But if you're going to leave out the Magic class names (personally I don't see anything wrong with it, and think Class::OSMagic might be appropriate)... Then my next choice would be Class::ForSystem, since it's not too long and conveys what the module is designed to do. Doing stuff like this can get pretty complicated, so I'm glad somebody is working on something for it :-). Good work Cheers, Jonathan (PAUSE: FREQUENCY) On Tue, Mar 24, 2009 at 6:30 AM, Paul LeoNerd Evans <leon...@leonerd.org.uk> wrote: > I find a number of times, that I've wanted to make some code that > certain OSes would have better implementations of than others, or just > plain implement in a different way. > > There's some existing examples of code that does this; File::Spec comes > to mind. It chooses a specific subclass at runtime, based on the OS > choice ($^O), or falling back on a list of decreasing specificness if > that isn't found. Another example here would be a Linux-specific > subclass of File::Tail that can use Inotify rather than polling for > stat(). I've had further thoughts on things like /proc-scraping, network > interface information, etc... > > What all these have in common is that $^O is used as a key to build a > list of possible module names, and the code then tries to load and use > the first one in the list it finds. Perhaps in cases like File::Tail > where the OS-specific class is simply more optimal, this could be an > optional installation later on. > > I'd like to write a small module for automatically doing this sort of > magic; I'm just in short of a name for it. I feel it ought to be > Class-y; something like > > Class::OSMagic > Class::OSSpecific > Class::MagicOS > Class::SystemSpecific > Class::ForSystem > > As a brief example of code, consider the following hack on File::Tail. > > Two-line change to File/Tail.pm: > > use Class::OSMagic; > > # Rename constructor > sub __new > { > ... > } > > The 'use' line would automatically import a 'sub new' into the caller, > which just does something like > > sub new > { > Class::OSMagic::find_best_subclass( shift )->__new( @_ ); > } > > The user of File::Tail need not know the difference; the normal > > my $tailer = File::Tail->new( $path ); > > constructor is unaffected. > > If one day someone writes an Inotify-aware Linux extension, all they > have to do is provide > > sub File::Tail::linux; # note lowercase, to match $^O > > use Linux::Inotify; > > sub __new > { > ... > } > > Now, any code that tries to use File::Tail objects on a Linux machine > will automatically find this subclass if it is installed. > > > There's a suggestion that the word 'magic' should be avoided - other > ideas on the name? > > -- > Paul "LeoNerd" Evans > > leon...@leonerd.org.uk | CPAN ID: PEVANS > > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.9 (GNU/Linux) > > iD8DBQFJyLYsvLS2TC8cBo0RAig4AJ9AvIGIeEi9KQPUMMZ2hiBxKJJjCwCfXl3O > vMATzHk4J9g2Dm/drmf1clY= > =xSGI > -----END PGP SIGNATURE----- > >