Gaurav Dadhania
Gaurav Dadhania

Reputation: 5337

Objects instead of global variables in Perl

I don't know if this is the right thing to do. But I'm lookig for tutorials/articles on using objects instead of global variables to store state. For eg.

package something
# some code here... 
# that generates errors and uses
# something::errors to track errors. 


package something::errors
sub new {
    my ($this) = @_;
    bless $this;
    return $this; 
}
sub setErrors{ 
    my ($this, @errors) = @_;
    $this->{errors} = \@errors;
}
sub getErrors{
    my ($this) = @_;
    return $this->{errors};         
} 

Is this better than using global varibles? Any down-sides to this? Any approach which might be better?

Thanks.

Upvotes: 2

Views: 926

Answers (4)

David W.
David W.

Reputation: 107080

You need a tutorial? Do you know that Perl has a whole mess of tutorials than you can shake a stick at?

Type in this command:

$ perldoc perl
[... a bunch of stuff]
Tutorials

    perlboot            Perl OO tutorial for beginners
    perltoot            Perl OO tutorial, part 1
    perltooc            Perl OO tutorial, part 2
    perlbot             Perl OO tricks and examples

Nifty?

All you have to do is simply to run:

$ perldoc perlboot

to see a particular tutorial. If you rather have this via a webpage checkout the on line Perl documentation.

And, they say that Perl is hard. After all, Unix comes with builtin documentation and how hard is that?

By the way, Perl objects are not all that difficult to use or understand. And, they really help clean up your code. If you're using hashes of hashes, or arrays of arrays, or arrays of hashes of hashes or arrays of hashes, you should really be using object oriented Perl.


Hint!

Take a look at the latest Perl documentation on state variables. It's made to do exactly what you want.

Upvotes: 2

daotoad
daotoad

Reputation: 27193

I hope this answer is useful for you, even though it's a pretty abstract comment and not very focussed on the particular details of your question.

IMO, objects are most useful because they provide a way to encapsulate a chunk of data and bind it to a set of behaviors.

Several clues are observable in code that indicate OOP may be a good way to go:

  1. Many subroutines that take the same group of arguments.
  2. You are working with non-homogenous data structures 3 or more levels deep.

So, do all (or most of) your subs have 3 or 4 common arguments?

sub whiz {
    my ($foo, $bar, $baz, $pogo) = @_;
    # blah
}

sub bang {
    my ($foo, $bar, $baz, $whibble) = @_;
    # blah
}

sub fiz {
    my ($foo, $bar, $baz, $smot) = @_;
    # blah
}

If you find your code looks like that, then maybe $foo, $bar and $baz need to be part of an object that groups all that messy stuff in one place.

Perhaps you have a big data or state object that looks something like this:

{   Foo => [ { a => 1, z => 3 }, [qw( milk milk lemonade)], ],
    quack => { round => 'the', corner => [qw( fudge is made )] },
...
}

Consider breaking this structure into smaller related, namable units. These are your objects.

Look at this structure:

{   teacher => $miss_jones,
    students => [ $bobby, $suzy, $joseph, $jenny ],
    principal => $mr_goodcop,
    vice_principal => $mr_badcop,
    custodian => $mr_mopitup,
}

And imagine that each variable was expanded into its own has with it's own set of fields. Some present in all variables, others unique to some subset of entries. But if $miss_jones is in class $teacher, we can call $miss_jones->add_student( $bobby ), without having to worry about how Teacher stores students.

These are the principles that I use to determine when to use OOP.

Upvotes: 2

daxim
daxim

Reputation: 39158

Any approach which might be better?

See chapter 13 of Perl Best Practices why and how to use proper exceptions. This topic also has come up on Stack Overflow repeatedly: Google search, SO search, SO tags

Upvotes: 1

j_random_hacker
j_random_hacker

Reputation: 51246

Well, your package still requires a (presumably global) variable of some kind to bless and to use as argument #1 in future method calls, so I don't see how this improves things in that respect. IOW you need a global variable regardless of whether you store the errors in a plain global array or use a something::errors object to hold them.

While using the object doesn't affect whether you need to keep global state, it does mean that you can control what operations can be performed more finely, and that is good for maintenance. (Maintenance is all about restricting the possible set of behaviours of any given piece of code to a manageable size.)

I think the important question is: "Will this list of errors ever be sufficiently different from a plain array to justify using a special type for it?" If the only operations you have are setErrors() and getErrors(), and you do not anticipate ever doing any filtering/processing during a setErrors() call, then I would say "no", since these operations are together powerful enough to let you do anything you could do with a plain array, so they don't provide any "safety". If on the other hand you wanted to avoid the possibility that errors are accidentally removed from the list, you could expose an addErrors() method instead of a setErrors() method, and you could now more convincingly argue that there was some benefit to using a separate type.

Upvotes: 1

Related Questions