Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I see that you can use no feature X to shut off new feature $X within a given lexical scope.

I also see that strict and warnings operate as sort-of a sledgehammer to limit various dangerous or unsavory practices.

But is there any way to use the feature pragma to shut off deprecated or otherwise undesirable language features?

For example, suppose you want compilation of a file to fail if your project's code contains bareword filehandles, 2-arg open, pseudohashes, restricted hashes, indirect object syntax, etc. Is there any way to just shut those things off with a no feature pragma?

I may have seen a talk given about this somewhere... Maybe given by the last pumpking. As a way of allowing users to selectively and gradually deprecate various bits in an effort to help users bring their old codebases into the 20th century. Does anyone have a link to this talk? Has there been progress in this direction?

Thanks.

  • Comment on Is there any way to shut off deprecated, dangerous, dilapidated, or otherwise undesirable language features?
  • Select or Download Code

Replies are listed 'Best First'.
Re: Is there any way to shut off deprecated, dangerous, dilapidated, or otherwise undesirable language features?
by davido (Cardinal) on Aug 14, 2012 at 16:15 UTC

    Usually when a feature is truly deprecated, Perl will give a warning (if warnings are enabled) if you use the feature. You can explicitly set warnings to "FATAL" for a given set of warnings. The syntax is discussed in perllexwarn at Fatal Warnings. Since 'depreated' is a class of warnings, you can do this:

    use warnings FATAL => qw(deprecated);

    Or you may just want to elevate all warnings to fatal:

    use warnings FATAL => qw(all);

    The next step might be to layer in the use of Perl::Critic. With Perl::Critic you can start with the default criticism, and then elevate the level of severity, as well as add your own custom configuration. For testing purposes, you could use Test::Perl::Critic to enforce code compliance via your test suite. However, there are some caveats to using the test approach. It's usually best to keep the test local to your developer's environment and not force it upon your users. For one thing, your users may have a different Perl::Critic configuration that suddenly makes your distributed code fail. One common practice is to go ahead and distribute the test that uses Test::Perl::Critic, but deactivate the test (using a skip) unless two conditions are met: (1) The user has Test::Perl::Critic installed, and (2) The user sets an environment variable to true that your test can detect; something like "MYDIST_TEST_PERLCRITIC". If those two conditions aren't met, the test should default to gracefully skipping itself.

    In my own code I sometimes make use of Perl::Critic. And I've found the "## no critic (some_test)" escape to be helpful for those times where I want to escape out of a test locally without changing the global configuration. It's sort of my way of reminding myself (and Perl::Critic) that I've checked out the suggestion and consider my usage Ok in this case.


    Dave

      Thanks very much, Dave.

      The situation I'm thinking of is when you've got a handful of people working on a given project, with questionable or little leadership, where one or more of the team are hot-doggers who like to bang out a major feature overnight leaving behind some dodgy ("but it works!!") code that everyone else now has to document and maintain.

      For this situation, it sounds like using Test::Perl::Critic on the dev server (and requiring that all code use warnings FATAL all) might be the way to go. As long as you can get everyone to agree on it beforehand.

        Then, the question becomes whether or not you are in a position of authority over them.   If they do not have leadership now, perhaps you can become the leader so as to knock a little sense into them.   Otherwise, and I kid you not, sometimes the right thing to do is to start forwarding Monster job-offers anonymously into their in-box.   When someone like that sees greener grass, he or she will reliably jump ship.   (“Hot doggers” are especially reliable, because they always think that they are God’s Gift to everything, and that none of the mortals around here appreciate their Brilliance.)

        A slightly craftier approach is to do that to the current project manager, if you think that you can then be internally promoted.   :-D

        Failing that, you jump ship.   Because, if the company’s management practices are to allow junk-code to proliferate and they will not exert proper project-management control, you don’t want to be left maintaining that or dealing with that.   This is how “death marches” happen.   If you can positively change the situation, do so.   If not, escape it.

Re: Is there any way to shut off deprecated, dangerous, dilapidated, or otherwise undesirable language features?
by daxim (Curate) on Aug 14, 2012 at 17:00 UTC
    No, not with feature, but CPAN pragma modules, see 984059. For some of the stuff you mention, you can also employ the criticism pragma.

    If you're looking for an improved Perl for new projects, use perl5i. It contained many fixes that do not go into mainline Perl for backwards compat reasons.

Re: Is there any way to shut off deprecated, dangerous, dilapidated, or otherwise undesirable language features?
by tobyink (Canon) on Aug 19, 2012 at 08:39 UTC

    Try Syntax::Collector as a way of enforcing syntax standards (and syntax extensions) onto all packages in your project.

    package YourProject::Syntax; use Syntax::Collector -collect => q{ use constant 0 { true => !0, false => !1 }; use Scalar::Util 1.23 qw(blessed); use Carp 1.00 qw(confess); use strict 0; use warnings 0 FATAL => qw(all); no warnings 0 qw(void once uninitialized); no indirect 0.10; use feature 0 qw(say state switch); use utf8::all 0; use autodie 2.12; use true 0; }; 1;

    Then enforce a coding standard that all packages must begin with use YourProject::Syntax. This allows you to control all your boiler-plate imports and pragmata from a single location.

    perl -E'sub Monkey::do{say$_,for@_,do{($monkey=[caller(0)]->[3])=~s{::}{ }and$monkey}}"Monkey say"->Monkey::do'