Over time, modules in Perl can become obsolete, or superseded by newer modules.  Furthermore, despite being over 15 years old, Perl 5 continues to grow. Much of this growth comes from Perl's practice of assimilating popular CPAN modules into the core language. Modules that are not part of the core Perl language must be explicitly included to be used by a program, but modules that are part of the core language need not be. When a module has been assimilated into the core language, the original module is still available in CPAN.

Modules that have become obsolete, superseded by newer modules, or integrated into the core language are considered deprecated. Do not import deprecated modules.

If a module becomes deprecated because its features have been integrated into the core language, then their features may be used without importing the deprecated module.

Here is a list of CPAN modules that should be considered deprecated, according to Perl::Critic.

Deprecated

Class::ISA

Pod::Plainer

Shell

Switch

Universal::isa

Universal::can

Universal::VERSION

Noncompliant Code Example (Universal::can())

This noncompliant code example tries to see if an object supports a method. The Universal::can() method provides this capability. It was formerly an external CPAN module, but it is now part of Perl itself.

use UNIVERSAL qw(can);  # deprecated

# ...

sub doit {
  my ($func) = @_;

  if (can($self, $func)) {
    $self->$func();
  }
  # ...
}

Although this code works correctly now, the use statement will be rejected by the Perl interpreter someday.

Compliant Solution

This compliant solution uses Universal::can() without explicitly importing it.

# use UNIVERSAL qw(can);  # deprecated

# ...

sub doit {
  my ($func) = @_;

  if ($self->can($func)) {
    $self->$func();
  }
  # ...
}

Risk Assessment

Using deprecated or obsolete classes or methods in program code can lead to erroneous behavior.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

DCL30-PL

Medium

Likely

Low

P18

L1

Automated Detection

Tool

 Version

Checker

 Description

Perl::Critic

5.0 

Modules::ProhibitEvilModules
BuiltinFunctions::ProhibitUniversalCan
BuiltinFunctions::ProhibitUniversalIsa

 Implemented

B::Lint

 5.0

... is deprecated and will be removed in a future ...

 

Bibliography


 


3 Comments

  1. I think this guideline is misleading, and possibly bogus altogether.  First of all, core modules have to be loaded into your program just like any other.  Second, when a module moves into the core it does not mean that the module from CPAN has been deprecated in any way.  Many modules exist in the core and on CPAN simultaneously.  These are called "dual life modules".  Often times, newer versions are released to CPAN first, and then become part of the core at the the next Perl release.

    The Perl::Critic policies you mention do forbid the use of certain modules.  Not necessarily because they are officially "deprecated" by the p5 porters, but because many (but not all) members of the community feel they should not be used.

    1. I have no argument with your facts, just your conclusion that this rule is bogus :) The intro may be misleading; I have wordsmithed it in hopes of being more clear.

      AFAICT the Perl community has no standard notion of 'deprecation'. (Some languages, like Java, do.) So we at CERT are hereby using this term /deprecated/ to refer to modules that the community discourages use. IOW CERT is defining what is 'deprecated' but trying to use it in the way the community would if they used the term :)

      Ideally this rule would eventually include all popular modules that should not be used. And they may not be used for many different reasons; while we might examine one or two such modules; we mainly just want this rule to say "don't use these modules", with the ability to grow the list as more modules become deprecated.

  2. There are multiple issues with this Rule, in no particular order:

    #1 It is UNIVERSAL::*, not Universal::*

    #2 it is not clear where the $self variable comes from - it seems a global variable which should be discouraged by itself

    #3 the compliant solution does not take into account that the $self variable might be undefined, which would lead to an error (Scalar::Util::blessed would help here)

    #4 "use UNIVERSAL::can" is very different from "use UNIVERSAL qw(can)", it should be pointed out that calling function UNIVERSAL::can() presents some issues and that solving those issues use-ing module UNIVERSAL::can implies other issues (e.g. see discussion about the module in CPANRATINGS)