in reply to Challenge: CPAN Golf

To start with, I don't understand your rant. What is wrong with code-reuse? Is CPAN's automated dependency resolution a problem? Sure, long dependency chains and resolving failed installs can be annoying, but an hour or so of work on your part and you now have, at your fingertips, what probably amounts to hundreds of hours of work by others.

But then there are all those Test::Tester, Test::Tester::Bestertester, Test::Tester::Bestertester::Helper modules and their dependencies as well.

Testing code is tedious, writing complex code to test your code is even more tedious (and error prone). One of the great strengths of the Perl community is its dedication to testing as evidenced by the many high-quality Test:: modules available on CPAN. I don't know about you, but I don't want to have to re-invent the wheel that modules like Test::JSON and Test::LongString have already invented.

Then I install the otherwise fine CGI::Ajax module and note it uses Class::Accessor to generate setters/getters for a list of seven object attributes, trading 29 lines of trivial hand-written code against 874 lines or 48 kBytes.

Well you say "29 lines of trivial hand-written code", I would like to change that slightly to "29 lines of tedious, repetative (and therefore possibly error prone) hand-written code". Modules like Class::Accessor (which is much less then 874 lines of code, not sure where you got that number) help increase the quality of modules that use them.

Just stop and think for a moment about this.

If I write my own accessor code, then I should test that code. So for 9 object attributes, I write 9 accessors, each which should be tested in a couple of ways. First I need to test that they store the values properly, then that they return stored values, if I want to be diligent I should test edge cases as well like passing in undef and such. Sure you could say "but those are so trivial, why even bother to test them", and actually I would agree with you. If you use Class::Accessor you don't have to test them, because Class::Accessor has already tested it's accessor generation code and you can be assured it works as expected.

In short, building your module from other well tested modules automatically ups the quality of your module. Standing on the shoulders, etc etc blah blah blah.

This kind of laziness places the burden of installing and updating dependencies, which are not crucial for the functionality of the module in question, on the module user.

Okay, this was the line that really kinda bothered me the most. I will point to what I said in the first paragraph in regard to installing dependencies. You are getting software which took someone else many hours to write FOR FREE. I think it is worth a few moments of your time to install it.

As to the "not crucial to the functionality of the module" argument, this is ridiculous. Why should the module author have to write, debug, test and maintain extra code so that you don't have to sit though a longer automated install? Trading their time for yours, how kind of you.

IMHO, hubris beats laziness for module authors, and modules should not depend on other modules if the latter only bring small benefits.

Well then I look forward to seeing all your "dependency free" modules. Please let us all know how much fun you have re-inventing, debugging, testing and maintaining innumerable small wheels.

-stvn

Replies are listed 'Best First'.
Re^2: Challenge: CPAN Golf
by shmem (Chancellor) on Jan 08, 2008 at 15:49 UTC
    Thank you for this good retort. If I have come across as a ungrateful fuck, I'm really sorry about it. Maybe I should have written <rant mode="not serious">.

    Of course the time and work I have to spend to install modules stands in no relation to the time spent and effort put into writing, testing and maintaining just one of the modules I install along with the top-level target, and I am not wanting to be ungrateful; giving back is maybe the strongest reason for hanging out here on PerlMonks. I'd write useful modules myself if I were more brillant and faced problems for which there isn't a module yet on CPAN; or if I could significantly improve existing solutions.

    That said, I still hold up the statement

    IMHO, hubris beats laziness for module authors, and modules should not depend on other modules if the latter only bring small benefits.

    because there are problems with module dependencies; dragonchild has named one - lack of standards - and pointed out the benefit that drawback brings. Off my head (there might be more)

    • "you don't have to test them" - part of a sane module install (and of automatic install) is testing, so that pulls in the entire module-author's testing infrastructure as applied on the module
    • a chain is only as strong as its weakest part; cpandeps provides a nice view of how and where automatic install might fail
    • longer inclusion chains have a hit on performance

    Of course, each of those arguments can be wiped away with "Trading their time for yours, how kind of you" without being really countered. For the CGI::Ajax / Class::Accessor example see Re^3: AJAX popup windows - an example.

    Well then I look forward to seeing all your "dependency free" modules. Please let us all know how much fun you have re-inventing, debugging, testing and maintaining innumerable small wheels.

    You did note the "small benefit" part? I am not arguing for dependency-free modules, but for as little dependencies as possible, which of course is no absolute, but something worth thinking of; and "as possible" has many constraints.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      Of course the time and work I have to spend to install modules stands in no relation to the time spent and effort put into writing, testing and maintaining just one of the modules I install along with the top-level target, and I am not wanting to be ungrateful; giving back is maybe the strongest reason for hanging out here on PerlMonks. I'd write useful modules myself if I were more brillant and faced problems for which there isn't a module yet on CPAN; or if I could significantly improve existing solutions.

      If you want something to work on, I'd love to give you either PDF::Template and/or Excel::Template. Or, I could use help working on DBM::Deep on Win32. Or, any of the other 20 really cool module ideas I have rattling around that I simply don't have time to work on. Like Presto. Or PerlGems.

      You did note the "small benefit" part? I am not arguing for dependency-free modules, but for as little dependencies as possible, which of course is no absolute, but something worth thinking of; and "as possible" has many constraints.

      So, I go ahead and put in a dep on ABC because it saves me half the project. It has a dep on DEF cause that saves it half the project. DEF's author is stupid and has 30 deps. Should I avoid ABC because of that?


      My criteria for good software:
      1. Does it work?
      2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
        DEF's author is stupid and has 30 deps. Should I avoid ABC because of that?
        I'd say yes, definitely - if you can afford it. Otherwise the submit to CPAN is questionable. ABC is likely to break (weakest link chain rule) because of DEF. Don't avoid ABC if you can convince its author to not use DEF, or if you can convince the author of DEF of the "less is more" principle. It is your module that's beholden (?) as unusable - even if the fault lies in DEF.

        update: I'm checking your modules =~ /${'my aptitude'}/

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
      because there are problems with module dependencies; dragonchild has named one - lack of standards - and pointed out the benefit that drawback brings.

      Yes, I agree with dragonchild on that, however TIMTOWTDI is core to the Perl Way of Life and standards are counter to that. Of course TIMTOWTDI is a double edged sword here especially.

      You did note the "small benefit" part? I am not arguing for dependency-free modules, but for as little dependencies as possible, which of course is no absolute, but something worth thinking of; and "as possible" has many constraints.

      I will say, and I suspect you will agree, that choosing to add dependencies is something that should not be taken lightly. For instance, if the module looks abandoned I will sometimes opt to write it myself because I don't want to depend on something which is unmaintained and might break and mess up my module with it. But a good solid module (like Class::Accessor) can be depended and it used widely enough that I would not even think twice about using it, knowing full well that many people will probably already have it installed.

      One of the really great things about Perl is CPAN, and one of the really great things about CPAN (IMO at least) is how much interdependency there is in it. If you take a look at the state of Python, Ruby or even Java modules you will find many more monolithic codebases (although ruby and python are getting better now last I checked). I would submit that this is directly related to the level of tool support to automatically resolve dependencies such as CPAN has. Anyway, just my 2 cents :)

      -stvn
        I will say, and I suspect you will agree, that choosing to add dependencies is something that should not be taken lightly.

        That looks like you understood my rant ;-)

        --shmem

        _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                      /\_¯/(q    /
        ----------------------------  \__(m.====·.(_("always off the crowd"))."·
        ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}