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


in reply to Re: Use modules or roll your own?
in thread Use modules or roll your own?

For a module with one essential function, parsing a number into an English string, it does seem excessive. But what if my program already has a get_string() function or an %N hash, and I add this module after the fact? The OO layer protects me from name collisions (and in my example is completely optional). While I might not worry too much about it for Lingua::EN::Numbers, I certainly would worry if CGI didn't offer me a choice-- that module has the potential to export several dozen function names, many of which (in a CGI script) might clash with my function names (poorly chosen names, perhaps).

The OO isn't really pointless. It's happening either way-- exporting symbols without being asked to do so is just a sneaky way of concealing it is all. What I've said is that it should be explicit and optional for a module where the instance is really just an instantiation of a machine, rather than an instance of a class with unique properties that would distinguish it from other instances in the same class.

Essentially the instance becomes a shorter way of doing print Lingua::EN::Numbers->get_string(1281), " fish in the seas\n";... which you can also get around by offering the ability to export get_string(). Is there an actual reason for avoiding instantiation of a machine to prevent namespace collision? Or is the objection purely aesthetic?

Replies are listed 'Best First'.
Re: Use modules or roll your own?
by Abigail-II (Bishop) on Jul 29, 2002 at 16:23 UTC
    But what if my program already has a get_string() function or an %N hash, and I add this module after the fact?
    Well, so what? You _do_ know the working of Perl, don't you? Then you _do_ know that if you do:
    use Module ();
    the import() routine isn't called, and nothing will be exported. In which case, you can still use the function by calling it like:
    Module::get_string ()
    But a name clash is an exceptional case - normally you don't have a name clash (I've been programming Perl for over 6 years now, I cannot recall ever having had a name clash problem), and you can just use the short get_string. But with a class method, you have to use Module -> sub, even if it's not necessary.
    The OO isn't really pointless. It's happening either way-- exporting symbols without being asked to do so is just a sneaky way of concealing it is all.
    Exporting symbols without being asked is only a sneaky way if there isn't an easy way to avoid it. All you need to do is ask to _not_ import anything. That takes a whopping two characters. A module author using Exporter gives the programmer a choice - a module author using OO to avoid name clashes doesn't. I know who acts Perlish, and it ain't the latter programmer.

    As for the %N of Lingua::EN::Numbers::Easy, let me quote from the manual:

           By default, "Lingua::EN::Numbers::Easy" exports a hash
           "%N" to the importing package. Also, by default, "Lin-
           gua::EN::Numbers::Easy" uses the British mode of "Lin-
           gua::EN::Numbers". Both defaults can be changed by
           optional arguments to the "use Lingua::EN::Numbers::Easy;"
           statement.
       
           The first argument determines the parsing mode of "Lin-
           gua::EN::Numbers".  Currently, "Lingua::EN::Numbers" sup-
           ports British and American.  The second argument deter-
           mines the name of the hash in the importing package.
    
               use Lingua::EN::Numbers::Easy qw /American %nums/;
        
           would use American parsing mode, and "%nums" as the tied
           hash.
    
    If %N gives you a name clash, just use any other suitable name. OO isn't the only way of solving name clash problems!

    Abigail

      Well, so what? You _do_ know the working of Perl, don't you?

      Actually I didn't know about use module (); never having had a need to use it I never bothered to learn it. Usually I've either wanted new subs directly in my name space or I use an instance w/instance methods. I've never used a module which had an interface that should have done the former, but did the latter instead. Just lucky I guess. :)

      I'll yield that name clashes probably aren't that big of a deal. And for what is essentially a one-function module, I'd probably opt for explicitly exporting that function (too bad Lingua::EN::Numbers' internals are so messy that this isn't really possible without an interface or a serious rewrite), especially given that there is a way to prevent it (and thanks for pointing that out).

      A module author using Exporter gives the programmer a choice - a module author using OO to avoid name clashes doesn't. I know who acts Perlish, and it ain't the latter programmer.

      A module author using Exporter is using OO-- subclassing, I believe-- and to good effect. Whether they provide a constructor and instance methods or just class methods is a different story. In the example module it might have been avoided-- but what if you want to have a number-to-English machine that does British working alongside one that does American? You'll need to have two instances of the machine, which I think was the motivation here (no matter how bizarre the result was). This would not have precluded making get_string both an instance and a class method and having the class method rely on a default/class variable for locale.