in reply to Re^3: Factory classes in Perl
in thread Factory classes in Perl

Example: you create something with a complicated dynamic table, with rows and cells.

I think there is a difference: the advent calendar article is talking about "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". In the example you name, typically the author of the module providing the common "Table" interface will provide at least one (reference) implementation as part of their distribution. All the other backends from other distributions are additional to the existing functionality - I'd say they are "plugins" instead of "fallbacks".

Just to clarify: I wasn't advocating against modularity, writing abstract interfaces, or "factory" classes that produce one of the implementations of an interface. What I was saying was that when faced with the situation "the dependency I want to use isn't available everywhere", it may be more worth it trying to figure out either "can I live without this dependency" (example) or "I'll require this dependency, and figure out how to get it into the environments where it doesn't work" (similar in spirit to Yes, even you can use CPAN) instead of this "maybe you'll get the full functionality of my code, maybe you won't" situation.

I had this dilemma with my module IPC::Run3::Shell. Though the initial release was in Aug 2014, if I go into my unpublished dev repository, I actually started working on it over a year earlier, and it initially had three backends, IPC::Run3, IPC::System::Simple, and system. After fighting with exactly the situation that the other two backends were "lesser" for several months, causing me to jump through all sorts of hoops and having very complicated documentation due to the limitations of the other backends, I realized that if I wanted to give the users of my module a solid, reliable experience, then I'd have to depend on the module that provides all the features I need - of course it helps that IPC::Run3's testers matrix is very good.

I also learned the point about optional dependencies possibly not being tested through the experience with my module Shell::Tools, which actually does have five "recommends" dependencies for use in Shell::Tools::Extra. If I were re-releasing that today, I'd turn it into two distributions: Shell::Tools with its core-only dependencies, and Shell::Tools::Extra which would require all of its CPAN dependencies.

As I said above, there are of course exceptions to all this, and with "you're right to question this" I meant that one should give this some serious thought before going down that road.

Part of the problem here is that most of the literature for factory classes will be written with JAVA like languages in mind. Perl is far more TIMTOWTDI.

I agree. Although I'm far from an expert on the theory, I think Dependency inversion principle is probably an interesting and relevant read.

Replies are listed 'Best First'.
Re^5: Factory classes in Perl
by LanX (Cardinal) on Jan 12, 2021 at 13:17 UTC
    > 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"

    Do you know Term::ReadLine ?

    Perl interface to various readline packages. If no real package is found, substitutes stubs instead of basic functions.

    I have to say it was very confusing for me to see features of the debugger documented ... And they simply don't work, because the right backend is missing or can't be installed.

    Well it still is confusing.

    But overload has a good example for fall backs.

    If ".=" isn't overloaded it will fall back to the overload for "." and this will fall back to "" for stringification.

    So it's possible to work with lesser code.

    > > Part of the problem here is that most of the literature for factory classes will be written with JAVA like languages in mind. Perl is far more TIMTOWTDI.

    > I agree. Although I'm far from an expert on the theory, I think Dependency inversion principle is probably an interesting and relevant read.

    Well I tried to read thru all those https://en.wikipedia.org/wiki/Creational_pattern and I'm a bit lost.

    I don't think they translate well to Perl, that's mainly "Meta Programming" in Perl.

    It's like explaining English with alien grammar. How do you explain Latin's Locative case to people who already struggle to use "whom" even after "to" or "for" in accusative or dative cases (that's direct and indirect object, folks ;).

    So without really deeply knowing Java and UML I can't fully decipher it.

    ANYWAY

    I read the OP's example again, and it seems to explain how to write a test suite that adapts to an application with various "Deer" plugins.

    It's not up to the test suite to install the plugin it has to react to the given environment.

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      Well it still is confusing.

      That sounds to me like you agree that such "lesser code paths" like the stubs in Term::ReadLine are problematic ;-)

      overload ... So it's possible to work with lesser code.

      I don't think that's the same thing. The option fallback could have been given a better name, since what is's actually controlling is "magic autogeneration", and the operations it generates oftentimes Do The Right Thing. Plus, it has nothing to do with dependencies.

      I don't think they translate well to Perl, that's mainly "Meta Programming" in Perl.

      Yes, I think there are quite a few of these concepts that we don't see too much of in the Perl world. Although I haven't used it myself, my understanding is that Bread::Board is a Perl implementation of some of these concepts.

      It's not up to the test suite to install the plugin it has to react to the given environment.

      Well no, but my points above still stand: summarized, I personally think it's better if the module's behavior and tests are as deterministic as possible, instead of depending on whether or not a module is installed in the user's environment.