theantler has asked for the wisdom of the Perl Monks concerning the following question:

Hey folks .. A quick question: I noticed that many modules at cpan has an OO interface. Even for small modules with relatively little code .. (I think). What kind of decisions go into whether to use an OO interface, or just a regular module with some exported functions? I guess many people just prefer the OO interface. It is more neat and tidy? I want to start use some modules at cpan, to improve my skills and make my coding a little more advanced. But the OO interface terminology is a little confusing when you expect to get references to hash's etc.
  • Comment on Cpan module interface: OO or just a module?

Replies are listed 'Best First'.
Re: Cpan module interface: OO or just a module?
by moritz (Cardinal) on Apr 09, 2010 at 13:05 UTC
    When a programmer designs a library, he generally has use cases in mind. So she plays around with a procedural and object oriented interfaces, and see what feels more natural, and what leads to the least code duplication.

    If a procedural interface ends up passing all the same information to each routine call, it's a bad design, and the information should be stored in an object instead.

      Thats really good point .. Thanks!
Re: Cpan module interface: OO or just a module?
by cdarke (Prior) on Apr 09, 2010 at 13:52 UTC
Re: Cpan module interface: OO or just a module?
by JavaFan (Canon) on Apr 09, 2010 at 22:16 UTC
    I guess many people just prefer the OO interface. It is more neat and tidy?
    There are neat and tidy OO interfaces. There are neat and tidy non-OO interfaces. There are far more messy interfaces, both OO and non-OO. Whether an interface is "neat and tidy" has less to do with OO vs non-OO than with the quality of the programmer. Of course, "neat and tidy" is something very subjective. What you find "neat and tidy", I may find an incredible mess.

    IMO, it entirely depends on the problem whether an OO-interface is "better" (for some definition of "better") than a procedurial interface is. And for many problems, it hardly matters.

    I find it far more easy to write spaghetti code/interface/documentation using OO than using procedures.

      I find it far more easy to write spaghetti code/interface/documentation using OO than using procedures.

      Is that because OO lets you lose sight of the overall picture, where as procedural makes you aware of it constantly?

        One of the problems with many OO interfaces is that it allows the author to conceal a lot of cruft in addition to the legitimate encapsulation it provides. Another is that it tends to encourage the duplication of data.

        For example: A while ago I was collaborating in writing a module to efficiently determine the N maximum or N minimum values of a list or array. I wrote this as two functions that took N, and either a list or an array reference, and returned the N required values.

        My collaborator wanted to turn this into a OO interface. I asked why. The response was that this would allow the users to accumulate their values in the object before asking for the N max or N min values. I said, they can just as easily accumulate them in an array before calling the functions. He said, They might want to obtain the values again without having them re-calculated. I said, they can just as easily store and re-use them externally. That went on for a bit.

        For me, the final nail in the OO-coffin, is that for the majority of uses, the data would not exist entirely for the purposes of this module, but would usually be a part of some other dataset that is also used for other purposes. Perhaps as a part of a larger dataset, say a hash of arrays; each of which must be N-Maxed. And storing the data internally to the module would just duplicate data that is (and must be) stored elsewhere. And that extra storage could have a substantial impact upon the user programs.

        Sure, you could construct the object, call the nMax() method, and the destroy the object immediately for each dataset. But then, where is the gain over just calling a function.

        The trouble with OO doctrine is that it only considers data for the life of the object. But data rarely lives in isolation. It comes from somewhere, and it goes some where, and inbetween, it has many operations, often not obviously related, applied to it.

        So you start by accumulating data into a hash of arrays; make copies of it into a nMaxMin object; then copy it onto a stats object to obtain the standard deviation; then copy it into a GD::Data object to draw a graph; then copy it into a CSV object in order to write it to disk interspersed with commas. But all of these operations can be better accomplished by applying functions to a standard array without all the creation/destruction of myriad objects or the duplications of the data.

        Now (auto)boxing enthusiasts might say that if we could add methods to standard arrays, then that would solve the duplications problem. But if all that does is allow my @min5 = @a->nMin( 5 ); rather than my @min5 = nMin( 5, \@a );, is the overhead, however small, worth it?

        The basic criteria of whether an interface should be OO or procedural is: do the basic operations of that interface require the retention of supplimentary state that cannot be contained easily in the basic datatype.

        A good example of bad OO is the FileHandle module. This wraps over the basic built-in file handling facilities, but does nothing to address the problems. It doesn't provide for per-handle supplimentary state. That is, you cannot set $/, $\, or a raft of other state that you'd wish were settable per-handle. So, like that other wrapover, it does nothing to fix the underlying problem, but rather just draws attention to it.

        Bad OO is much worse that bad procedural. Example. FileHandle gives the ability to set autoflush on a handle using a nicely named method, but to get it involves 1000s of lines of code and a great deal of overhead. Sure it is nicer than

        my $old = select $fh; $|++; select $old;

        But all that OO to achieve that, when it can be fixed with something like:

        sub autoflush { my $fh; my $old = select $fh; $|++; select $old; }

        OO is very useful done properly. But making everything OO is as bad as performing all flow control with goto; all iteration with recursion; all state change through duplication; all error handling through exceptions; all program logic through declarations. It rejects the toolkit of well adapted tools, in favour of a one-size-fits-all, universal tool that will be the wrong one much (most) of the time.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.