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

Re: OOP: Plugin Style Development

by dragonchild (Archbishop)
on Jul 22, 2002 at 19:11 UTC ( #184182=note: print w/replies, xml ) Need Help??

in reply to OOP: Plugin Style Development

Possibly something like:
package Display::Base; sub new sub foo sub bar ---- package Display::LDAP; @ISA = qw(Display::Base); sub new sub foo sub bar ---- package Display::DBI; @ISA = qw(Display::DBI); sub new sub foo sub bar ---- etc...

If you're wondering if the language will enforce anything OOP ... the short answer is "No". It enables OOP, but doesn't enforce it like C++, Java, and/or Smalltalk. Perl isn't an inherently OOP language.

The plug-in architecture you're describing is essentially an overloaded base class. A few caveats:

  1. If you feel the need to do a if ($display->isa('Display::LDAP')) in your client code, think long and hard. The point behind plug-ins is that you don't know which it is.
  2. Write your plug-in objects so that they ignore any data they don't need. This allows you to have data that some plug-ins might use, but not others. The client would create all data for any object anyways.

    This is best facilitated by passing hashrefs or objects around. Don't use fixed-size param lists.

  3. You seem to have done this, but I'll say it anyways. Come at the design from the perspective of what you would need to display to ANY of the formats, then create your object(s) or hashref to pass to the displayer accordingly. Don't start with one or two, then try and extend. You'll end up with some nasty Anti-Patterns.

Most importantly, if you come up with a really neat implementation, post it to CPAN.

We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Replies are listed 'Best First'.
Re: Re: OOP: Plugin Style Development
by jk2addict (Chaplain) on Jul 22, 2002 at 19:32 UTC

    Here's where the windows OOP brainwashing kicks in for me:

    package Display::LDAP; @ISA = qw(Display::Base); sub new sub foo sub bar

    If I was the one making the LDAP module, no problems. But what if someone else is doing it? What bugs me is that if I decide to start using Display::Foo instead of Display::LDAP, there's no way to know if Display::Foo is going to play nice, or ignorant for that matter.

    I was just looking at Class::Contract, but that's overkill for now

    Not to mention, if Display::LDAP overrides all the methods that Display::Base exports, then why use Display::Base at all? I've seen modules whos 'public' subs call private "_" subs inherited form the base class. But that's just like any other method, you can't assume anything about the overloaded base class. If it decides not to call the private methods from base, game's off anyways.

      There is a very good reason to use a base class. This way, you can do something like:
      die "This isn't a Display adapter!" unless $display->isa('Display::Base'); $display->doSomething(@args);

      As for your concern about contracts and enforced APIs ... Perl doesn't do that. You're just going to have to make sure with all other developers that everyone agrees on an API.

      IMHO, this is a "Good Thing"(tm). More communication between developers is good.

      You can do a few things in the base class to provide for interface checking. Here's a canonical way to implemental a virtual function:

      sub foo { my $self = shift; die "Whoever wrote '", ref($self), "' is a dork. S/He didn't overr +ide foo()!"; }
      Then, when a client expects foo() to be a method and it isn't overriden, you can take a "Clue-By-Four"(tm) to the offending author. (Something along the lines of "Why didn't you follow the agreed-upon spec?!?" Of course, you need one of those to have a leg to stand on .........)

      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

        *smacks forehead repeatedly*

        I always forget the little things, repeat after me, can() and isa() are your friends. :-P

        The more it sinks in, the more I think I like the following approach: public subs (mysub) in Base that call private subs (_mysub).

        When a module uses and overrides base, it should override the private subs. This gives me enough of a warm fuzzy about preserving the public methods signature (if only in theory).

        Is there anything wrong with this approach from the standpoint of painting myself into a corner?

        Thanks for the help, and the patience.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://184182]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (13)
As of 2018-05-23 15:07 GMT
Find Nodes?
    Voting Booth?