in reply to High level OOP query

G'day packetstormer,

Superficially, what you're doing there is probably fine. You wrote "Suppose this simple code:" — unfortunately, I don't know to what extent you've simplified your original code for posting here.

Here's a few pointers (they're guidelines and recommendations; not rules and regulations):

So, Storm.pm would have this general structure:

package Storm; ... # use statements, etc. sub new { ... } ... # other methods 1;

Accessing instance variables (e.g. $self->{varname}) from your scripts is generally a very bad idea which you should avoid: it breaks encapsulation, causes all sorts of maintenance problems, and will generally come back to bite you in the bum when you least expect it. Add accessor and mutator methods to your classes and call them from your scripts, e.g.

my $varname = $self->get_varname(); $self->set_varname($new_name);

Passing a hashref to a constructor (e.g. Class::Name::->new($hashref)) is fairly common practice. I don't see any cause for concern in doing this.

The code you have in new() is somewhat deceptive and may trip you up down the track. Both "$self->{storm_auth_login}" and "$self->{append_text}" look like instance variables, but they're not! At this point in your code, $self is an unblessed hashref: it's not until a few lines later that it becomes an instance of $class (i.e. bless $self, $class;). You may want to consider rewriting new() (and adding an additional instance method) something like this:

sub new { my ($class, $args) = @_; my $self = bless $args => $class; $self->init; return $self; } sub init { my ($self) = @_; if ($self->{storm_auth_login}) { ... } ... # other initialisation code here return; }

Now new() is clean and could be inherited by a subclass which has its own init() method.

There's lots of documentation on this subject. Search perldoc: perl for any entries matching "mod" or "OO".

You may also be interested in Moose (and related modules). That's probably getting a little off-topic from what you're asking about here.

-- Ken

Replies are listed 'Best First'.
Re^2: High level OOP query
by packetstormer (Monk) on Oct 24, 2013 at 13:18 UTC
    Thanks for the detailed response, Ken. I really appreciate it.

    The code I posed was just for ease of reading and I would expect to split the class out to it's own package file when in use

    I am working my way though the book "Intermediate Perl" at the moment but I would love to find some real world examples that are simple enough for me to read. I have looked at many packages (from CPAN and other devs) but they are still a little complex for the standard I am at and I find trying to work them out is very time consuming due to their large size

    I will battle on though and thanks again for the reply.

      However, is it the "norm / acceptable", as above, to check the argument and based on a value then modify it.

      It is acceptable to modify any attributes based on arguments

      They say the user of a class shouldn't know/care about the internal state of attributes -- attributes are an implementation detail for the writer of a class

      so as the writer of a class do what makes sense, but as the user of a class pretend you don't know how it works inside (hard I know)

      smart people say: design a class the way you want to use it, start by writing code that uses it first

      perlootut, Modern Perl, Moo

      OR, is it better/normal to create a "blank" instance and then pass that into another method to change/modify?

      That depends, does the change/modification happen only once, during object creation? Or can it happen at any time in the life of the object?

      If you allow the user of your class to modify user/pass after object instantiation, and some other attribute depends on user/pass , then its best to encapsulate this relationship in a seperate method

      Instead of allowing ->change_username and ->change_password, call it ->change_userpass, and document that it affects the value of append_text

      But most likely you'll simply want to stick with doing this in the constructor -- and not allow changing of user/pass after instantiation

      OR, the third option: I am getting way to bogged down on what is the "norm" and I should worry more about my apparent lack of understanding of how OOP works!

      This! I recognize you as a one-of-us who doesn't really understand how OOP works :)

      This question is more of a low-level detail and you're not going to ferret out any benefits/tradeoffs/caveats... to find the best approach in this project -- its just not big enough and this detail is very low level

      No matter what you do, you're going to get it wrong, so you might as well get on with it, write your code (deliver product), make your mistakes, and learn from them :)

      The part you're probably missing
      Class-responsibility-collaboration card
      GRASP (object-oriented design)
      OOP in the Real World - Creating an Equation Editor - CodeProject
      How I explained OOD to my wife - CodeProject
      A Simple Example of Object-Oriented Design: An Address Book and An Example of Object-Oriented Design: An ATM Simulation ; tarballs at http://www.cs.gordon.edu/courses/cs211/
      Story-driven modeling

      Just remember that every one of us fought that same battle, from time to time felt just as lost and just as stupid, and that from time to time we still do.   It comes with the territory.   Meditate on all of the responses (present one excepted?) that you have received so far.   “Welcome to Perl,” and keep us up-to-date of your progress down The Path.   Bounce questions off of us (boink!!) anytime.