Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

Well, I disagree strongly that you should avoid OO just because the code is small. Just yesterday I wrote an OO module that was under 20 lines.

At this point, since you've not shown the need for inheritance implementation reuse or even interface reuse, I'd stay away from the complexity of objects. My personal rule is not to pull in OO technology in Perl until the line count of the program exceeds about 1000 lines, and using all the OO features of abstraction, inheritance, and data hiding all becomes useful.

Well, I find that implementation reuse and inheritance are way over emphasized in OO and almost never happen (outside of standard libraries that get shipped with the language). Although I see a small percentage of objects that do interface reuse (via inheritance), the majority don't do any of those things.

In Perl the most common big advantages I see from OO are reduction of namespace collisions and simplified compartmentalization of configuration settings (my other favorite is cleaning up via destructors, but not all objects involve such). Here we want cascading defaults (ie. compartmentalization of configuration settings), which is done very nicely and naturely in Perl OO (I've never noticed it being done nicely in Perl in the absense of OO). I find that using Perl OO almost gives you cascading defaults without even trying.

Have a package global that contains the default configuration parameters. Have a constructor that copies the configuration parameters from the package or object that was used to call it. Provide methods for changing configuration parameters (but only on constructed objects, not on the package global of sane defaults). (Heck, if writing methods seems like too much work, you can let the module user directly set the parameters using $obj->{param_name} -- though I think you'd be wrong both in thinking that writing methods is too much work and in encouraging such unverified manipulation of your object's members.)

If you want script-level defaults, then you can also make this easy by making it easy to export/import a default error object for the script (see below).

Also, a package that starts out at 20 lines could eventually grow to over 1000. Retrofitting OO at that point would be a huge pain. I wouldn't necessarilly start all projects as OO modules. But once you get to the point that you see a need to use the code from multiple scripts and that therefore it makes sense to turn it into a module, then I think it also usually (in Perl) makes sense to put in OO.

package Err; use base qw( Exporter ); use Carp qw( croak ); my( %defaults, @options ); BEGIN { %defaults= ( Title => 'An error has occurred', Message => 'If error persists, seek assistance', ); @options= keys(%defaults); } sub new { my $this= shift; # Either a package name or an object. croak 'Usage: $handle= ',__PACKAGE__,"->new();\n", ' or: $handle= $ErrHandle->new()',"\n" if @ARGV; my $class= ref($this) || $this; # Copy defaults from calling object or use standard defaults: my $obj= ref($this) ? {%$this} : {%defaults}; return bless $obj, $class; } sub import { # Export a unique $ErrHandle to each caller: my $uniq= $_[0]->new(); *ErrHandle= \$uniq; goto &Exporter::import; } sub Configure { my( $self, $opts )= @_; croak 'Usage: $ErrHandle->Configure( ', '{ Title=>"new title", Message=>"new msg" } )', "\n" unless 2 == @ARGV && ref($opts) && UNIVERSAL::isa($opts,"HASH"); my @err= grep { ! exists $defaults{$_} } keys %$opts; croak __PACKAGE__,"::Configure: Unknown option(s) ", "(@err) not (@options)\n" if @err; @{$self}{keys %$opts}= values %$opts; return $self; }

Now add a method that actually reports the error (you just had "do something" in your example). And you use it like this:

use Err qw( $ErrHandle ); # Set script-specific defaults: $ErrHandle->Configure( {Message=>"Contact technical support"} ); # Use script defaults: $ErrHandle->Report(...); # Set and use other configurations: my $accountingErrHandle= $ErrHandle->new()->Configure( {Message=>"Please notify Bob"} ); $accountingErrHandle->Report(...);

Note that you can now add a new configuration parameter by just adding one line specifying the name and default value for it. At 40 lines, it is more complex than what we started out with. But a lot of that has to do with the request for script-level defaults and some nice things I added like croak()ing when a method is called incorrectly.

In summary, I think you can write very small but reasonable OO modules when you have something that starts out very simple but that you want to use several places. I think that in the long run you'll be glad you did start out with OO.

Update: Fixed unmatched quotes in my still-thoroughly-untested sample code. Actually, I was forced to test the exporting of a unique scalar stuff before posting since I'd never actually done that before (actually).

        - tye (but my friends call me "Tye")

In reply to Re: Handling cascading defaults by tye
in thread Handling cascading defaults by markjugg

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



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?
    Username:
    Password:

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

    How do I use this? | Other CB clients
    Other Users?
    Others drinking their drinks and smoking their pipes about the Monastery: (2)
    As of 2020-12-05 12:39 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?
      How often do you use taint mode?





      Results (63 votes). Check out past polls.

      Notices?