http://www.perlmonks.org?node_id=451771


in reply to To module or not?

Aside from namespace there's also other concerns, like kiat before me mentioned, such as code reusability, maintainability etc.

To give a practical example from my own experience, a while ago I asked the esteemed monks for help on a problem concerning unbuffered socket reading. Some really good advice was given there(as always), and I decided to set out to create my own way of reading unbuffered socket data into an artificial buffer so as to process it on a line by line basis. But, the solution I was going to create for this might very well be something I'd want to use elsewhere as well, hey, someone else might even have use for it, so it made sense to give the solution its own package.(reusability) Besides, the entire solution was probably going to be a rather sizable chunk o' code which I really didn't want to have half way my main project when I could have it conveniently tucked away in its own little corner.(maintainability). An additional advantage to it being its own module is that if for some reason I were in a crunch for time(which I am not, considering Perl is a project of love, not work-related for me) I'd be able to deploy what I have now and set out to improve the underlying code later on without having to change the calling script.

As a side note to your own example, note that quite often it is completely unnecessary to use Exporter at all. It can be convenient, often even appropriate, but hardly ever necessary.

Anyway, after this rather sizable rant *grin* here's the actual module just to give you an idea. It's mostly untested and still under development, so don't hold it against me ;-)

package IO::Buffer; use strict; use warnings; use Carp; ################# # Class Methods # ################# sub new { my $self = bless({}, shift); @{$self->{'queue'}} = (); #an array that will hold complete + lines $self->{'fract'} = ''; #a scalar to store a fragment of +a line $self->{'size'} = 1024; #default amount of bytes read per + sysread() return $self; } ################## # Object Methods # ################## sub set_handle { my($self, $fh) = @_; unless(ref($fh) eq 'GLOB') { carp "argument to \'new\' must be a filehandle"; return; } else { $self->{'fh'} = $fh; return 1; } } sub set_size { my($self, $size) = @_; unless($size =~ /^\d+$/) { carp "argument to \'set_size\' must be integer"; return; } else { $self->{'size'} = $size; return 1; } } sub sysreadline { my $self = shift; my($chunk, @lines); #if there still are lines in the queue, simply shift one off and ret +urn it if(@{$self->{'queue'}}) { return shift(@{$self->{'queue'}}); } #otherwise attempt to perform a sysread on the filehandle and proces +s the data # if the read fails it will return 0 for end of file or undef for a +read error # while setting $! to the reason for the error unless(my $read = sysread($self->{'fh'}, $chunk, $self->{'size'})) { return $read; } #the sysread was succesful, so let's move on @lines = split(/\r\n|\r|\n/, $chunk); #if the first character of $chunk is a newline, then what we current +ly have listed as a broken line # from the last read is in fact a regular full line, so we can go ah +ead and add it to the queue. if(($chunk =~ /^[\r\n|\r|\n]/) && ($self->{'fract'})) { push(@{$self->{'queue'}}, $self->{'fract'}); $self->{'fract'} = ''; } #otherwise if we still have a broken line sitting around, merge it w +ith the first line of @lines # and then add it to the queue if($self->{'fract'}) { push(@{$self->{'queue'}}, $self->{'fract'} . shift(@lines)); $self->{'fract'} = ''; } #if the last character of $chunk is a newline, then there is no actu +al broken line in this batch, # so we can simply process all the lines in order. otherwise make su +re the last line in $chunk is # treated as a fragment unless($chunk =~ /[\r\n|\r|\n]$/) { $self->{'fract'} = pop(@lines); } #now simply push all of @lines into the queue push(@{$self->{'queue'}}, @lines); #and last but not least, return the first line of the queue return(shift(@{$self->{'queue'}})); } 1;
Remember rule one...