jamroll has asked for the wisdom of the Perl Monks concerning the following question:
okay. i've been around the globe, not literally, trying to figure this module thing out. I have a basic understanding. I have been coding in perl for years, and modules have always confused me somewhat, cuz they don't seem to behave like .H files in C or .TPU files in pascal - their equivalent to .PM files.
anyway, i went to stackexchange to ask my question - what are the relationships between modules - how do they interact with each other. CAN they? etc. etc. They are NOT helpful in the slightest. The post gets flagged, and most responses are responses I already know about - cuz they've done the same searches on google i have. other say buy a book! I'm not looking to be berated, or belittled.
I'm seeking real advice on the RIGHT way to use modules in a real-world environment.
I have several .pm files stored:
bc_chef.pm
bc_dir.pm
bc_misc.pm
bc_sql.pm
date.pm
html.pm
redir.pm
search.pm
security.pm
subdesc.pm
user.pm
bc_*.pm are "base code" files, i like to call them. the intent is for these particular modules to do only what they appear to do - one does JUST sql stuff, another does just cookie stuff (that's bc_chef).
so, where's my problem? you see, most of my modules need to make sure it's handing the correct data back to the client. this means that some user.pm subroutines need access to security.pm. so i put "use pm::security;" at the top of my "user.pm" file. all's good so far, i think. building on my setup, i eventually come across things like "subroutine banned(...) is not defined". I'm like thinking how can that be. I STARE at my code and just can't figure out how "use pm::security;" in my "user.pm" module can say that "banned($$)" is not defined, when it's right here in the security.pm file! makes NO SENSE! So, I get clever, you see, and I remove "use pm::security;" clause from "user.pm" and update all the references to subs in security by adding "pm::security::" to those calls. SAME error!
I clearly am missing something very fundamental to modules, but I can't, for the life of me, figure out why this is going on.
I can post some of the code (i'd have to redact a few things in many subs), but i'm willing to post code in order to gain insight into the intricacies of modules.
unless i have the concept down without knowing it, i'm feeling so lost, guys. pls don't be like stackexchange guys and flag this as "too broad" and pls don't tell me to get a dang book. none of that stuff is at all helpful.
i have scoured every site and document i can find on google, and here, and there and everywhere. most just talk about a single module. never do they say whether other modules can interact with each other, or what the relationships are.
i do understand, however, perl modules are collections of subs - related, and/or unrelated to each other. like subs, though - can a module include another module. the simple answer is yes. but, i don't understand how that relationship works.
Bottom line - i'm lost on modules and could really use some input on the finer details of modules.
thank you very kindly
Jarett
edit: (wow! what happened to my "paragragphs"? why did this thing take away my line spacing? it looks awful, drat)
edit: there, i fixed the paragraph bit, after i noticed i have to add that silly p tag
Re: Perl Modules
by stevieb (Canon) on Jun 20, 2017 at 16:05 UTC
|
It is terribly difficult to read your post as is, so I didn't. However, I've put together an example of what I think you're after. The first file is the script itself, which uses the A module (A.pm in the local directory). The A module exports a single function, and this module includes the B module which also exports a single function. It in turn uses the C module, which exports a single function, which prints an incoming string.
a_func() takes a single parameter, a string. It passes it to b_func(), which then passes it to c_func() which then prints it to the screen.
The flow is like this:
script
-> A::a_func("str")
-> B::b_func("str")
-> C::c_func("str") # c_func is what prints the data
The script:
use warnings;
use strict;
use lib '.';
use A qw(a_func);
a_func("a string");
The A module:
package A;
use lib '.';
use B qw(b_func); # load the 'B' package
use Exporter qw(import);
our @EXPORT_OK = qw(a_func);
sub a_func {
my $str = shift;
b_func($str);
}
1;
The B module:
package B;
use lib '.';
use C qw(c_func);
use Exporter qw(import);
our @EXPORT_OK = qw (b_func);
sub b_func {
my $str = shift;
c_func($str);
}
1;
The C module:
package C;
use Exporter qw(import);
our @EXPORT_OK = qw(c_func);
sub c_func {
my $string_to_say = shift;
print "$string_to_say\n";
}
1;
| [reply] [d/l] [select] |
|
my apologies re the ugly post, initially. i hadn't noticed i needed to add the p tag...weird to have to add it. anyway. thank you for your reply. i honestly will review it in depth. i have a goal to meet, and the more info i can suck up the better. so your reply is very useful, and spot on track with what i need - despite the initial post being a nightmare to read lol. very cool
| [reply] |
|
Real world example?
Here's the source code for a module that pretty much only usees external modules, and each subroutine generates an object of the external module classes, then returns that object.
Take a look at the dac() sub for instance... it creates a new object of class RPi::DAC::MCP4922, which is in an external, separate module. That module is used on this line.
There are no exports in this case, because the majority of the code is Object Oriented, meaning that the functions don't need to be imported; the subs are methods of the object that was returned.
The RPi::DAC::MCP4922 module itself relies on modules of its own, namely it uses a core external API library. Notice that this use statement does import explicitly, in this case *all* of the functions that are exported by that API module. The API module then requires/uses other external modules, but only Exporter to be able to export the functions , and XSLoader to load the C/XS code that it requires.
Example:
my $pi = RPi::WiringPi->new;
my $dac = $pi->dac(
model => 'MCP4922',
channel => 0,
cs => 18,
);
my ($dacA, $dacB) = (0, 1);
$dac->set($dacA, 4095);
$dac->set($dacB, 0);
So you instantiate a new top-level RPi::WiringPi object, then call its dac() method. It then makes a call to RPi::DAC::MCP4922's new() method which returns an object of its own class. Then once the object is returned to the top-level object, it in turn returns it to you.
In this case its a convenience thing. We include the necessary external classes and hide away the need for you, the caller script from having to use the module directly, and manually writing the DACs instantiation code within the script.
Make sense? | [reply] [d/l] [select] |
|
|
|
Re: Perl Modules
by thanos1983 (Parson) on Jun 20, 2017 at 16:05 UTC
|
Hello jamroll,
Your description is very open, you are saying that you have all these modules that you are trying to call. Did you implement all these modules yours self? Do you have a main script eg. main.pl that calls the modules in the directory?
For example pseudo code main.pl
#!usr/bin/perl
use strict;
use warnings;
use pm::security;
print banned(...); # This is how you are calling the method and you ar
+e getting the error?
How you export your methods? Have you read Simple Module Tutorial
We need to see at least one module and how you have define it, how you are calling it and see why you are not able to access your methods.
Provide us all these data with well formatted output and we will be more that happy to provide assistance.
Update: Sample of your module to get you started:
Perl module (Security.pm) inside your directory Pm. Path to the module is (local dir of main.pl module Pm/Security.pm)
package Pm::Security;
use strict;
use warnings;
use Exporter;
use vars qw($VERSION @ISA @EXPORT_OK);
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT_OK = qw(banned);
sub banned { return reverse @_ }
1;
Main module (main.pl)
#!usr/bin/perl
use say;
use strict;
use warnings;
use Pm::Security qw( banned );
# use Benchmark qw(:all) ; # WindowsOSn
# use Benchmark::Forking qw( timethese cmpthese );
my @list = qw (First ~ Second);
say banned( @list );
__END__
$ perl main.pl
Second~First
Hope this helps, BR
Seeking for Perl wisdom...on the process of learning...not there...yet!
| [reply] [d/l] [select] |
|
and i know the title of this thread is vague. i have no clue how title my current conundrum....let alone describe it well enough (or in jargon) for you to completely understand in my first posting. i'm terribly sorry about that. it's not meant to intentionally mislead, even if it does mislead a tad. i just have no words to describe succinctly the issue at hand.
| [reply] |
|
alright. i'll post some code. the relevant stuff. it'll be large, i'm sure...that's why i didn't post code in the first place. i'm seeking general information - problem is i can't articulate into words what I'm having difficulty with. with that said, it is imperative i figure this out, so i'll do exactly what you guys need to help me, and i will pay great attention. oh! let me just say this - jargon often escapes me. simple jargon doesn't, but if the jargon starts getting real technical, jamroll tends to get lost...so i adhere to the KISS principle like flies on ... stuff.
i may redact some areas of the code for security purposes.
i'll point out that i don't use caps very often, as you can see. i don't much care to hit shift that much. i recognize the convention is to upcase the first char of a module (Security instead of security, for example) - but is that just a convention, or a hardcoded rule?
all of the modules in pm:: are my own creation! the modules are stored in D:/Apache24/htdocs/pm/
i try to avoid having to use other's packages (that requires learning their way, and since i'm so very deep into this project, incorporating something new would be an entirely grandiose endeavor - no, i'm kinda stuck with the structure i'm laying out here)
so, firstly, this is the error message i get (happens everywhere, too - not JUST with this example):
Software error:
Undefined subroutine &pm::security::banned called at pm/user.pm line 1
+36
so here's the ALL of the code that is generating this error (like i said, this could be big)
user.pm - d:/apache24/htdocs/pm/user.pm
##########################
package pm::user;
##########################
#/
# Encapsulates all user related functions
# these routines do NOT require a DBH
# the DB is connected to automagically!
#/
##########################
use strict;
use CGI::Carp qw(fatalsToBrowser);
use URI::Escape;
use Exporter;
use vars qw($VERSION @ISA @EXPORT);
##########################
##########################
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(
_tests
blockedUser
check_user_stats
get_uid_byNickname
get_user_age
get_user_blocked_users
get_user_city
get_user_country
get_user_dp
get_user_friend_requests
get_user_friends
get_user_fuck_alert_count
get_user_message
get_user_messages
get_user_pic
get_user_pics
get_user_stat
get_user_stats
get_user_stats_asIcons
get_user_subscription_type
get_user_theme_data
get_user_unread_messages
get_users_emails
get_users_nicknames
isUser
isUserAdmin
isUserBday
isUserModerator
isUserSubscriber
isFriend
set_user_stats
user_paid_expired
nickname_in_use
email_in_use
);
##########################
##########################
my $loggedin = pm::bc_chef::cookie_get("loggedin");
my $db = pm::bc_sql::sql_connect("ns.db");
##########################
# this is just one sub. as you can see there are TONS of subs...
##########################
sub get_user_blocked_users($) {
#*
# gets a list of blocked users for the specified user
# can return an empty array
#*
my ($uid) = @_; # a uid
my @blocks = ();
my $results = pm::bc_sql::sql_execute($db, "select BID from blocks w
+here UID = " . $db->quote($uid)); # could be a single hash ref, or a
+ref to an array
if (ref $results eq "HASH") {
if (pm::bc_sql::user_exists($db, $results->{BID}) and not pm::secu
+rity::banned($db, $results->{BID})) { push @blocks, $results->{BID};
+}
} elsif (ref $results eq "ARRAY") {
foreach my $ref (@$results) {
if (pm::bc_sql::user_exists($db, $ref->{BID}) and not pm::securi
+ty::banned($db, $ref->{BID})) { push @blocks, $ref->{BID}; }
}
} else {
return undef;
}
return @blocks; # an array of blocked uid's
#usage: my @blocked_users = get_user_blocked_users($uid);
}
#...
1;
and related code for the function calls within the above module's sub. which are:
sql_execute, user_exists, and banned
pm::bc_sql::sql_execute(...) is my own flavor of the execute command (and i'm certain, nay, i know it's is badly done) - but it works! so, it stays as is for now
bc_sql.pm - d:/apache24/htdocs/pm/bc_sql.pm
package pm::bc_sql;
#/
# a module for manipulating an SQLite DB on
# Apache in a Windows 10 environment
#/
########################
use strict;
use warnings;
use Exporter;
use vars qw($VERSION @ISA @EXPORT);
use CGI::Carp qw(fatalsToBrowser);
########################
use DBI;
########################
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(
_tests
sql_connect
sql_create_perchie
sql_create_random_user
sql_db_user_reset
sql_db_valid
sql_disconnect
sql_execute
sql_execute_bound
get_about_page
get_body_asWord
get_cities
get_city_id
get_city_name
get_config
get_constant
get_constants
get_country_cities
get_country_id
get_country_id_byName
get_country_name
get_countries
get_default_theme
get_errors
get_eye_clr_asWord
get_gender_asWord
get_hair_clr_asWord
get_height_asWord
get_help_page
get_home_page
get_location
get_navbar
get_orientation_asWord
get_phrase
get_profile_views_count
get_race_asWord
get_security
get_security_asWord
get_seeking_asWord
get_site_name
get_theme_data
get_themes
get_users
get_weight_asWord
get_zodiacs
set_config
set_constant
is_friend
is_admin
is_subscriber
is_moderator
ban_exists
ccid_exists
fma_exists
ipn_exists
msg_exists
msgs_exist
theme_exists
user_exists
sql_get_user_stat
in_maint
new_uid
new_tid
new_ccid
read_text
validate_new_user_data
valid_id
valid_ip
valid_date
valid_config
);
########################
########################
sub sql_execute($$) {
#*
# runs an SQL statement on the supplied db.
# must be connected, and <b>must</b> <a href='#sql_disconnect'>sql_d
+isconnect</a> to commit changes.
# a reference to an array of hash references can be returned
# if only one item is in the array, then we give a hash ref instead
# of a one element array reference
# (which is a hash reference in and of itself)
# three different return values: scalar, array ref, or hash ref
# - dependent on # of results, or kind of sql statement (insert, c
+reate, update,
# select, delete, etc)
# !this function does not and will NOT "sanitize" your query - that'
+s your job!
# for instance: my $sql = "select * from users where ID = " . $db->q
+uote($uid);
# note: this function should only have one return statement at its e
+nd...not
# several strewn throughout the code like it is here. this will be
+updated
#*
my ($db, $sql) = @_; # the dbh && the SQL statement
my $prept = $db->prepare($sql);
if ($sql =~ /^insert |update |delete /i) {
my $rv = $db->do($sql) or die $db->errstr;
if ($rv eq undef) { $rv = 0; }
if ($rv eq "0E0") { $rv = 0; } # yes. a failure. insert update a
+nd delete ought to affect at least one row.
return $rv; # 0 on failure, 1 on success
} elsif ($prept) {
$prept->execute();
# now, grab all the results from the query, and dump them into an
+array as hash references to each "hit"
my @arr = ();
while (my $row = $prept->fetchrow_hashref) { push @arr, $row; }
if (@arr eq 1 and $arr[0]) {
# if the array has only one element, then, it's kinda pointless
+to give a ref to the array
# so instead, let's just give back that hash reference
my $hashRef = $arr[0]; # this ought to be a hash reference, no?
return $hashRef; # a hash reference when there is only one array
+ element
}
if (@arr eq 1 and ref $arr[0] ne "HASH") {
# if the array has only one element, and it's not a hash referen
+ce (meaning $arr[0] =~ /0e0/i)
# then ...
@arr = (); # clear the array
}
return \@arr; # an array reference (can be a zero element array),
+or
} else {
return \(); # a reference to an empty array when no results, or qu
+ery failed
}
#usage: my $rv = sql_execute($db, $sql);
}
########################
sub user_exists($$) {
#*
# determines if a user exists or not
#*
my ($db, $uid) = @_; # a DBH && a user ID
my $sql = "select ID from users where ID = " . $db->quote($uid);
my $uref = sql_execute($db, $sql);
if (ref $uref eq "HASH") {
return 1; # 1 when user exists
} else {
return 0; # 0 when user does not exist
}
#usage: if (user_exists($uid)) { print "$uid exists"; }
}
# ...
1;
security.pm - d:/apache24/htdocs/pm/security.pm
package pm::security;
#/
# a module to encapsulate security-related functions
#/
use strict;
use Exporter;
use vars qw($VERSION @ISA @EXPORT);
use CGI;
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT = qw(
_tests
banned
bounced
get_salt
password_correct
password_set
get_client_IP
login
logout
);
######################################################################
+##########################
######################################################################
+##########################
######################################################################
+##########################
########################
sub banned($$) {
#*
# gets the banned status of a uid
# !this function requires updating
# the code in this function needs to
# conform to a more basic format
# there should only be one return!
#*
my ($db, $uid) = @_; # a DBH && a uid
my $query = "select banned from users where ID = " . $db->quote($uid
+);
my $result = pm::bc_sql::sql_execute($db, $query); # should result i
+n a 0 or a hash with one key: a UID
# $result is a hash reference
if (ref $result eq "HASH") {
if ($result->{banned} eq 2) {
return 1; # 1 when the user is banned
}
}
return 0; # 0 when the user is not banned
#usage: if (banned($db, $uid)) { print "yer banned, bitch"; }
}
i think that covers the meat of it...
i have removed all use pm::xxx; statements in the actual code, and just copied it to here. i have also tried removing pm::xxx:: before my function calls when the corresponding module has "use pm::xxx;" in it. i get the same error as what's above in other places (not just ::banned does exist - but sometimes sql_execute doesn't exist). it's all very very confusing to me. i don't understand even why the error message appears...and sorry it took so long to reply. had to make sure i covered my bases, dotted my T's and crossed my eyes!
| [reply] [d/l] [select] |
|
package pm::mytest;
sub message {
return 'Hello from pm:mytest';
}
1;
and a script that uses it
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
use CGI::Carp 'fatalsToBrowser';
use lib 'd:/apache24/htdocs';
use pm::mytest;
my $msg = pm::mytest::message();
my $q = CGI->new;
print $q->header,$q->start_html,
$q->h1($msg),$q->end_html;
poj
| [reply] [d/l] [select] |
|
|
|
|
Package names are sometimes an exception to this rule. Perl informally
+ reserves lowercase module names for ``pragma'' modules like integer
+and strict. Other modules should begin with a capital letter and use
+mixed case, but probably without underscores due to limitations in pr
+imitive file systems' representations of module names as files that m
+ust fit into a few sparse bytes.
Having said that I would recommend renaming the directory to Pm/Security the same applies to the rest of the modules that you are using. Let's move on to the next problem, calling the module.
You are saying that you have a main.pl script that gives you the error:
Undefined subroutine &pm::security::banned called at pm/user.pm line 1
+36
Let's try to replicate the problem. I am creating the directories as you say d:/apache24/htdocs/pm/user.pm
I would modify a bit your module so I would recommend to do the same on the rest of your modules. First of all I use also use warnings; for many reasons make your code more safe. Second from the Perl documentation Exporter/Selecting What to Export:
Do not export anything else by default without a good reason!
Exports pollute the namespace of the module user. If you must export t
+ry to use @EXPORT_OK in preference to @EXPORT and avoid short or comm
+on symbol names to reduce the risk of name clashes.
Having said that I modify your Export to Export_OK. On your modules you need to close them with 1;. Why? Read the perlmod/Making your module threadsafe:
If it returns a true value, then no objects of that class will be clon
+ed; or rather, they will be copied as unblessed, undef values.
If this is not enough also read Perl Module ending without 1;. Having said that I add also 1; at the end of your module.
Sample of your module based on the modifications that I propose Security.pm in the directory of my local PC /home/tinyos/apache24/htdocs.
package Pm::Security;
#/
# a module to encapsulate security-related functions
#/
use CGI;
use strict;
use warnings;
use Exporter;
use vars qw($VERSION @ISA @EXPORT_OK);
$VERSION = 1.00;
@ISA = qw(Exporter);
@EXPORT_OK = qw(
_tests
banned
bounced
get_salt
password_correct
password_set
get_client_IP
login
logout
);
######################################################################
sub banned {
#*
# gets the banned status of a uid
# !this function requires updating
# the code in this function needs to
# conform to a more basic format
# there should only be one return!
#*
# my ($db, $uid) = @_; # a DBH && a uid
# my $query = "select banned from users where ID = " . $db->quote(
+$uid);
# my $result = pm::bc_sql::sql_execute($db, $query); # should resu
+lt in a 0 or a hash with one key: a UID
# $result is a hash reference
# if (ref $result eq "HASH") {
# if ($result->{banned} eq 2) {
# return 1; # 1 when the user is banned
# }
# }
return reversed @_; # 0 when the user is not banned
#usage: if (banned($db, $uid)) { print "yer banned, bitch"; }
}
1;
Now that we have defined and applied minor modification to your module let's try to call it for execution from our main.pl:
Sample of main.pl script, remember the path is relevant to my local PC but it should work for your PC with minor modifications:
#!usr/bin/perl
use say;
use strict;
use warnings;
use lib '/home/tinyos/apache24/htdocs';
use Pm::Security qw( banned );
my @list = qw (First ~ Second);
say banned(@list);
__END__
$ perl main.pl
Second~First
A minor detail to add here I call the script from a different directory where the dir Pm is located. I manage to do that by using the lib module. If I comment out this line # use lib '/home/tinyos/apache24/htdocs'; I get the following expected error:
$ perl main.pl
Can't locate Pm/Security.pm in @INC (you may need to install the Pm::S
+ecurity module) (@INC contains: /home/tinyos/perl5/lib/perl5/5.24.1/x
+86_64-linux-gnu-thread-multi /home/tinyos/perl5/lib/perl5/5.24.1 /hom
+e/tinyos/perl5/lib/perl5/x86_64-linux-gnu-thread-multi /home/tinyos/p
+erl5/lib/perl5 /etc/perl /usr/local/lib/x86_64-linux-gnu/perl/5.24.1
+/usr/local/share/perl/5.24.1 /usr/lib/x86_64-linux-gnu/perl5/5.24 /us
+r/share/perl5 /usr/lib/x86_64-linux-gnu/perl/5.24 /usr/share/perl/5.2
+4 /usr/local/lib/site_perl /usr/lib/x86_64-linux-gnu/perl-base) at ma
+in.pl line 7.
BEGIN failed--compilation aborted at main.pl line 7.
Of course it is because Perl is not aware of my Pm::Security module that I have defined in my directory.
One last question, why you are calling your function as sub banned($$) I was looking online regarding this because I never used it before and I found perlvar/General Variables:
LinuxThreads is now obsolete on Linux, and caching getpid() like this
+made embedding perl unnecessarily complex (since you'd have to manual
+ly update the value of $$), so now $$ and getppid() will always retur
+n the same values as the underlying C library.
If this is the case why don't you call getppid instead of $$. Maybe I am wrong regarding this point so another Monk could share some knowledge.
Hope this provides you enough information to resolve all of your module(s) problems.
Seeking for Perl wisdom...on the process of learning...not there...yet!
| [reply] [d/l] [select] |
|
|
|
|
|
|
|
Re: Perl Modules
by hippo (Bishop) on Jun 20, 2017 at 15:53 UTC
|
pls don't tell me to get a dang book. none of that stuff is at all helpful.
Try Ulysses - I think you'd enjoy it. (Edit: the parent post has subsequently been amended to introduce some formatting thus making this reference rather more obscure)
so i put "use pm::security;" at the top of my "user.pm" file. all's good so far, i think. building on my setup, i eventually come across things like "subroutine banned(...) is not defined". I'm like thinking how can that be. I STARE at my code and just can't figure out how "use pm::security;" in my "user.pm" module can say that "banned($$)" is not defined, when it's right here in the security.pm file! makes NO SENSE!
See Exporter or just call the sub via the full name eg: pm::security::banned ($foo, $bar)
Other things to read: perlmod and package. Also Coping with scoping.
| [reply] [d/l] |
|
oh yes. i am using exporter, don't get me wrong there. always.
| [reply] |
|
Well, here's an SSCCE showing chained packages, one of which is an Exporter, the other not. Compare and contrast.
#!/usr/bin/env perl
use strict;
use warnings;
package pm::security;
use Exporter;
our @ISA = ('Exporter');
our @EXPORT = ('banned');
sub banned {
print "Banned: @_\n";
}
1;
package user;
pm::security->import; # If in separate files, "use pm::security;" will
+ do.
sub do_stuff {
# We call banned without its package prepended because banned is
# exported by package pm::security
banned (@_);
}
1;
package main;
# If in separate files, "use user;" here
# We call do_stuff with its package prepended because do_stuff is not
# exported by package user.
user::do_stuff ('foo', 'bar');
If your packages behave differently then you'll have to provide a similar SSCCE displaying the precise problem in order for others to help you get to the bottom of it. | [reply] [d/l] |
|
Re: Perl Modules
by Sinistral (Monsignor) on Jun 20, 2017 at 16:05 UTC
|
| [reply] |
|
i'm not opposed to books. they are great. i've read many. the one you suggest is not one i have read. so ... i will check it out. most folks generally point me in the direction of the tutorials and documents one can easily find. but, none address the issue i'm having. most just talk about one module, and not many that interact together and require each other in circus - sometimes two modules need each other in order to do their job. i think this is the underlying problem i'm having, but i can't be 100% certain. mainly because I lack a group of friends whom i can have a face to face conversation with. one man band kinda sucks, but i'm determined to get this site up and going!
| [reply] |
|
hello jamroll,
your thread is long and somehow confusing, but here you say something that captured my attention:
> many that interact together and require each other in circus
First some firm stone, to not let confusion overhelm us: Some::Module must be in Some/Module.pm and this path must be in @INC or added to it at runtime using -I perl switch. See perlmod (and perlrun for the perl switch). Also notice that you (i think is not a constrain but more a convention) you start Some::Module declaring a package with the same name package Some::Module; ( PS read tobyink's wise advices in Re: Module's name and file's name )
Second: the easy way is to use Exporter; and fill @EXPORT_OK with every sub you want to be usable (with use ..) by other programs or modules. All sub you put in @EXPORT will be exported by default, generally not what you want.
After this basic level abstraction will be the keyword. I have a little experience but when I ended with a tools.pm module as a an unorderd collection of subs i know i was on the looser path.
For such reason choosing rigth names(spaces) for your modules is so hard, generally harder than choosing sub names. They reflect how you approached the problem/subject you'll resolve with you programs. In more complex cases you can have entire trees of modules with the deeper ones specializing the parent: like Project::Display will be responsable to compose messages to be shown and Project::Display::Console and Project::Display::HTML will handle differnt display types.
Nothing bad if Project::Logger uses a facility sub you defined in Project::Display .If you are always sure where you put your subs and you export the sub correctly everybody is happy.
Once a wise programmer said "progrimming is a matter of interfaces" and is true. A lot true. If your module just exposes a mixed collection of beahviours this will no matter a lot. But when you find that some subs in your module are, and possibly must remain, private to such module, you are implicitly thinking an interface.
Consider having a Project::Postman that is used to send out mails: the module can just expose one or few subs but can have dozen of private subs to check mail addresses, availability of smtp servers.. Less you expose and as much as this remain stable, more you will be able to change internally Project::Postman without braking any program that uses, consumes your module.
More you stress this in your programs more you tend to just expose one sigle sub that return a scalar, or an object if you want, that is autosufficient and knows who it is and what behaviour to put in the field.
As much will be easy for you to do such name/functionality abstraction, as much you'll be closer to Object Oriented programming, easy to realize using Perl, with or without OO frameworks.
As always you have a lot of different options you must follow your inclination or needs of particular projects.
L*
There are no rules, there are no thumbs..
Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
| [reply] [d/l] [select] |
|
|
|
Re: Perl Modules
by runrig (Abbot) on Jun 20, 2017 at 15:50 UTC
|
(wow! what happened to my "paragragphs"? why did this thing take away my line spacing? it looks awful, drat)
Use html paragraph (<p></p>) tags.
| [reply] [d/l] |
|
|