CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Intermediate:
To OO or not to OO

 



yapp
User

Mar 6, 2002, 6:14 AM

Post #1 of 13 (2335 views)
To OO or not to OO Can't Post

I'm thinking of converting my Forum into an OO module style version. Currently, there are a lot of .pl files located in a special directory, loaded when required, (using require). It works perfectly, but isn't so flexible.

I want some my CGI scripts to be able to access the forum datahanding core., so:
- A topic can also be posted through the the contact us mailform aswell.
- A visitors online text can be displayed everywhere, and so on.

In my current situation that would mean I have to load several files, implement some subroutines and declare 50 variables with use vars into the script that acts as an interface to the forum.

Recently I've mastered the basics of OO in Perl (I've leared much about OO in the Java language at school) However, I am very confused there is no regular syntax in Perl to use OO. (maybe I can write a module for it, or does that already exist?)

Any tips, recommendations, do's and don'ts??

Yet Another Perl Programmer

_________________________________
~~> [url=http://www.codingdomain.com]www.codingdomain.com <~~
More then 3500 X-Forum [url=http://www.codingdomain.com/cgi-perl/downloads/x-forum]Downloads! Cool

(This post was edited by yapp on Mar 6, 2002, 6:21 AM)


Jasmine
Administrator

Mar 6, 2002, 12:25 PM

Post #2 of 13 (2325 views)
Re: [yapp] To OO or not to OO [In reply to] Can't Post

No regular syntax to use OO? Hrm. Not true, unless I'm mistaken about what you meant by that.

The first thing I'd suggest is to grab Damian Conway's excellent Object Oriented Perl. For lack of time or funds, head over to [url=http://perldoc.com]perldoc.com and read [url=http://perldoc.com/perl5.6.1/pod/perlboot.html]the Beginner's OO tutorial, the more in-depth OO tutorials ([url=http://perldoc.com/perl5.6.1/pod/perltoot.html]part 1 and [url=http://perldoc.com/perl5.6.1/pod/perltootc.html]part 2), [url=http://perldoc.com/perl5.6.1/pod/perlobj.html]Perl objects, [url=http://perldoc.com/perl5.6.1/pod/perlbot.html]Perl OO tricks and examples and maybe even [url=http://perldoc.com/perl5.6.1/pod/perltie.html]Perl objects hidden behind simple variables.

With that many variables, I'd throw it into its own module as a hashref and make a sub to initialize it. Something like this:

[perl]use MyModule::vars;

my $vars = MyModule::vars->init();
[/perl]

You can also export all of the vars into the caller's namespace, but with that many vars, that's a bit of namespace clutter and invites clashing (IMHO, of course).

Because I'm not so busy today, here's a relevant example of OO and maybe a little inheritance for those who may not have delved into OO yet:

First, here's a tiny program that'll receive email posts (guess you'll be using procmail or some other way to alias a specific email address to this program).
[perl]#!/usr/bin/perl -w
# let's call this mailpost.cgi

use strict;
use Topic::Submit::Email;

my $message = Topic::Submit::Email->new( messagetype => 'mail' );

my $success = $message->post();

if ( $success ){
# do something, if you want
}
else {
# do stuff when successfully posted. Maybe create a sub in
# Topic::Submit::Email that will email the user with the reason
# for failure
}

[/perl]
Now, here's another tiny program that'll receive posts from a website:
[perl]#!/usr/bin/perl -w
# let's call this sitepost.cgi

use strict;
use Topic::Submit::SitePost;

my $message = Topic::Submit::SitePost->new( messagetype => 'site' );

my $success = $message->post();

if ( $success ){
# do stuff when successfully posted
}
else {
die "Nope. Didn't post.";
}

[/perl]

Not much different, huh :) The magic is in the modules...

Topic::Submit
Topic::Submit::SitePost
Topic::Submit::Email


Here's Email.pm, which you use when receiving posts by email:

[perl]package Topic::Submit::Email;

use Topic::Submit;
our @ISA = qw/ Topic::Submit /;

sub new{
my ( $class, %args ) = @_;
bless{
messagetype => $args{ 'messagetype' },
}, ref( $class ) || $class;
}


sub post {
my ( $self ) = @_;
my ( $username, $subject, $message ) = _parse_email();

my $newpost = Topic::Submit->new(
username => $username || 'Anonymous',
subject => $subject,
message => $message,
);

$newpost->commit_post() or return 0;

return 1;

}

sub _parse_email{
# subroutine to extract post information from email.
}

1;[/perl]

Here's SitePost.pm, which you'll use if you're receiving posts from a website:

[perl]package Topic::Submit::SitePost;

use CGI;
use Topic::Submit;

our @ISA = qw/ Topic::Submit /;

my $in = CGI->new();

sub new{
my ( $class, %args ) = @_;
bless{
messagetype => $args{ 'messagetype' },
username => $in->param( 'username' ) || 'Anonymous',
subject => $in->param( 'subject' ),
message => $in->param( 'message' ),
}, ref( $class ) || $class;
}


sub post{
my $self = shift;

my $newpost = Topic::Submit->new(
username => $self->{ 'username' },
subject => $self->{ 'subject ' },
message => $self->{ 'message ' },
);

$newpost->commit_post() or return 0;

return 1;
}

1;[/perl]

And finally, here's Submit.pm, which handles the post, regardless of whether it submitted by email or from the website:

[perl]package Topic::Submit;

our @ISA = qw/ Topic /;

sub new{
my ( $class, %args ) = @_;

bless{
username => $args{ 'username' },
subject => $args{ 'subject' },
message => $args{ 'message' },
}, ref( $class ) || $class;
}

sub commit_post{
my $self = shift;

# commit data, confirm, whatever
# print "User $self->{'username'} just Posted.";
}

1;[/perl]

Later on, if you wanted to add another way to post, then you can use add another subclass like Topic::Submit::Telepathy. The only thing Topic::Submit::commit_post() cares about is receiving the username, subject and message.

That's the beauty of OO modules. It lets you work on the little stuff (like different ways to post a topic) while keeping the big picture (like actually committing the post) intact and not having to rewrite different implementations of committing the post for each post method.

Oops. Just ran out of time. Gotta fly, but if you have questions, holler Smile


yapp
User

Mar 6, 2002, 11:49 PM

Post #3 of 13 (2316 views)
Re: [Jasmine] To OO or not to OO [In reply to] Can't Post


In Reply To
No regular syntax to use OO? Hrm. Not true, unless I'm mistaken about what you meant by that

Well, creating a new method that blesses some variable isn't exactly what I call regular syntax.

But this is. (some Java code)

Code
package Topic.Submit;   // same as perl: a folder. 
import topic.*; // somewhat like use lib

// extends replaces @ISA stuff. (file is Topic/Submit.java)
public class Email extends Submit {


// Constant that belongs to the Class, not an object instance
// accesable through Topic.Submit.Email.VERSION
public static final int VERSION = 1.00;


// instance variables replace the hash to be blessed
private String messageType;


// constructor replaces the new sub
public Email(String messageType) {
this.messageType = messageType;
}


public void post(String userName, String subject, String message) throws CannotCommitPostException {
if(userName == null) { userName = "Anonymous"; }
Submit newpost = new Submit(userName, subject, message);
newpost.commit_post();
}
}


including a throws statement in the methods header forces our callers to
implement a try..catch for that exception object or they must also declare
that exception to be thrown. That's much better then the die() in perl isn't it?
Although Java is superieur in OO but I really miss the inteligence of the perl
interpreter, the flexible syntax (if after a statement, or using unless, etc),
the regexps, it's funny tricks
(copying an array to a list, using a <<HERE; block, the qq[] operators)


btw, isn't the our statement very very new in perl? Since my scripts are in
public domain, I also want some previous perl to be able to work with it.
(so i use vars).


In Reply To
Oops. Just ran out of time. Gotta fly, but if you have questions, holler Smile

I didn't expect you to post soo much codeTongue
I just needed some ideas. I already created some basic modules that work OO.

Yet Another Perl Programmer

_________________________________
~~> [url=http://www.codingdomain.com]www.codingdomain.com <~~
More then 3500 X-Forum [url=http://www.codingdomain.com/cgi-perl/downloads/x-forum]Downloads! Cool

(This post was edited by yapp on Mar 6, 2002, 11:55 PM)


mhx
Enthusiast / Moderator

Mar 7, 2002, 12:16 AM

Post #4 of 13 (2308 views)
Re: [yapp] To OO or not to OO [In reply to] Can't Post


In Reply To
including a throws statement in the methods header forces our callers to
implement a try..catch for that exception object or they must also declare
that exception to be thrown. That's much better then the die() in perl isn't it?


Have a look at the [url=http://search.cpan.org/search?dist=Exception]Exception package.

-- mhx

At last with an effort he spoke, and wondered to hear his own words, as if some other will was using his small voice. "I will take the Ring," he said, "though I do not know the way."

-- Frodo



yapp
User

Mar 7, 2002, 12:32 AM

Post #5 of 13 (2305 views)
Re: [mhx] To OO or not to OO [In reply to] Can't Post

very very cool. I'll always use this in my code now. However, you can't force the caller to catch an exception id using a at compile time test, is it?

Back to the OO (or not to OO), what would you advise to use in Perl?

Yet Another Perl Programmer

_________________________________
~~> [url=http://www.codingdomain.com]www.codingdomain.com <~~
More then 3500 X-Forum [url=http://www.codingdomain.com/cgi-perl/downloads/x-forum]Downloads! Cool

(This post was edited by yapp on Mar 7, 2002, 12:33 AM)


mhx
Enthusiast / Moderator

Mar 7, 2002, 12:49 AM

Post #6 of 13 (2300 views)
Re: [yapp] To OO or not to OO [In reply to] Can't Post


In Reply To
However, you can't force the caller to catch an exception id using a at compile time test, is it?


Umm, sorry ... using what? Crazy


In Reply To
Back to the OO (or not to OO), what would you advise to use in Perl?


When I wrote my first Perl modules, they all were non-OO, because I'm not too much into OOP languages. I can write Java or C++, but I don't usually do it, because I have Perl, and C is more widely spread. (And you can write OO-style code in C as well...)

Later I recognized that Perl's OO system (which seemed more like a kludge to me first), is really cool because it's a lot easier to use. You can write very clean code/modules, but with the flexibility of Perl. When I write a module now, I always use OO style. (It's also some kind of laziness, because I don't have to look up how to configure the Exporter, I just don't use it. Wink)

As Jasmine already said, you should really get a copy of Damian's book on OO Perl. It tells you all you ever wanted to know about that topic. There's also an appendix where Perl's OO system is compared to other OOP languages like Java, C++ or Eiffel.

-- mhx

At last with an effort he spoke, and wondered to hear his own words, as if some other will was using his small voice. "I will take the Ring," he said, "though I do not know the way."

-- Frodo



yapp
User

Mar 7, 2002, 1:09 AM

Post #7 of 13 (2297 views)
Re: [mhx] To OO or not to OO [In reply to] Can't Post


In Reply To

In Reply To
However, you can't force the caller to catch an exception id using a at compile time test, is it?


Umm, sorry ... using what? Crazy


In Java, you can add a throws <list of classnames> statement to the method header. When you start compiling, everywhere your method is called, the error Uncaught exception <name> must be caught or declared to be thrown appears. So that means you should eiter implement a try...catch for this exception, or also include that class name in the throws section of your code.

What is that good for: for example, when working with files (IO), you are required to catch the IOException. There is no choice. However, if you don't handle it, and declare it to be thrown, your caller has to catch or throw it. Finally, when your exception reaches the GUI object, it only have to implement this code:

Code
try { 
dataClass.saveAllData(); // forces us to catch.
}
catch(IOException e) {
Messenger.confess("Can't save data: " + e.getMessage());
}

So basically, you can simple get good error messages into the GUI, without creating dependent classes. Also, you won't forget to catch an exception, since you're warned for this. I can remember a VB program I created once. It worked great, until I made that program save my file at a read-only network share. A runtime error occured, the program closed, and I lost all my data. In java, you 're already notified at compile time that this might happen, so you can't make such terrible mistake.

Back to perl: no-one implements a die() statement in CGI, since you never know where you need to catch errors in your code, with results in a 500 ISE or (CGI::Carp page) otherwise.




In Reply To
When I wrote my first Perl modules, they all were non-OO, because I'm not too much into OOP languages.

Same for me, but since I discovered OOP (since we need to program in Java at school), I also want to do the same thing in perl.


In Reply To
Later I recognized that Perl's OO system (which seemed more like a kludge to me first), is really cool because it's a lot easier to use. You can write very clean code/modules, but with the flexibility of Perl.

Well, I've guess I'm not that far and deep into this. at all...Tongue
I'm thinking of making a module that might solve this for me,
and provide some better solutions. I'm getting sick or shifting $self
from the @_ everytime, and then check if it's a reference, or my subroutine is called as "static method" (a method that belongs to the class itself, not an object of it)


(edit) added
use fields and use base are a great help, but they are also very very new, and "use 5.006". Not everyone has that, nor my webhost.

Yet Another Perl Programmer

_________________________________
~~> [url=http://www.codingdomain.com]www.codingdomain.com <~~
More then 3500 X-Forum [url=http://www.codingdomain.com/cgi-perl/downloads/x-forum]Downloads! Cool

(This post was edited by yapp on Mar 7, 2002, 1:15 AM)


Jasmine
Administrator

Mar 7, 2002, 1:16 AM

Post #8 of 13 (2293 views)
Re: [yapp] To OO or not to OO [In reply to] Can't Post

I'm the first person to admit about being ignorant about java, but I don't see your code being that much different... but it still appears to be a little more inflexible


In Reply To
Well, creating a new method that blesses some variable isn't exactly what I call regular syntax.


But what does that java code do that differentiates it as OO opposed to "normal" java. It's still the same jibberish to me Smile

I see a package, an import, and a few statements. What I don't see is the ability to parse the data from different receivers (as in from a mail post or from a form from a website). It has a package name, a private (aka my), a few publics (aka our), an import function (aka @ISA), and has expections (aka die), but doesn't seem to do as much as the Perl code offered...

I see several java statements replacing (albeit more) Perl statements, but with a lot less flexibility than the offered Perl code. I simply don't see the extensibility in the java code offered without modifying and recompilng the core "module" (or whatever it's called in java).

Also, perhaps because I know nothing about java, I don't understand the difference between the java exception and perl's die. They both fail; they both yield errors; why is one better/worse than the other? That's not a hostile question; it's merely an inquisitive question (as is the rest of the statements above).

The our keyword is new as of 5.6.0. The use vars you noted will be appropriate for older versions of perl.

edit: goodness, can i be that slow at 3.30am? 3 posts in the time that i composed the above message. snipped the answered questions.


(This post was edited by Jasmine on Mar 7, 2002, 1:30 AM)


yapp
User

Mar 7, 2002, 3:13 AM

Post #9 of 13 (2285 views)
Re: [Jasmine] To OO or not to OO [In reply to] Can't Post


In Reply To
I don't understand the difference between the java exception and perl's die. They both fail; they both yield errors; why is one better/worse than the other?

They both yield errors indeed. However, I can't distingish between the different errors. (in java Exceptions are just classes inheriting the Exception class). Also I can't force my caller to trap the exception (or let him declare it to be thrown). As I mentioned to mhx in a post before. However, you really need to work with it to see the fun and use of it. Just like Perl was a culture shock to me. Finally, you get used to it, and see the fun and use.

~ I still prefer perl, the only thing I like about Java is the strict class/object syntax, and it's exception handling mechanism. The rest sux.


In Reply To
edit: goodness, can i be that slow at 3.30am? 3 posts in the time that i composed the above message. snipped the answered questions.



Smile It's 12:10 here (GMT +1). I just arrived at school.

btw, how does that advanced editor work?; this is the first time I see it. At home (ie5) I never see the advances editor, it looks very much like the editor at hotmail.

Yet Another Perl Programmer

_________________________________
~~> [url=http://www.codingdomain.com]www.codingdomain.com <~~
More then 3500 X-Forum [url=http://www.codingdomain.com/cgi-perl/downloads/x-forum]Downloads! Cool

(This post was edited by yapp on Mar 7, 2002, 3:20 AM)


Paul
Enthusiast

Mar 7, 2002, 8:27 AM

Post #10 of 13 (2276 views)
Re: [Jasmine] To OO or not to OO [In reply to] Can't Post

[perl]
sub new{
my ( $class, %args ) = @_;

bless{
messagetype => $args{ 'messagetype' },
username => $in->param( 'username' ) || 'Anonymous',
subject => $in->param( 'subject' ),
message => $in->param( 'message' ),

}, ref( $class ) || $class;
}
[/perl]

Hmm couldn't you just do:

bless \%args, $class;


(This post was edited by RedRum on Mar 7, 2002, 8:28 AM)


Jasmine
Administrator

Mar 7, 2002, 12:22 PM

Post #11 of 13 (2272 views)
Re: [RedRum] To OO or not to OO [In reply to] Can't Post

Yes, of course, but I like to spell it out (particularly in examples). It helps me remember what's expected.


Paul
Enthusiast

Mar 7, 2002, 12:24 PM

Post #12 of 13 (2269 views)
Re: [Jasmine] To OO or not to OO [In reply to] Can't Post

Ah I also misread it a little. I thought you had used all $args but some were $in->param's


(This post was edited by RedRum on Mar 7, 2002, 12:25 PM)


yapp
User

Mar 8, 2002, 2:32 AM

Post #13 of 13 (2261 views)
Re: [Jasmine] To OO or not to OO [In reply to] Can't Post

Although this is a nice discussion, I still wonder:
should I convert me project into a OO version? (keeping in mind what I want to accomplish)

Yet Another Perl Programmer

_________________________________
~~> [url=http://www.codingdomain.com]www.codingdomain.com <~~
More then 3500 X-Forum [url=http://www.codingdomain.com/cgi-perl/downloads/x-forum]Downloads! Cool

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives