Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

RFC: Test-Smart-0.01

by Trizor (Pilgrim)
on Jul 25, 2007 at 04:45 UTC ( [id://628623]=perlmeditation: print w/replies, xml ) Need Help??

Greetings monks

I recently uploaded my first CPAN module Test-Smart-0.01 and I would like some feedback on the quality (not Kwalitee) of the dist as well as the idea itsself.

Some issues already raised on #perl:

  • Can it verify the person being asked is qualified to answer the question?
  • This should fail intelligently if it finds its running on an end-user's system who isn't an expert
  • 'Smart' is a loaded word, but any more accurate name gets too long too fast (open to suggestions on this one)

but feel free to revisit them.

Please keep in mind: this is my first CPAN module. If I've done something wrong be brutal so I won't make the same mistake twice. Thanks

Replies are listed 'Best First'.
Re: RFC: Test-Smart-0.01 (tye)
by tye (Sage) on Jul 25, 2007 at 05:48 UTC

    "Smart" is usually part of the name of badly-named modules where the author is claiming that the module is "smart". So the current name came nowhere near pointing me toward what the module does. Test::AskAnExpert seems a much more informative name.1 Even Test::Ask would be better.

    The documentation would be easier to understand if the examples were more illustrative. get_yes("question") illustrates very little. Since it doesn't give me any clues about what type of question would be asked, it also does very little to help me understand what the point of get_yes() even is.

    # Display complex results for expert to review. Then: get_yes( "Do the above results meet all requirements?" );

    Test::Smart::Interface::File was very uninformative, of course.

    Exporting a subroutine with a name as generic as initialize() seems a poor interface design. If you must stick with the exporting, then give the exported routine a name that at least hints at where it came from (and thus is less likely to conflict with the names of routines exported by other modules). But it seems more natural to avoid exporting (a good thing to avoid in general) and replace:

    initialize( "Test::Smart::Interface::Subclass", @args );

    with

    Test::Smart::Interface::Subclass->initialize( @args );

    even if you hadn't intended for someone to subclass in a way that overrides your initialization code and even if initialize() wasn't originally part of the subclass interface (just have the base class delegate it to the factory class). Yes, the user would then "require Test::Smart::Interface::Subclass;" as well as "use Test::Smart".

    Commenting on the code is painful since trying to even find it when hidden between chunks of POD much less read it while having to skip over big chunks of POD over and over just because you want to glance at a different subroutine... Ugh.

    I did manage to notice (because the strange interface made me wonder) that you have a single global (worse, actually, a file-scope lexical) so your module design is quite inflexible, not allowing for more than one interface to be used in any given test script.

    The documentation seems to imply that initialize(), get_yes(), and get_no() are exported even if you list things to be exported and don't list those. I hope that isn't the case and this is just something to be improved in the documentation. I should be allowed to avoid exporting things that I don't want exported (perhaps I don't use them, perhaps I choose to use them with a fully-qualified name). Even more likely, I should be allowed to list everything that is exported so someone reading my code and searching for what the heck initialize() does, will find that name listed on the "use Test::Smart" line and thus know where to go read up on it.

    The design feels very much like it came out of the "Now, which classes should I have inherit from which other classes?" school of design. I get the impression that this school of design comes out of (bad, IMO) newbie OO tutorials and experienced OO designers tend to be more of the "Inheritance of more than interfaces is usually best to avoid" school. And, IMHO, inheritance of interfaces in Perl is mostly just silly (since Perl doesn't really have interfaces). But that just qualifies as "design smell" rather than something specific I can point to and say "change this".

    - tye        

    1 But I'm not sure why I'm suggesting you change the name, since experience shows that you'll just keep the same name no matter how many people reasonably point out that the name has problems.

      In response to your footnote, I am seriously considering changing the name to Test::AskAnExpert, its much more informative, and better than any of the crap I came up with before settling on Smart which still wasn't very good. However I already hit register namespace... do I just e-mail modules saying "Guys its been brought to my attention that the name sucks. I'll resubmit with a better one"? I really like Test::AskAnExpert better, and the change will be made if you point me in the right direction.

      As for the "design smell" I'll see what I can do about it, I see your point and do see how it would be hard to point it out in any one line of code, but understand that its there.

      Regarding the docs versus the exporting. Yikes that is a sore spot, should I export nothing by default?

      Thank you for the response and the honesty, I'll work on attempting to re-work the worst of it and polish what can be saved.

        IMHO, Perl has enough syntax.

        Exporting functions adds to what looks like core syntax even though it's not. Forcing a user of your module to explicitly import something, to access it through the package namespace, or to create and object with which to interact all give a better clue as to where different variables and functions/modules come from.

        Exporting variables by default isn't any better. Your user is often writing the type of application for which you designed your module. There's often a lot of similar ideas for how to name variables when you and another person are working on the same problem. So please, don't give your user variables he's going to accidentally override.

        So I'd say that it is best to export nothing by default. Exporting upon request is okay. Object instantiation is okay. Exporting nothing and requiring the namespace to be specified is okay.

        Don't give me main::some_func() and especially not $main::some_var unless I ask for them. I don't want the potential conflicts, and I don't want to look back six months from now and have to search through my code and eight modules to figure out where $foo got set.

        The subroutines might not be so bad for an experienced Perl programmer because they've had time to assimilate what should be core syntax and what doesn't look familiar. A new Perl programmer, though, is likely already overwhelmed with all that's in perlfunc and will only get confused further by what's provided by CORE and what's provided by your module looking alike. Variables are always an issue, though, so that's even worse.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (7)
As of 2024-04-24 11:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found