Beefy Boxes and Bandwidth Generously Provided by pair Networks kudra
Welcome to the Monastery
 
PerlMonks  

Re^4: The Most Essential Perl Development Tools Today

by pemungkah (Priest)
on Jan 09, 2013 at 20:40 UTC ( #1012568=note: print w/ replies, xml ) Need Help??


in reply to Re^3: The Most Essential Perl Development Tools Today
in thread The Most Essential Perl Development Tools Today

If you're arguing that the default choices are inappropriate and that the choices should be updated to reflect current Perl programming practices, I'd say that's generally correct (though there are, as I mentioned, a number of things you should, in general, do unless you are a highly-sophisticated programmer and know exactly what you are doing and what risks you are taking).

There is, however, a certain amount of handwaving in your argument against static analysis as a technique in itself. You say you "do my analysis dynamically". What does that mean? As far as I can tell, it means that you decide what to do as you write, determining as you write whether or not you will use a given construct.

For your bareword file handles example, does "I can safely use this bareword filehandle because I know I haven't used it anywhere else, and I'm sure that no module I've used uses this filehandle either because I've read them and made sure" capture the process?

Because that's still static textual analysis - you just happen to be using your brain and not a program to do it. If "dynamic analysis" means something else to you, it would be interesting to hear more about that.


Comment on Re^4: The Most Essential Perl Development Tools Today
Re^5: The Most Essential Perl Development Tools Today (static analysis)
by tye (Cardinal) on Jan 10, 2013 at 06:46 UTC
    For your bareword file handles example, does "I can safely use this bareword filehandle because I know I haven't used it anywhere else, and I'm sure that no module I've used uses this filehandle either because I've read them and made sure" capture the process?

    Don't be silly. A module using FOO as a bareword filehandle introduces no problems for me when I've used FOO as a bareword filehandle. Not even two modules each separately using FOO as a bareword filehandle causes a problem. *main::FOO is not the same as *Ancient::Module::FOO nor as *Modern::NonConformist::FOO.

    And "I haven't used it anywhere else" isn't even good enough of a test. The test is much more like: I won't be calling this bit of code that opens bareword filehandle FOO again until after I no longer need access to the prior file I opened.

    I'll be quite impressed if you can manage to get Perl::Critic to perform that test accurately.

    - tye        

      Since what you say, what I remembered, and what many of my Google searches say conflict, I ran an experiment. I created this package in the debugger:
      package bar; sub new { my $self = {}; bless $self, shift } sub openme { open BLODGETT } sub closeme { close BLODGETT } 1;
      and then did this:
      $x = bar->new() $x->open x %main:: x %bar::
      *main::BLODGETT does not exist, and *bar::BLODGETT does exist.

      This confirms that, despite many webpages to the contrary, bareword filehandles in different packages do not conflict, and I am therefore pleased to have fixed a bug in my internal inside-my-head Perl documentation, which was wrong.

      However, it's of interest that the scenario at the CERT secure coding site depends on bareword filehandles; specifically, if someone defines a sub with the same name as your bareword filehandle, that will take precedence, and can lead to the problems noted there.

      A programmer probably wouldn't do that to herself, but the potential exists for someone else to do so; lexical file handles actually prevent this vulnerability from working.

      As far as the "did I reuse this filehandle before I ought to have?" test, I definitely agree: that *is* hard to write. You could prevent it by having a table of filehandles and currently-open-for-output files, and throw an error if I try to re-open one that is currently open, or do simulated runtime analysis that verifies that there is no path that could lead to the file being reopened before it is closed.

      But now we're outside the scope of the question I asked, which was not about whether I could formulate this particular check right, but what "dynamic analysis" meant to BrowserUK. I'm guessing you're both talking about "simulated execution", which puts us into a much more sophisticated kind of analysis. Not impossible to do, but way more sophisticated than Perl::Critic. If that is the case, I'll agree: Perl::Critic can't do that.

      It can do some things that are appropriate in large development projects, like verifying you remembered strict. You can certainly do that yourself if you want. I prefer to have mechanical tests handled in a mechanical way, just like I prefer automated tests, even though Test::More can't test every possible situation. We just need to remember and emphasize to more naive programmers that tests don't guarantee the code is right, only that what we've tested passes the tests as they were defined, and is therefore probably not wrong.

      I think that a tool that lets me know about stuff that is possibly going to mess me up is useful. Others don't. I think we'll have to agree that we don't agree about this, as I have the feeling that perhaps this isn't about the tool, but instead about approaches to development, and I already know BrowserUK and I have wildly different preferences on that! And that since those are matters of taste rather than fact, arguing about them isn't productive, so I shall stop.

        I'm guessing you're both talking about "simulated execution"

        That would be guessing at more agreement between us than is warranted. On that point, I'm not completely sure what BrowserUk is talking about (though I certainly agree with many things he said). What I'm thinking of is fairly simple analysis by a programmer.

        And I'm pretty doubtful that a software program would be able to do that analysis well. For example, I see little problem with sometimes writing code that intentionally makes use of the fact that open FOO silently implies close FOO if FOO was still open. And that code can be written where that intent is quite clear (to a human, and not even using comments).

        A lot of what often makes this type of analysis so simple for (at least some) programmers, is being able to discern the purpose of parts of the code. That isn't an easy trick to teach to a piece of software.

        specifically, if someone defines a sub with the same name as your bareword filehandle

        Yeah, somehow that just doesn't worry me much at all. I tried to go read the page you linked to but the code examples were simply empty, brightly-colored boxes. Perhaps that would be remedied if I told my browser to run the unknown code that that web page offered up. Rather ironic from a site espousing "secure coding".

        From the text description, it sounds like the "problem" was demonstrated by somebody introducing code very similar to "sub BAD() { 'GOOD' }". Yeah, that's a very believable example. I write code like that all of the time. I especially do that using ALL-CAPS names that match filehandles that I use in the same source file (required in a sane coding environment because separate source files have distinct 'package' declarations).

        But it does suggest a much better idea for a Perl::Critic policy. Tell me when I have a conflicting pair of same-named items, such as a package name ("use CGI"), a subroutine name ("sub CGI"), or a filehandle name ("open CGI"). That'd actually be something worth pointing out.

        And not that I'm encouraging everybody to run off and use bareword filehandles. I am aware of several down sides to them. But I also appreciate at least in some situations the value of a filehandle that looks nothing like my other lexical variables.

        And I'd probably discourage inexperienced Perl programmers from using bareword filehandles. But I don't think I'd recommend that those same programmers try to use Perl::Critic to aid them in avoiding that practice. Though, I can certainly see it sounding like a really smart idea if you don't really think it through thoroughly. And it could've been a much less bad idea if several things about Perl::Critic hadn't been done so very badly.

        But my experiences of seeing some results of people having tried to use Perl::Critic have really only greatly strengthened my prior assessment that using it would usually end up being a bad idea. Re^2: Hello World for module writers (stumper) is an excellent example. Re^2: Symbolic reference with strict "refs" (it stinks!) even better.

        Telling me I forgot to "use strict" at the top of some module would be another fine use for something like Perl::Critic. Though, even that use is, IMHO, best done rather differently than most people appear to do it.

        The fact that ProhibitNoStrict actually got published is a pretty clear demonstration that the people maintaining Perl::Critic are not thinking clearly and thoroughly about the implications of their work. But it also isn't the only indicator of that.

        So I'm not surprised to find smart people having pretty strong reactions against using something like Perl::Critic.

        Things that would make Perl::Critic at least significantly less bad:

        • The default policy set should err on the side of only including things that are clearly serious problems
        • It should complain every time you run it if the set of policies to be included hasn't been customized yet (just make a policy for that and include it in any pre-defined set of "not just clearly serious errors" policies)
        • 'ProhibitNoStrict' is a great example of a policy that should never be easily enabled, not even by some "--be-extra-picky" mode, and not included in any pre-defined set of policies
        • It should default to complaining if you have added "#nocritic" markers to your code
        • Instead, if you ask it to tell you about suggestions other than about clearly serious problems, then it should provide ways for you to record "yeah, none of those really need to be addressed" without polluting your code
        • It should encourage being run in a mode where it only complains about non-serious problems if they are associated with lines of source code that have changed (run it against a commit or against a branch)
        • It should encourage that the complaints should always be evaluated by a qualified human, not as part of some automated step that has any consequences other than to provide details to a qualified human
        • Policies against things other than clearly serious problems should be careful to be clear in the description that this is not always a problem

        I gave up trying to find a sample report of "violations" (a poor word choice for use with this module). But I did find this in some documentation:

        --severity gentle --severity stern --severity harsh --severity cruel --severity brutal

        Yeah, that is really the wrong way to go. The levels should describe how likely a variance from the policy is to be a real problem or to risk becoming a real problem. The last level shouldn't be "brutal", it should be something more like "nit-picky", "of questionable value", "probably worth ignoring". And "lint" was a much better name choice than "Critic".

        - tye        

Re^5: The Most Essential Perl Development Tools Today
by BrowserUk (Pope) on Jan 11, 2013 at 19:44 UTC
    If you're arguing that the default choices are inappropriate

    Oh, the defaults are absolutely abominable, and when P::C first hit our consciousness, I argued fervently that a) they should be changed; b) that considerable thought (and preferably open discussion), be put into deciding what they should be changed to. I was ignored.

    Now, having seen the way the overall project has evolved, my position now is far stronger: fixing the defaults would not fix the problems, which run far too deep for this to simply be a "configuration issue".

    One problem is the matter of "quality control".

    Anyone can write and upload a 'policy module'; and it seems that most of them get adopted without any serious consideration of their efficacy.

    That is best exampled by tye's stark demonstration of your own misunderstanding with regard to the bareword filehandles issue. Do not feel bad about that, I think many others are in a similar position with regard to this issue. and many others. And there in a nutshell is the bigger problem.

    A Perl::Critic policy for something, no matter how trivial:eg. trailing commas; capricious:eg. spell-checking POD; misunderstood:eg. bareword filehandles; or just out&out wrong:eg. requiring use base; becomes widely, and wrongly, legitimised

    Witness the number of replies we see here that completely ignore the question asked and respond with edicts that "You must use lexical filehandles", even when they are unrelated to the question, and barewords are being used completely safely.

    Configuration is not enough.

    File-scope granularity for defaults is simply not enough. Programmers can (and should!) make their judgements on the appropriateness of particular constructs and idioms dynamically, ie. On a case-by-case basis.

    Eg 1. If a subroutine requires stepping through an array by 2s, 5s, or 10s, a C-style for loop is the ideal construct; but like most perlers, I prefer to use a perlish for loop for most cases.

    Eg 2. Using <> rather than <STDIN> may be the 'right thing to do' in most cases; but sometimes the requirement calls for reading from both in the same loop(s).

    As a teaching aid, P::C does more harm than good.

    Giving beginner's a bunch of arbitrary, capricious, pedantic and outright wrong "rules" to follow rather than encouraging them to experiment and learn by their mistakes; and learning to read the (amazingly comprehensive, if somewhat difficult) perl documentation carefully and thoroughly, will bread new generations of Perl programmers every bit as damaged as the archetypal VB programmers from yesteryear.

    Monkey see, monkey do

    This has nothing to do with snobbery; or being a "highly-sophisticated programmer"; it has everything to do with wanting to protect my favorite language and its future practitioners from the capricious, java-wannabe, idiots that think that they can save money on training by reducing Perl to some bland, flavorless, generic programming language.

    We should not be entertaining, much less encouraging, people who think that while( ! eof() ){

    is any clearer or easier to understand that until( eof() ) { .

    Or that for my $line_out ( @array ) { say $line_out } is clearer, more understandable; or dog forbid, 'more correct' than say for @array.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    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.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2014-04-19 21:12 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (483 votes), past polls