http://www.perlmonks.org?node_id=66379

I have always thought I was a programmer, making scaleable programs, that were graceful, quick and concise. Until yesterday, I actually started playing with Objects in earnest...

I think my problem is for my current job, I hack Perl and have little time for code reuse since I'm given ten to thirty minutes turn-around. Reuse involves copying and editing the code closest to what I need, or grepping through the bash_history to find that 'one-liner' that was 100+ columns and pretty much did what I wanted.

So with some time on my hands I viewed the work I'd done and abstracted stuff into modules, then the modules to classes. Armed with OO Perl1 perltoot and perlobj and all the code for modules from CPAN, I set forth to make honest readable code that was maintanable and graceful. But the dark thoughts kept coming: put that in the destructor method, make that a class variable, don't use inheritance or overloading where an 'if' gets it done in half the time.

I ended up tying myself in knots divided between hacking a quick and dirty solution to some of my issues rather than being a mature and responsible programmer and making it a scaleable solution.

Other than finish reading OO Perl, which is the obvious answer; which idiom should I use? Part of me says to shun the Object way as it slower and means I don't use as many 80 column commands: The other says - Use Objects and in time all of the cool things will become second nature and they'll work in harmony with your desire for terse code.

So I guess what I want is other people's meditations on Objects in Perl and to see what the majority opinion on Objects in Perl - (What can I say? I'm a pack animal)

1. which like "Moby Dick", I've read much less of than I want to but I find the pages are too crammed with things to fire the imagination that I overload after 5-6 pages and reflect on that for a week or so.

--
Brother Frankus.

Replies are listed 'Best First'.
Re: Hacking with objects
by Masem (Monsignor) on Mar 22, 2001 at 21:21 UTC
    OOP is not a solution for all problems, nor is shunning it and using functional programming a solution for all. Sure, nearly every problem can be solved in both, but one may be easier than the other to write the code for, or it may be equally easy.

    The way I look at it, think of your problem and try to work out if object patterns fall out of it immediately. Things like business transactions, GUI elements, and the like will naturally be suited for OOP, while more rigorous low level tasks like network communications, file manipulation, and the like, are best done in "step a, then step b, then step c...". If you cannot easily recognize a good object structure within a few well-spent minutes of thinking on it, then it's probably better to avoid using Objects all together and stick to functional programming.

    This is not to say that after you've gotten the meat of your functional program in place, you cannot provide an Object (which could be as simple as a Module) that can be used to wrap these functions in an object framework. From some that I've seen, a good number of CPAN modules are of this type, where you have a few module-level functions that do a task and include some properties setting, but there's a lot more hidden away behind the scenes, thus acting like a true OOP object.

    update typo fixed


    Dr. Michael K. Neylon - mneylon-pm@masemware.com || "You've left the lens cap of your mind on again, Pinky" - The Brain
Re: Hacking with objects
by indigo (Scribe) on Mar 23, 2001 at 03:34 UTC
    OO in your program is like mustard on a ham sandwich. You can get by without it, a little can make things a lot better, and too much gets you a mustard sandwich.

    Unfortunately, OO has been such a buzzword over the years, there are a lot of mustard sandwiches out there. I've have spent more time in my career undesigning pointlessly complex object hierarchies than I have designing my own. There is something about OO that causes people to just go crazy and design these worthlessly ornate OO constructs. I think it is because while everyone knows the advantages of OO, but very few know its drawbacks. You have to understand both to know when to use OO, and how much is appropriate.

    I counsel OO minimalism. Start with a small set of core objects, and add new OO trappings only when your code speaks to you with a voice unwavering.

      You have to understand both to know when to use OO, and how much is appropriate.

      This is my problem. If I were coding in Java or C++ I'd play it by the numbers, because the voices in my head don't tell me to make this code as terse (basically, at least for Java a well trained Labrador can understand the code, so where's the fun?).

      But for me, in my less sober moments, Perl is for being a wizard and bending the rules if not breaking them or taking 3 words from one rule and sticking them with half a dozen from another.

      So the desire to use Good OO principals is not always at the forefront of my mind. What I was commenting on was the desire to hack using OO.

      In the same way that on a certain day you might bung all the processing for a piece of code in a regular expression and know it is `baaad'; I'll say rather than have a for loop and an item before the for loop and an item after the for loop I'll make an object do the first thing in the constructor the for stuff in a method and the bit after the for loop in the destructor function, and believe me in this situation it is brevitous, feasable and reusable.

      When I'm feeling mischevous or bored or lazy why should I feel bad about misusing the tools of OO? Being in awe of OO stops the use of some cool features, why should I have to be an OO Designer?

      I like the food analogy, I like food :-).

      --
      
      Brother Frankus.
Re: Hacking with objects
by mothra (Hermit) on Mar 23, 2001 at 00:39 UTC
    By the sounds of it, the coding that you do is done on tiny tasks, for which OO isn't really meant, IMHO.

    In my (day job) situation, we're using OO for a project (that doesn't use Perl, because it features a few stupidly complex GUI widgets in it :) that has over 200 stored procedures behind it, a 30 tablish database, and about 20,000 lines of code (ballpark). OO works quite well for it though.

    For example, my current task is to write an abstraction layer for creating database tables from the source code (rather than in the procs). The OO paradigm is nice here, because the interface to creating these tables (via the set of objects I'm creating to encapsulate this process) can stay exactly the same whilst the database vendor should change, or a version upgrade should change the SQL statements necessary to create tables.

    OTOH, a "side job" I'm doing is a simple CGI shopping cart site (maybe 500-600 lines of Perl, if that), for which I haven't even considered OO because it would be overkill.

    Overall, I really like the OO paradigm because to me it seems like a natural way of thinking about the way pieces interact within a complex system. But for small administrationish type scripts (or simpler CGI scripts), unless you have time to burn (or want to learn something fun), don't OOverdo it. :P

Re: Hacking with objects
by Rudif (Hermit) on Mar 23, 2001 at 05:21 UTC
    Brother frankus,

    Perl does not force you to OO. You have to decide one day to cross the threshold and find out what's in it for you.

    So, let me stick my neck out. I'm not crazy about objects, in Perl or otherwise. I just use them.

    In my experience, Perl objects are good for structuring any program, from the lowly quick hack to a large application involving tens of modules, other people's and your own.

    IMO, all those classical OO benefits show up more often than not in the programmer's daily work - the bread that our sandwiches are made of, so to speak
    • bundling the code and data together
    • encapsulating the data
    • managing object instances, each with it's state properly initialized and maintained
    • abstraction
    • separating interface from implementation
    • reusable modules
    • easy testing of modules
    Let me give you an example - a quick hack I did last night.

    I wanted to have a simple probe for the quantity of memory that my perl program is hogging at different phases of execution. I looked around for a Win32 module that could help me, and I found two - IProcess and Win32::PerfLib. I installed the former, tried the test scripts that came with it, and then simplified one of scripts and packed it into a module.

    Here is my test script - just to exercise my module
    #! perl -w # TestPerlprocdata.pl use Perlprocdata; my $pp = new Perlprocdata; my @x; for (0..5) { $pp->printProcessMemInfoShort; # probe # gobble some memory push @x, 1 for (0...100000); sleep 1; } # free the memory (to perl, not to the OS) @x = (); for (0..10) { $pp->printProcessMemInfoShort; # probe # gobble some more memory push @x, 1 for (0...100000); sleep 1; } # free the memory (to perl, not to the OS) @x = (); __END__ [Name] [PageFaults/s] [PeakWS] [WS] perl.exe 841 3436544 3436544 perl.exe 1366 5586944 5586944 perl.exe 1894 7753728 7753728 perl.exe 2694 11034624 11034624 perl.exe 2945 12062720 12062720 perl.exe 3344 13697024 13697024 perl.exe 4545 18620416 18620416 perl.exe 4545 18620416 18620416 perl.exe 4545 18620416 18620416 perl.exe 4545 18620416 18620416 perl.exe 4545 18620416 18620416 perl.exe 4545 18620416 18620416 perl.exe 4545 18620416 18620416 perl.exe 4647 19038208 19038208 perl.exe 5046 20676608 20676608 perl.exe 5444 22306816 22306816 perl.exe 5844 23949312 23949312
    And here is my quick and dirty module:
    #! perl -w # Perlprocdata.pm by Rudif@bluemail.ch use strict; package Perlprocdata; # uses Win32::IProcess by Amine Moulay Ramdane # from website: http://www.generation.net/~aminer/Perl/ use Win32::IProcess qw( PROCESS_QUERY_INFORMATION PROCESS_VM_READ INHERITED INHERITED DIGI +TAL NOPATH ); #---------------------------------------------------------- sub new { my ($class, %args) = @_; my $self = {}; bless $self, $class; my $obj = $self->{obj} = new Win32::IProcess || die "Can not creat +e an IProcess object..\n"; my @EnumInfo; $obj->EnumProcesses(\@EnumInfo); my $size=scalar(@EnumInfo); for(my $j=0;$j<$size;$j++) { if ($EnumInfo[$j]->{ProcessName} =~ /perl/i) { $self->{EnumInfo} = $EnumInfo[$j]; my $Info; $obj->GetProcessMemInfo($EnumInfo[$j]->{ProcessId},\$Info) +; $self->{Info} = $Info; my @data = ( $EnumInfo[$j]->{ProcessName}, $Info->{PageFaultCount}, $Info->{PeakWorkingSetSize}, $Info->{WorkingSetSize}, $Info->{QuotaPagedPoolUsage}, $Info->{QuotaNonPagedPoolUsage}, $Info->{PagefileUsage}); } } return $self; } #---------------------------------------------------------- sub getProcessMemInfo { my $self = shift; $self->{obj}->GetProcessMemInfo($self->{EnumInfo}{ProcessId},\$sel +f->{Info}); } #---------------------------------------------------------- sub printProcessMemInfoShort { my $self = shift; $self->getProcessMemInfo; printf("\n\n%17.15s%15.14s%12.11s%12.11s\n\n", "[Name]","[PageFaults/s]", "[PeakWS]","[WS]") unless $self->{printed}++; printf("%17.15s%15.14s%12.11s%12.11s\n", $self->{EnumInfo}{ProcessName}, $self->{Info}{PageFaultCount}, $self->{Info}{PeakWorkingSetSize}, $self->{Info}{WorkingSetSize}); } 1; __END__
    In this little exercice I can see just about every OO benefit that I listed above.
    Convinced?

    HTH
    Rudif

(jeffa) Re: Hacking with objects
by jeffa (Bishop) on Mar 23, 2001 at 05:37 UTC
    The important question to ask is "why am I making this thing an object?"

    Recently I ripped apart a CGI script that I wrote - one script handled 3 different pages, so I decided to decompose it. In the process, there were many subroutines that needed to be shared - should I create an object or should I create a module? I created both.

    I placed he common functions (stripping out leading and trailing whitespace, SQL queries, etc.) into a module and created an object to store errors that were generated from bad user input (such as blank fields, letters instead of digits, etc.). Some things are objects, others are just patches of functions quilted together.

    I might use that error object in another CGI application, but I doubt I will use the module, it is too specific and not general enough. It's easier for me to cut and paste the white space stripping function I wrote, or better yet, copy the module and delete the stuff I don't want.

    But I ain't touching the inards of my error object until I absolutely have to, they'll have ta pry it from my cold, dead hands. . .

    Jeff

    who is 'they'?
    
(tye)Re: Hacking with objects
by tye (Sage) on Mar 23, 2001 at 20:42 UTC

    Some good comments. I'd like to stress that OO is quite useful in Perl (it isn't "great OO" if you compare it to OO in some other languages, but it is very useful and overcomes some sticky problems, especially if you are writing a module).

    But I'd really like to stress that inheritance is so very often way overemphasized in OO and it should only be used for certain special and fairly rare cases. In Perl's OO, inheritance is especially troublesome and I strongly suggest that you enthusiastically avoid it.

    But the dark thoughts kept coming: put that in the destructor method, make that a class variable, don't use inheritance or overloading where an 'if' gets it done in half the time.

    Destructor methods are a very powerful tool in Perl OO. If you ever use inheritance to replace an if, I will hunt you down and kill you. But one of the particular advantages to OO when writing Perl is that it allows your modules to be used in multiple parts of the same process without having one part's customizations of the module's behavior stomping on the other part's. So I only consider one of those thoughts as "dark".

            - tye (but my friends call me "Tye")
      What is wrong with using inheritance to replace an if?

      If the test would have appeared in 20 places, I would find it very reasonable to use inheritance to abstract out the check. And if the if would have been a case statement, well eliminating that is exactly what inheritance is for!

      OTOH if the test would have appeared but once, that is a different issue...

        What is wrong with using inheritance to replace an if?

        If the test would have appeared in 20 places,

        I see that you didn't even answer your own question!

        Even if I had 20 ifs and they were all the same test and they all represented a clean bifurcation of a design, I'd still scream at you if your first thought of how to remove the ifs was inheritance.

        If you use only inheritance then you replace:

        sub Widget::Munge { # code block A if( $self->is_blue() ) { # code block B } else { # code block C } # code block D }
        with
        sub Widget::Munge { # code block A # code block C # code block D } sub Widget::Blue::Munge { # code block A # code block B # code block D }
        plus other code to implement the object...

        Now multiply that by 20. Gee, great solution. Now instead of 20 repeated ifs we have 40 repeated blocks of code.

        Oh, I'm sorry, you meant to also abstract out the code in the if blocks as separate functions. Okay, so now we have 40 new functions. What are you going to name them all? Does each of the 40 have a single, clear purpose that it serves well?

        Or are you assuming that each of the ifs also surround identical code? Well, then your problem isn't that you 20 ifs; your problem is that you have 20 duplicated chunks of code. So abstract that out as a function and now we have 1 if and using the sledgehammer of inheritance to squish it is still not the best first choice.

        Even if we decide that we have a case where using two functions in place of one if makes sense, then I'd first consider just storing a reference to the function in the object. If we have a bunch of cases like this and creating another class is warranted, I'd still prefer to have the original object contain a reference to these new objects rather than resorting to inheritance.

        From Advanced Perl Programming:

        Perl supports only [implementation] inheritance. [....]

        Subclassing is not easy, as Erich Gamma et al. say in Design Patterns:

        Designing a subclass also requires an in-depth understanding of the parent class. For example, overriding one operation might require overriding another. An overridden operation might be required to call an inherited operation. And subclassing can lead to an explosion of classes, because you might have to introduce many new subclasses for even a simple extension.
        They suggest using composition instead, a topic we will touch on shortly.
        and
        When C++ came along, I quickly became enthusiastic about a language that supported inheritance, and attempted to implement the widget set in C++. Then when John Ousterhout's Tk came along, I marveled at the ease of creating widgets, even though it was in C and provided all the features that Motif provides (and much more). The Tk architecture used composition, not inheritance.

        If Perl supported other types of inheritance, then I'd be less critical of the use of inheritance in Perl.

        But even Perl's version of implementation inheritance has extra pitfalls beyond those in most languages. But I'll save the details for a meditation since few will benefit from an analysis deep in an old thread.

        So, yes, using inheritance in Perl to remove an if is still likely to tempt me to hunt you down and kill you. (:

                - tye (but my friends call me "Tye")

      Of all the responses this is my favourite. I'm surprised it's not got more votes than my comment.

      If you've read the question 1, I hope you'll see it's not a "how should objects be used" question; it's a "how should I abuse objects.." question, tye's and tilly's comments were more salient for me (FWIW).

      Not to say the others missed the point, I've learnt some new OO good practices, thankyou :-). I've ++ all the comments in a thread, since they're all well written and to see what other folk think of the responses, if people ++ a statement more than I'd expect then I look a harder at the comment, to see if I've missed anything.

      1. For me "Hacking Objects in Perl" means elegantly ignoring OO principles to achieve what I want. I could do neat Objects but not in this job ;^)

      --
      
      Brother Frankus.
Re: Hacking with objects
by Anonymous Monk on Mar 24, 2001 at 00:01 UTC
    First of all, please accept this in the spirit intended... I've programmed in Perl for about 6 years now. I started doing OO Perl about 2-3 years ago, but recently I realized that (OK, I'm about to utter blasphemy in the Monestary don't flame be too bad) that Perl's OO model is so kludgy and the code is so ugly that I needed an alternative. My point here is that to really learn and take advantage of OO techniques you may need to go to another language.

    I found OO peace in moving to Ruby, and I might add, the move is quite easy if you're coming from the land of Perl. Others find OO nirvana in Python, but the move to Ruby seemed a lot easier for me. I've been programming in Ruby off and on (I still have to use perl at work primarily) for about three months now and already I feel more comfortable with it than with Perl. Look, I know this will be seen as advocacy, but I'm just trying to help out other tormented souls :-)... Check out http://www.ruby-lang.org for more info on Ruby. Ruby has a very clean OO model. It has a lot of the same functions for dealing with strings (like chomp, for example) as Perl (and in fact it has a lot more built-in goodies like reverse). Also, I find that threading and timeout (Ruby's equivilent of alarm) work on the Windows platform (Perl's alarm still doesn't work on the Windows platform).
      Why is this on PerlMonks?

      I know Ruby, and I know full well how nice its OO model is compared to Perl's, but this site is about Perl. Attempts to "rescue tormented souls" here will just result in Ruby being looked at by Perl people like most people look at Jehova's Witnesses. (And the way that Perl people look at Python.)

      Besides which, for someone who claims to have programmed in Perl for 6 years you seem strangely ignorant of basic Perl functions like reverse...

Re: Hacking with objects
by gregor42 (Parson) on Mar 26, 2001 at 21:01 UTC

    I write in several programming languages & have for quite some time now. Interestingly, though I sucessfully(?) have crammed several flavors of syntax into my skull that machines understand, I've never been very good at learning human languages.

    Which is maybe why I love PERL so much!

    The entire issue raised by this discussion thread can be answered by the first basic shibboleth of PERL:

    TMTOWTDI!

    There MUST ALWAYS be more than one solution to EVERY problem! You can use OOP or choose not to, and you will never be wrong, you may only be shown different paths to the solution. Are you optimizing for execution speed? In that case you most likely be better off going for the 'hack'. (Frankus' word, not mine.)

    If you're feeling REALLY motivated & have too much time on your hands, then do it BOTH ways & play with Benchmark.pl & you may learn something about how PERL works under the hood.

    OTOH, if you have very fast turn-around in your job, you may be more interested in the maintainability of your code. Especially if your intention is on code re-use. This this case OOP offers good guidelines for design that a trained monkey can follow when re-using your code later.

    And please don't flame for for implying that the use of OOP in PERL is slow in general. I'm referring to optimizations. And I do believe in wrapping your psycho-fast routines in objects and method calls as a general design principle. But the nature of the project dictates that more than a general rule. If you have 1/2 hour to turn out a CGI, you're most likely not going to be eloquent, but rather down & dirty. If you happen to be writing full-blown applications, then you're going to need a more thought out & well planned approach & design.

    Wait! This isn't a Parachute, this is a Backpack!

      It seems to me that a lot of people are versed in OO Principals and undoubtedly versed in Perl principles: "TIMTOWDI" and "can do!".

      So in my mind these people should feel there is dissonance where: Perls "can do!" meets OO's "thou shalt not" or if you don't like that: OO's "I wouldn't do that if I were you". The point is Perl's OO is "as you like it" .. there are legends, that Perl-Coders whisper around the terminals at night after pizza, of hackers who can change the inheritance of objects at run-time.

      Perl is laiden with features we (ab)use daily,so why are objects any different? Why, when I say Objects, do folk don their Systems Analysts hat?

      --
      
      Brother Frankus.
        Brother Frankus,
        Thank you for provoking a thoughtful discussion on an interesting subject and all the other contributers to this discussion for equally interesting replies.

        Concerning your question on objects being different, perhaps it is due to the way that OOP is taught. One always reads about a considerable amount of rigour in how an object should be created, public and private data, methods, encapsulation and on and on. Then you have the whole issue of creating beastiaries of objects, how they play together, etc. It starts to feel like Latin with all the rigour with which verb are tensed and objects are declined. But when spoken or composed by a fluent speaker, it can be magical.

        Then you have English, a ne'er do well language consisting of parts of several languages and newly created bits when folk feel like it. Grammar is considerably looser (certainly in the Rocky Mountain regions) and you can make your point even by fracturing your sentences to near intelligability. But again, it can be very powerful when used fluently.

        I have often thought the OOP is the new Latin and Perl as Modern English. I suspect the speed with which we abuse Perl as compared to objects is similar - Perl is perhaps more easily bent to a users will than the seemingly more rigourous OOP. Perl was designed to reflect natural languages, after all (unless I have misread the Camel book yet again). Rigour of form tends to make folk stick to the rules that they have spent a good deal of time learning and then (over)zealously apply them to how the language should be spoken. Perhaps this tends to stop folk from thinking as an English style hacker and more as Latin style formalist.

        Just a thought.

        MadraghRua
        yet another biologist hacking perl....

Re: Hacking with objects
by fmogavero (Monk) on Mar 26, 2001 at 21:11 UTC
    IMHO Objects are the way to go if you have the time.

    I came to my current employer and suggested objects. There is already Perl code that will do everything I want, here. The fallacy as I see it in the current work situation is that people keep re-inventing the wheel. They take that one liner and change it to what they need it for. There's nothing wrong with that until you see two people doing the same task different ways.

    This is what is happening at work. I was tasked with combining all of the different methods people use and create one method for the task. I initially thought that I could write a Q&D (Quick & Dirty) script to solve the problem. I decided against that when I realized that through object orientation I could take almost all the tasks around here and standardize them.

    Here is how I approached it. Our business is based on information contained in a database. We do two things: we either put information into the database, or we take information out. That is it on the simplest level. Taking the information out is always the same. It's putting the information in that causes a lot of headaches because of the different formats of information.

    My solution is to create an object that contains the information, an object that connects to the database, an object that loads the information to the database, an object that extracts the object from the database, an information destination object and an information origin object.

    Thus the loading and extracting tasks could be standardized with flexibility to change any portion of the process.