shmem has asked for the wisdom of the Perl Monks concerning the following question:

Surely this has been handled long ago and far away. Maybe I didn't notice, maybe I forgot, I am getting old.
So, is it bad practice to have multiple packages at different paths implementing the same methods according to the configuration of the requiring package?

Say, I have some application which needs auth methods, search and such and can be configured to either use some X500 implementation (e.g. LDAP, AD) or database stuff. Is it sensible to

if($config{X500}) { require Users::LDAP; } elsif ($config{DB}) { require Users::DB; } elsif (...) { ... } else { die "no suitable User handling module found\n"; }

and have Users/{LDAP,DB,...}.pm which all implement Users via package Users; ?

Which each sport:

package Users;

Well, I could have a "Users" package which gets the configuration object passed in upon import and does what it should. What do you think is best? Glove this or that way turned in or out?

Well yes, polymorphism, signatures and such... how would you handle that case?

perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'

Replies are listed 'Best First'.
Re: packages (Classes) and file names
by Fletch (Bishop) on Mar 02, 2023 at 17:16 UTC

    Were I doing this w/Moose (or other Moose-ish package like e.g. Moo) I'd think you'd have maybe a role UserAuthProvider (or maybe User::AuthProvider depending on how you want to structure things) that requires providing whatever methods, and then your individual implementation classes include the role with 'User::AuthProvider' and implement the required methods.

    Edit: And aside from role vs subclass this is pretty similar to the subclass-and-factory suggestion above.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: packages (Classes) and file names
by NERDVANA (Priest) on Mar 02, 2023 at 15:22 UTC
    It's not "wrong" per-se, but you get more capability from it if you define sub-classes with a package matching the file name. Consider the case where someone wants to connect to both active directory and their database and compare the two. With separate classes a user can make one object of each kind, but if you make dynamic extensions for a single class then the user is limited to one implementation per process.
Re: packages (Classes) and file names
by shmem (Chancellor) on Mar 01, 2023 at 22:58 UTC

    Memory is coming back. The LDAP, DB, ... code belongs into subclasses, and the Users class has to figure out and die if some needed methods are not implemented in the required subclass. Sorry folks, but here you can see what two years without programming (perl) does to an average brain.

    Maybe it's time to go to urinate at the chestnut. The circus is approaching. My dog is calling me out.

    perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
      An alternate approach to to do it this way:
      • User::Base <- base class that implements the default methods
      • User::{DB,LDAP,...} <- inherit from User::Base and provide specific implementations
      • User <- Factory class that inspects the details and returns the right class
      my $user = User->new( system => 'LDAP' , ...); # $user isa User::LDAP
      --
      Clayton
Re: packages (Classes) and file names
by BillKSmith (Monsignor) on Mar 03, 2023 at 14:05 UTC
    I think that you confusion has more to do with "Object Oriented Programming" than with perl's implementation of it. Under "Structured Programming", it would make sense to call different subroutines, depending on configuration. Your scheme would be a reasonable implementation. Under "Object Oriented", objects that behave differently are not members of the same class. You can use subclass to model objects that are almost alike. NERDVANA has outlined a perl implementation of your problem under this scheme.
    Bill
      «…objects that behave differently are not members of the same class»

      Not necessarily:

      use Monk; use Role::Tiny; … $karl = Monk->new; $bill = Monk->new; Role::Tiny->apply_roles_to_object($karl, qw(Nose)); Role::Tiny->apply_roles_to_object($bill, qw(Cuke)); …

      It is safe to assume that we behave differently. Regards, Karl

      «The Crux of the Biscuit is the Apostrophe»

        In the original post, I recognized my own confusion with anything "Object Oriented". I am not surprised that my explanation is not quite right. I hope that I have motivated shmem to look in the right place for the explanation of his problem.
        Bill