Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Re^2: How do I go from procedural to object oriented programming?

by Lady_Aleena (Priest)
on Apr 22, 2015 at 08:01 UTC ( [id://1124234]=note: print w/replies, xml ) Need Help??


in reply to Re: How do I go from procedural to object oriented programming?
in thread How do I go from procedural to object oriented programming?

Hello SimonPratt and thank you for stopping by. I have a few specific questions about the code you provided. I will be writing up something more general as a reply to my OP to show the true breadth of the module.

  1. Is Perl 5.16.2 required? I write for 5.8.8 since that is what my web host provides.
  2. How are you getting %movies_data from the module to the script below?
    #!/usr/bin/perl use strict; use warnings; # movie is the first package name I found in the module, # so I'm guessing it is also the module's name. use movie; my $library = library->new(name => "Lucky's"); foreach my $movie (values %movies_data) { $library->add_movie(movie->new(%$movie)); } $library->print();
    I see %movies_data but I don't see how you got it from the module. %movies_data is not something I want to have to copy and paste to the three scripts which use it now.
  3. Why doesn't end_year get a value if it does not have one? It needs an end year for run_time which you seem to have dropped.

You do not need to worry about adding movies with this module. I enter the data into the file by hand since the last time I did anything with the data file with a script, I accidentally dropped a value causing me to have to redo my research for the value for a lot of movies.

The module I am possibly rewriting has 7 hashes, 5 of which get sent out to scripts from the module. Some values of the hashes use the subroutines and other hashes to create some of the values. It is a big complex organism.

No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
Lady Aleena

Replies are listed 'Best First'.
Re^3: How do I go from procedural to object oriented programming?
by SimonPratt (Friar) on Apr 22, 2015 at 08:52 UTC

    Kia ora, Lady_Aleena, sure

    1. No it isn't, just happens to be the version I use (faster than writing use strict; use features;. Also gives hints about the version of Perl I am using, in case people do run into issues with any scripts I have created)
    2. In the sample I provided, this is main:
      my %movies_data = ( 'Firefly' => { 'title' => 'Firefly', 'startyear' => '2002', 'endyear' => '2003', 'media' => 'tv', }, 'Criminal Minds' => { 'title' => 'Criminal Minds', 'startyear' => '2005', 'endyear' => 'tbd', 'media' => 'tv', }, 'The 10th Kingdom' => { 'title' => 'The 10th Kingdom', 'startyear' => '2000', 'endyear' => '', 'media' => 'miniseries', }, 'Iron Man' => { 'title' => 'Iron Man', 'startyear' => '2008', 'endyear' => '', 'media' => 'film', 'basedon' => 'comics', 'company' => 'Marvel Comics', }, 'Tin Man' => { 'startyear' => '2007', 'title' => 'Tin Man', 'media' => 'miniseries', 'basedon' => 'novel', 'company' => 'L. Frank Baum' }, 'The Avengers (1998)' => { 'title' => 'The Avengers (1998)', 'startyear' => '1998', 'media' => 'film', 'basedon' => 'television series', 'company' => 'Thames Television', }, ); my $library = library->new(name => "Lucky's"); foreach my $movie (values %movies_data) { $library->add_movie(movie->new(%$movie)); } $library->print();
      From this, you can see that $movie is a reference to each of the hashes contaning the movie info (startyear, endyear, etc). When I call movie->new(%$movie) it is a call to the new function in the package movie, passing in the de-referenced hash containing the movie information. new is expecting a hash of stuff and deals with it appropriately when it creates the movie object. As for copying it, you don't have to do this - You can store this information in a myriad of ways (I would suggest a read-only XML file that you can easily backup, which your scripts can load easily)
    3. It won't get a value if I don't give it one. I didn't implement run_time as I was just trying to show a quick sample of how to create an OO object. Implementing this should be pretty straight-forward (and I would expect no end_year would be handled appropriately by run_time

    Heh, certainly looks pretty meaty. In a more OO fashion, I would expect lookup to be a single function within a library class, that returns an object from the library (movie, tv show, whatever). Then getting any of the underlying state information of the object that the caller wants is placed back onto the caller, who simply asks the object for that piece of information.

    UPDATE: You can copy the original sample I provided as-is, stick it all into a single script, change the use 5.16.2; line to use 5.8.8;, save it and run it - It should work just fine (though might complain about say (not sure when this feature was implemented), which you can just change to print.

Re^3: How do I go from procedural to object oriented programming?
by SimonPratt (Friar) on Apr 22, 2015 at 12:51 UTC

    Uhh, did a quick update to my previous script, to print the movies on individual lines, as per your OP. Notice how most of the work was done inside the classes, adding and extending function and procedure calls as necessary. main really is only having to deal with the what side of the equation, as opposed to the how, which is encapsulated inside the classes.

    use 5.16.2; use warnings FATAL => qw( all ); package movie; sub new { my $class = shift; my %params = @_; my $self = bless {}, $class; $self->title($params{title}); $self->start_year($params{start_year}); $self->end_year($params{end_year}); $self->media($params{media}); $self->based_on($params{based_on}); $self->company($params{company}); return $self; } sub title { my $self = shift; my $title = shift; $self->{title} = $title if $title; return $self->{title}; } sub start_year { my $self = shift; my $start_year = shift; $self->{start_year} = $start_year if $start_year; return $self->{start_year} // 'TBD'; } sub end_year { my $self = shift; my $end_year = shift; $self->{end_year} = $end_year if $end_year; return $self->{end_year} // 'TBD'; } sub media { my $self = shift; my $media = shift; $self->{media} = $media if $media; return $self->{media} // 'TBD'; } sub based_on { my $self = shift; my $based_on = shift; $self->{based_on} = $based_on if $based_on; return $self->{based_on} // 'TBD'; } sub company { my $self = shift; my $company = shift; $self->{company} = $company if $company; return $self->{company} // 'TBD'; } sub run_time { my $self = shift; my $result = $self->end_year(); $result = $self->start_year() if $self->media() eq 'film'; return $result; } sub print { my $self = shift; my $output = $self->title()." is a ".$self->start_year()." "; if ($self->media() eq 'tv') { $output .= "television series which "; if ($self->end_year()) { $output .= "completed in ".$self->end_year(); } else { $output .= "is still running."; } } else { $output .= $self->media()." based on ".$self->based_on()." by +".$self->company(); } say $output; } package library; sub new { my $class = shift; my %params = @_; my $self = bless {}, $class; $self->name($params{name}); $self->add_movie($_) for @{$params{movies}}; return $self; } sub name { my $self = shift; my $name = shift; $self->{name} = $name if $name; return $self->{name}; } sub add_movie { my $self = shift; my $movie = shift; $self->{movies}{$movie->title()}{movie} = $movie; $self->{movies}{$movie->title()}{location} = 'in'; } sub get_allmovies { my $self = shift; my @movies = map {$_->{movie}} values $self->{movies}; return @movies; } sub print { my $self = shift; say "I am a library called '".$self->name()."' and contain the fol +lowing movies:"; say "\t".$_->{movie}->title() foreach values %{$self->{movies}}; } package main; use XML::Simple; my @data = <DATA>; my $movies_data = eval { XMLin("@data") }; my $library = library->new(name => "Lucky's"); foreach my $movie (@{$movies_data->{movie}}) { $library->add_movie(movie->new(%$movie)); } $library->print(); say ""; foreach my $movie ($library->get_allmovies()) { $movie->print(); } __DATA__ <movies> <movie> <title>Firefly</title> <start_year>2002</start_year> <end_year>2003</end_year> <media>tv</media> </movie> <movie> <title>Criminal Minds</title> <start_year>2005</start_year> <end_year>tbd</end_year> <media>tv</media> </movie> <movie> <title>The 10th Kingdom</title> <start_year>2000</start_year> <end_year></end_year> <media>miniseries</media> </movie> <movie> <title>Iron Man</title> <start_year>2008</start_year> <end_year></end_year> <media>film</media> <based_on>comics</based_on> <company>Marvel Comics</company> </movie> <movie> <start_year>2007</start_year> <title>Tin Man</title> <media>miniseries</media> <based_on>novel</based_on> <company>L. Frank Baum</company> </movie> <movie> <title>The Avengers (1998)</title> <start_year>1998</start_year> <media>film</media> <based_on>television series</based_on> <company>Thames Television</company> </movie> </movies>

      SimonPratt, I'm sorry I didn't get back to you sooner. I got distracted. If you want to see my actual data, it is here. I don't know what you used at the bottom of the script, however it looks like it is going to gobble up a lot of screen real estate when you consider I have nearly 2,400 movies' data collected, and there are the additional fields qw(format Wikipedia allmovie IMDb TV.com Flixter genre). I shudder to think of the amount of bytes it would take to store them the way you are. I stored 13 movies for the bytes you used for 6, and 42 in the same amount of lines.

      I told you all that so you know I why I put the data in the same module as my subroutines. To keep storage so small, I have to do a fair amount of processing on each field. Even media gets processed. (If media is written like miniseries:5, miniseries is the media, 5 is the amount of parts it has and goes into $movie->{'counts'}{'episode'}. If I can't have the data in the same module as the subroutines, I will not be able to keep my storage sizes down.

      For example, when processing $series and $franchises (2 hash refs processed after $movies), I need start_year and end_year.

      There are a total of 7 hashes created in the actual module. If there were a way to keep them with the objects subroutines, I wouldn't have to drop the idea of using objects. As long as the data is not included, the module becomes useless to me. The actual module is all inclusive of everything which has to do with movies on my site which includes movies, series, franchises, genres, what I own, etc. Everything this module needs to handle is explained here.

      No matter how hysterical I get, my problems are not time sensitive. So, relax, have a cookie, and a very nice day!
      Lady Aleena

        Hi, Lady_Aleena. No worries, I've been away for a while anyway.

        I had a nosey around your git repository when you first posted the link to it. I thought it was a bit strange that you had gone to so much effort in creating a custom data management interface, however if storage space is that much of a concern to you, then I totally get it :)

        __DATA__ effectively tells Perl that everything after that point should be made available through the DATA handle. You get the same effect by having everything below __DATA__ saved in an external file, then manually opening a filehandle called DATA in order to read the content.

        In your particular case, your data management interface should be re-worked to do all of the object building for you. So, instead of creating a bunch of hashes, then calling a set of functions to populate the hashes, you should be able to add your data library and create a new library object which would be populated with movie objects, which are all populated with the data contained in your raw files.

        Once this is working correctly, it doesn't matter how many scripts need access to this data, they can all simply load your data management library and ask it to give them a library of movies to use.

Re^3: How do I go from procedural to object oriented programming?
by soonix (Canon) on Apr 22, 2015 at 22:02 UTC
    the last time I did anything with the data file with a script, I accidentally dropped a value causing me to have to redo my research for the value for a lot of movies.
    Now that you have an offsite backup , that should be a simple matter of git revert or at most git cherry-pick … (at least as long as you keep it up to date, of course)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1124234]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (7)
As of 2024-04-19 06:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found