Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??
However, in Perl we have CPAN from which we install our modules...this allows us to specify dependencies be be installed when we install our module. In this Perl Advent Calendar example, why would we create a ReindeerFactory instead of just forcing our module to install Robo-Reindeer if that's the one we prefer?

IMHO, you're right to question this. Factory classes are often used in strongly typed languages like Java, I myself have for example written a Logger interface with different underlying implementations. The important thing to note is that the user of my library specifically chooses which implementation they want, and the factory class is helpful because the language is compiled and strongly typed; it's not as simple as Perl's "a constructor can return whatever it wants".

However, the conditional loading of modules depending on something outside of the user's control is something that I nowadays think should be very sparingly used for exactly the reason you hint at: if I've written my code to depend on a certain module or functionality (RoboReindeer), then trying to adapt my code to environments where that module isn't available (BioReindeer-only) is often more work than either backporting RoboReindeer to that environment, or simply declaring that my code requires RoboReindeer, with whatever limitations that brings.

For me, it comes down to the question of well-defined behavior. If I'm writing a library, I don't like telling the user of my code "you ask for a reindeer and maybe I'll give you a BioReindeer or maybe a RoboReindeer, why do you care?" because more often than not there is a difference between the two that will have my user jumping through hoops to cope with that difference down the line (if ( $reindeer->isa("RoboReindeer") ) { do_this() } elsif ( $reindeer->isa("BioReindeer") ) { do_that() } else { die "unknown species" }).

On the practical side, let's say I write a library that uses *Reindeer, and when the user installs my library they only have BioReindeer installed, so only that subset of my module's test suite gets run. If they install RoboReindeer later, my test suite may never get executed against the RoboReindeer they installed, which again may lead to problems.

So for these reasons nowadays I lean very strongly towards simply saying "the users of my library are getting RoboReindeers, period".

There are of course exceptions, an important one is the OS-dependent implementation of a platform-independent interface, as choroba indicated - one of the big ones in the Perl core is File::Spec, for example. Another one is the automatic loading of XS-based versions of otherwise pure-Perl modules when they are available (as long as the two really behave identically and the XS version is just an optimization). And a last reason that I can think of at the moment may be if you're trying to gradually transition your code away from one dependency onto the other.

(It's late and I don't have the time to investigate further right now, but I'd be genuinely curious if there are other useful uses for the "recommends" and "suggests" relationships of CPAN::Meta::Spec.)

Update: Thinking about this a bit more, I guess what I am saying is that my experience simply doesn't line up with the premise of the article, in particular the first word:

Often we find ourselves writing code that copes with optional dependencies; Code that will use a module to do amazing things if it's installed, but will muddle through with some lesser code path if that dependency is missing or unavailable on the system.

Instead, I think that most of the time one thinks one is in this situation, there is a different and often more pragmatic solution possible.

In reply to Re: Factory classes in Perl (updated) by haukex
in thread Factory classes in Perl by Bod

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?

What's my password?
Create A New User
Domain Nodelet?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (2)
As of 2024-06-19 06:10 GMT
Find Nodes?
    Voting Booth?

    No recent polls found

    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.