Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re^2: RFC: Some of my toolkit modules

by bennymack (Pilgrim)
on Sep 21, 2006 at 14:56 UTC ( [id://574142]=note: print w/replies, xml ) Need Help??


in reply to Re: RFC: Some of my toolkit modules
in thread RFC: Some of my toolkit modules

Sorry to be a naysayer, but I would not put these on CPAN.

It's no problem at all. I am certainly not all gung-ho about putting these on CPAN. I just wanted to see if they'd make anyone else's life easier as they have for me.

Package::Require sounds like it is doing something that Perl already does for you. See the documentation for require, and look at %INC.

Not quite. First of all, I come across the

eval { require $somepm; };
quite often and the eval will be executed regardless of whether a module has already been required. This is slow.

Also, how often do you see the

$somepackage =~ s{::}{/}/g;
come up? This module contains simple methods for going from a file to a package and vice versa and uses Memoize for speed.

Lastly, %INC doesn't record modules that it has already FAILED to require, but this module will handle that for you.

Package::Exporter does something you shouldn't want to do. Exporting functions without telling the user what you are exporting increases the odds of encountering software conflicts. Therefore a well-designed module should export as little as possible. (Exporter deliberately warns about this point for a reason.)

I tend to disagree because as a user of Package::Exporter, I'm at least somewhat aware that if I do

use Package qw/SomeModule/;
then I'll be able to access all the subs in Package::SomeModule as just SomeModule.

The interface of all three of these modules is so minimal that there almost ISN'T an interface.

Your code example is not long enough to clarify what Package::Overridable does or how it is supposed to work. I tried to download it from your site so I could see for myself, but the connection timed out. However your reference in your comments to TestPackageOverridable and MyTestPackageOverridable suggests that the API is not one I'd like.

Package::Overridable basically provides an import sub to its children. So when a child class is imported, it will look in $PERL5LIB for a package of the same name but beginning with My. This makes it possible to transparently override code in development that will not be deployed to production because it's not under source control. I find this EXTREMELY handy.

Replies are listed 'Best First'.
Re^3: RFC: Some of my toolkit modules
by tilly (Archbishop) on Sep 21, 2006 at 18:38 UTC
    Sorry to be a naysayer, but I would not put these on CPAN.

    It's no problem at all. I am certainly not all gung-ho about putting these on CPAN. I just wanted to see if they'd make anyone else's life easier as they have for me.

    Package::Require sounds like it is doing something that Perl already does for you. See the documentation for require, and look at %INC.

    Not quite. First of all, I come across the

    eval { require $somepm; };
    quite often and the eval will be executed regardless of whether a module has already been required. This is slow.

    It is not particularly slow. Secondly if you're swallowing errors like that a lot, then you're making it unnecessarily hard to notice when you have problems, let alone to debug them. I'd strongly recommend against doing that.

    Also, how often do you see the
    $somepackage =~ s{::}{/}/g;
    come up? This module contains simple methods for going from a file to a package and vice versa and uses Memoize for speed.

    I don't see that happen very often. But when it does happen, I'm willing to bet that the substitution is faster than using Memoize. In either case, the odds that this is a performance problem are somewhere between zero and nil. That you would think otherwise suggests that you know very little about optimization. Read this chapter on optimization and you may learn something.

    Lastly, %INC doesn't record modules that it has already FAILED to require, but this module will handle that for you.

    If you regularly find yourself requiring modules that aren't there, that is a code smell. You're almost definitely doing something wrong. Furthermore the odds are that this is a real performance problem are extremely low. See the chapter I already pointed you at on optimization.

    Package::Exporter does something you shouldn't want to do. Exporting functions without telling the user what you are exporting increases the odds of encountering software conflicts. Therefore a well-designed module should export as little as possible. (Exporter deliberately warns about this point for a reason.)

    I tend to disagree because as a user of Package::Exporter, I'm at least somewhat aware that if I do

    use Package qw/SomeModule/;
    then I'll be able to access all the subs in Package::SomeModule as just SomeModule.

    You have missed the point.

    Are you familiar with the concepts of loose and tight coupling? The basic principle is when two pieces of code interface, there is a coupling between them. It is often convenient to make that interface big and complex - the result is called tight coupling. It is, however, important to make it as small as possible, that is loose coupling. That makes for more maintainable and modular code.

    You are making the coupling very tight by default. That is bad. Why is it bad? It is bad because now when you go to maingain Package::SomeModule you need to think about all the places where it is imported to be sure that your change doesn't break something. When you are trying to debug your main code and you see a function, you may have to look in all the modules that you imported to find the function that you called and verify how it works. When you are writing your main code, you need to stay aware of all of the interfaces, all of the time. If your brain is small (trust me, your brain is small, you just may not have discovered that yet), this is too much.

    Therefore what you are achieving is the exact opposite of modularity. You are instantly destroying any hope of modularity. This is a really bad idea.

    The interface of all three of these modules is so minimal that there almost ISN'T an interface.

    There is always an interface. And I differ with you on the size of that interface. Sure, something like Package::Exporter is simple to write and simple to use, but it results in very large interfaces. (That is why it is bad.)

    Your code example is not long enough to clarify what Package::Overridable does or how it is supposed to work. I tried to download it from your site so I could see for myself, but the connection timed out. However your reference in your comments to TestPackageOverridable and MyTestPackageOverridable suggests that the API is not one I'd like.

    Package::Overridable basically provides an import sub to its children. So when a child class is imported, it will look in $PERL5LIB for a package of the same name but beginning with My. This makes it possible to transparently override code in development that will not be deployed to production because it's not under source control. I find this EXTREMELY handy.

    This comment tells me that you don't know how to use source control properly.

    What sane people do is define a release procedure with a staging step. In the staging step you have a copy of code from source control as it will be deployed to production. Then you test that. You do not provide an override functionality, manually override everything that you are currently working on (hope you didn't forget anything!), then test that.

    Now I do recognize the need for a global configuration to make it easy to do different things in development and production. (For instance you do not want to accidentally send email to real people from development!) There are many possible approaches to that. But it doesn't sound like you're trying to solve that problem. (And if you are, you don't have a particularly good solution.)

    I'm sorry to come across so harshly. But it seems you have a lot to learn about good coding practices. Therefore I'm going to suggest that you pick up Code Complete and read it. Be warned that it is very long, and is not about Perl. (It doesn't even have examples in Perl.) But it is an extremely valuable book to read, and will make you into a much better programmer.

    As a friend pointed out to me about chess, novices can't recognize many of their mistakes because they aren't aware of the basic principles that would let them see that they are mistakes. That is where you are as a programmer right now. Code Complete should go a long way towards correcting that problem.

      It has become quite clear to me that the point of these modules have completely escaped you. I will not press the issue other than to say that your statements about interfaces, coupling, source control, etc have no bearing on anything remotely related to what they do.

      Like I said, I use them daily with great affect. Your comments seem dogmatic to me at the very least. I blame myself for not presenting them correctly but I hereby withdraw my request.

      Even though I've seen the many places where these come in handy, it seems that the world is not yet ready to recognize them for what they are.

        Actually the point has not escaped me at all. I understand what they do, how they work, and why you might like them. However I have the knowledge and experience to recognize how using this approach limits you and causes you worse problems in the long run than the ones that you are avoiding.

        You are free to disregard that knowledge and experience. But I think that in so doing you've missed a valuable learning opportunity. I apparently wasted my time in trying to educate you about fundamental software development concepts that let you see the larger picture.

        It is obvious how convenient it is to type one line less now. You see that and think your modules are wonderful. It is much less obvious that they will lead to longer debugging sessions 3 months down the road. It is very far from obvious that we spend more time and energy debugging code than we do developing it, so it pays off in the long run to focus on coding in ways that avoids creating problems that need to be debugged, and ones which will make debugging faster when you have to do it.

        Someday you may learn that lesson. But obviously that won't be today.

Re^3: RFC: Some of my toolkit modules
by eric256 (Parson) on Sep 21, 2006 at 15:22 UTC

    I don't know about the rest. But your last paragraph is already handled by perl. Just do use lib 'My'; and put a My folder in the directory with your program, and the modified modules in there. Not 100% the same, but it has worked nicely for me in the past.


    ___________
    Eric Hodges
      Or you can just have PERL5LIB point first at your my_special_versions_lib directory. Depends on which mistake for which you prefer to watch: submitting your code with use my_personal_module; in it or submitting code that secretly needs your personal module's fixes. I prefer the latter.

      Be well,
      rir

Re^3: RFC: Some of my toolkit modules
by runrig (Abbot) on Sep 21, 2006 at 16:18 UTC
    First of all, I come across the eval { require $somepm; }; quite often and the eval will be executed regardless of whether a module has already been required. This is slow.

    No, eval is not "slow" in this case. Perhaps you are confusing eval { BLOCK } with eval "STRING".

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (2)
As of 2024-04-20 04:45 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found