Beefy Boxes and Bandwidth Generously Provided by pair Networks DiBona
Think about Loose Coupling
 
PerlMonks

Perl Factory Method Pattern?

by osunderdog (Deacon)
 | Log in | Create a new user | The Monastery Gates | Super Search | 
 | Seekers of Perl Wisdom | Meditations | PerlMonks Discussion | 
 | Obfuscation | Reviews | Cool Uses For Perl | Perl News | Q&A | Tutorials | 
 | Poetry | Recent Threads | Newest Nodes | Donate | What's New | 

on Oct 11, 2004 at 19:37 UTC ( #398257=perlquestion: print w/ replies, xml ) Need Help??
osunderdog has asked for the wisdom of the Perl Monks concerning the following question:

Perlmonks, I have a matter for your consideration:

I am looking for a pattern for a Class Factory Method pattern in perl. I am developing a class that I expect to have at least three subclasses that can be instanciated. The base class will define the interface and each of the subclass will provide a different implementation for the platform where class is invoked. I have written several of these, but each time I wonder if there is a pattern out there that avoids some of the pitfalls or, worse yet, there are pitfalls have yet to encounter!

I know that there is a Package to do this via inheritance: Class::Factory  However I do not have access to that Class in our standard Perl installation and I would like to minimize external dependencies.

For the base class, here's what I have:

package ProcInfo; use Carp; use strict; use warnings; our $VERSION = '0.01'; sub new { my $class = shift; my $self = {}; bless $self, $class; $self->_init(); return $self; } sub _init { my $self = shift; my $osModule = "ProcInfo_$^O"; # Load the subclass if it isn't already loaded. eval "require $osModule"; if($@) { croak "Could not load OS ProcInfo Module:$osModule. [$@]"; } # rebless self using subclass. bless $self, $osModule; $self->_init(@_); return $self; } sub method_1 { return 1; } 1;

Some question I have about the base class implementation:

  • If I know that I'm going to rebless the object to a subclass. Is there any advantage to blessing it in the first place in the new?
  • Is the rebless in the _init the right way to recast self to another class?

The skeleton for each sublcass would looking like this and it would be stored in ProcInfo_linux.pm:

package ProcInfo_linux; use strict; use warnings; use base qw|ProcInfo|; our $VERSION = '0.01'; sub _init { my $self = shift; return $self; } sub method_1 { return 1; } 1;

Finally, here is my test script (ProcInfo.t):

use Test::More tests => 3; BEGIN { use_ok('ProcInfo') }; my $pInfo = new ProcInfo; is(ref($pInfo), "ProcInfo_$^O", "Factory new Works"); ok($pInfo->method_1());

Any suggestions or comments on this implementation would be appreciated!


"Look, Shiny Things!" is not a better business strategy than compatibility and reuse.


OSUnderdog

Janitored by Arunbear - added readmore tags, as per Monastery guidelines

Comment on Perl Factory Method Pattern?
Select or Download Code
Re: Perl Factory Method Pattern?
by dragonchild (Archbishop) on Oct 11, 2004 at 19:42 UTC
    ... and I would like to minimize external dependencies.

    That is a feeling that many share, but I don't think it is worthwhile. CPAN exists so that the mainline distribution of Perl doesn't bloat to 10G, 90% any given user will not need. Most of the applications you can think of in Perl require at least 10-20% of their module code to be downloaded from CPAN. For example, one of the most downloaded module from CPAN is DBI. If CGI wasn't in the mainline, it would be the most downloaded module.

    Download Class::Factory and just deal with it. CPAN isn't an external dependency - it's one of the primary reasons Perl is worth using.

    Being right, does not endow the right to be rude; politeness costs nothing.
    Being unknowing, is not the same as being stupid.
    Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence.
    Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.

[reply]

      I agree that one has to deal with CPAN more or less, but it is quite normal to have concerns over quality.

      A mudule like DBI, as you said, is one of the most downloaded module. What does that mean? that means that it gets a better chance to have bugs found, and fixed because of all the attention it attracted. This creates a positive cycle, it is getting better, so more poeple use it; more people use it, so it gets even better...

      I am not sure about Class::Factory, but in general, it is always a good idea to ask for others' experience with a CPAN module before you use it, or the other way around, try it, and share your good or bad experience with others.

[reply]
Re: Perl Factory Method Pattern?
by SpanishInquisition (Pilgrim) on Oct 11, 2004 at 20:10 UTC
    CPAN is no more an external dependancy than is having the right version of libc or the latest security patches to SSH...you have to be able to deal with these things. Plus, you can always download/install a local copy to your home directory (or any directory) and check it in to version control if you have a problem with deployment in network-constrainted environments.

    as to the OOP question, my stance on design patterns is another story... Dominus is more eloquent than I, and he bites his tongue more too: Design Patterns Aren't

[reply]

      I think you misunderstood MJD's presentation (which is quite common, as he expresses at the addition he made to the end of the talk on the web).

      MJD is not saying Design Patterns are good or bad. He's saying there is a conflict of terminology, and we may be missing out on some really useful stuff because of it.

      "There is no shame in being self-taught, only in not trying to learn in the first place." -- Atrus, Myst: The Book of D'ni.

[reply]
        I understood. "Design Patterns" in the C++ sense is what this post is pretty much about, not "Design Patterns" in the architectural sense. His point about such things being inhuman (first several slides) were right... Agreed, they have value, but they have value in the common terminology sense, i.e. knowing what a Factory is, rather than having the template to implement a Factory.
[reply]
Re: Perl Factory Method Pattern?
by sandfly (Beadle) on Oct 11, 2004 at 22:51 UTC
    To answer the questions you actually asked, in reverse order:
    • Yes, this is the way to rebless into a new class.
    • The way you've coded the "new" method, it calls _init using a method call on $self. It needs to be blessed for this to work. You could change this to a simple subroutine call: _init( $self ), and not bother with the first blessing.

    What you've coded will work, and most of it is fine; but there are a couple of things I dislike about the class structure you've used:

    • First, you have two _init methods, which do different things: one is a factory method; the other is a genuine instance initialisation.
    • Second, your base class, ProcInfo, has two roles: first, it's a factory; second, it's a ProcInfo thingy.
    You've said you have written a few of these; if you put the code from _init into a separate module, called, say, Factory, in a method called something like "makeOSSpecific", you can get reuse. The first parameter would be the base class name, so you'd call it from "new" something like: return Factory::makeOSSpecific( "ProcInfo", $self ). There would be no need to include Factory in the class hierarchy, you'd just require or use it in ProcInfo.
[reply]
[d/l]
[select]
Minimizing dependencies (was: Perl Factory Method Pattern?)
by lachoy (Parson) on Oct 13, 2004 at 00:40 UTC

    Just a few words on minimizing dependencies:

    Having to download/build dependencies is a complaint a lot of people have with large modules/applications on CPAN. I don't personally agree with not using a module because of dependencies-- especially a pure-Perl module! without additional dependencies of its own! -- but you should at least realize that you're making a number of trade-offs by doing so.

    • This module has been on CPAN for nearly four years, and has been exercised by lots of people in lots of situations on lots of platforms. Yours is brand new and barely tested.
    • Chances are those additional features in the module are there for a reason; if you continue to improve yours for a while you'll probably see why.
    • Because it's written for public vs. private consumption I'm guessing it has much better documentation than you're going to write, which makes it easy for the person reading your code six months from now to figure out what's going on. Even if that person six months from now is you.

    I'm not saying anything bad about re-creating functionality to learn how it works because I learn by doing too. Going through the trials of typing in code, debugging it, thinking about ways to break it is a great way to learn. (And I've been known to recreate some wheels as well...) But CPAN is such a fantastic resource that it seems a shame to dismiss it because you'll have to mount the wheel yourself :-)

    And yes, I'm the Class::Factory author, so I'm a little biased :-)

    Chris
    M-x auto-bs-mode

[reply]

      It's a great library and I'm going to end up using it. I'll just add it to a local package collection.


      "Look, Shiny Things!" is not a better business strategy than compatibility and reuse.


      OSUnderdog
[reply]

Back to Seekers of Perl Wisdom


Login:
Password
remember me
What's my password?
Create A New User

Node Status
node history
Node Type: perlquestion [id://398257]
Approved by kvale
Front-paged by cLive ;-)
help
Community Ads
Chatterbox
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users
Others avoiding work at the Monastery: (6)
GrandFather
atcroft
herveus
Eyck
gnosti
im2
As of 2009-11-21 08:52 GMT
Sections
The Monastery Gates
Seekers of Perl Wisdom
Meditations
PerlMonks Discussion
Categorized Q&A
Tutorials
Obfuscated Code
Perl Poetry
Cool Uses for Perl
Perl News
Information
PerlMonks FAQ
Guide to the Monastery
What's New at PerlMonks
Voting/Experience System
Tutorials
Reviews
Library
Perl FAQs
Other Info Sources
Find Nodes
Nodes You Wrote
Super Search
List Nodes By Users
Newest Nodes
Recently Active Threads
Selected Best Nodes
Best Nodes
Worst Nodes
Saints in our Book
Leftovers
The St. Larry Wall Shrine
Offering Plate
Awards
Craft
Snippets Section
Code Catacombs
Quests
Editor Requests
Buy PerlMonks Gear
PerlMonks Merchandise
Planet Perl
Perlsphere
Use Perl
Perl.com
Perl 5 Wiki
Perl Jobs
Perl Mongers
Perl Directory
Perl documentation
CPAN
Random Node
Voting Booth

Future historians will find that the material characteristic of the current era is...

Aluminium
Plastic
Oil
Water
Carbon dioxide
Copper
Iron
Silicon
Salt
Uranium
Hydrogen
Other

Results (729 votes), past polls