Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Re^3: Factory classes in Perl

by LanX (Saint)
on Jan 12, 2021 at 00:04 UTC ( [id://11126771]=note: print w/replies, xml ) Need Help??


in reply to Re^2: Factory classes in Perl (updated)
in thread Factory classes in Perl

> ...and thought - "why not just install the missing module then?"

because different "missing" modules have different interfaces !

The factory creates objects/classes with the same interface (which might themselves make use of a specialized CPAN module under the hood ... or not)

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

Tables with rows and cells are a universal concept, but the details differ a lot.

The factory could produce output-backends for

  • HTML,
  • TK,
  • Excel,
  • Word,
  • PDF,
  • SVG
  • LaTeX
  • you-name-it,

but all now with the same interface for geometry, color, font, etc.

And just supporting the features you really need for the problem at hand.

The code for the complicated table is just using the factory and doesn't need to care about the output details.

And if someone needs to target new media - like a fancy JS-library for grids - you'll just add an implementation to the factory.

I don't know if that's even possible (or how useful the feasable may be), but it's an example.

Now take a look at all the modules for Tables and ask yourself how you'd write reusable code to use multiple of them.

UPDATE

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.

In Perl I could imagine a factory "package" without any OOP involved.

Or a factory "function" (aka a generator) to create functions. (generators are actually quite common in functional programming but rarely as complex as packages)

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

Replies are listed 'Best First'.
Re^4: Factory classes in Perl
by haukex (Archbishop) on Jan 12, 2021 at 11:14 UTC
    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.

      > 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.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11126771]
help
Chatterbox?
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-04-20 11:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found