File Coverage

blib/lib/Perl/Critic/Policy/Community/DiscouragedModules.pm
Criterion Covered Total %
statement 22 23 95.6
branch 2 2 100.0
condition 6 9 66.6
subroutine 9 10 90.0
pod 4 5 80.0
total 43 49 87.7


line stmt bran cond sub pod time code
1             package Perl::Critic::Policy::Community::DiscouragedModules;
2              
3 1     1   487 use strict;
  1         2  
  1         31  
4 1     1   5 use warnings;
  1         3  
  1         28  
5              
6 1     1   5 use Perl::Critic::Utils qw(:severities :classification :ppi);
  1         2  
  1         51  
7 1     1   398 use parent 'Perl::Critic::Policy';
  1         2  
  1         7  
8              
9             our $VERSION = 'v1.0.2';
10              
11             sub supported_parameters {
12             (
13             {
14 4     4 0 23629 name => 'allowed_modules',
15             description => 'Modules that you want to allow, despite being discouraged.',
16             behavior => 'string list',
17             },
18             )
19             }
20 19     19 1 187 sub default_severity { $SEVERITY_HIGH }
21 0     0 1 0 sub default_themes { 'community' }
22 4     4 1 76284 sub applies_to { 'PPI::Statement::Include' }
23              
24             my %modules = (
25             'AnyEvent' => 'AnyEvent\'s author refuses to use public bugtracking and actively breaks interoperability. POE, IO::Async, and Mojo::IOLoop are widely used and interoperable async event loops.',
26             'Any::Moose' => 'Any::Moose is deprecated. Use Moo instead.',
27             'Class::DBI' => 'Class::DBI is an ancient database ORM abstraction layer which is buggy and abandoned. See DBIx::Class for a more modern DBI-based ORM, or Mad::Mapper for a Mojolicious-style ORM.',
28             'CGI' => 'CGI.pm is an ancient module for communicating via the CGI protocol, with tons of bad practices and cruft. Use a modern framework such as those based on Plack (Web::Simple, Dancer2, Catalyst) or Mojolicious, they can still be served via CGI if you choose. Use CGI::Tiny if you are limited to the CGI protocol.',
29             'Coro' => 'Coro abuses Perl internals in an unsupported way. Consider Future and Future::AsyncAwait in combination with event loops for similar semantics.',
30             'Error' => 'Error.pm is overly magical and discouraged by its maintainers. Try Throwable for exception classes in Moo/Moose, or Exception::Class otherwise. Try::Tiny or Syntax::Keyword::Try are recommended for the try/catch syntax.',
31             'File::Slurp' => 'File::Slurp gets file encodings all wrong, line endings on win32 are messed up, and it was written before layers were properly added. Use File::Slurper, Path::Tiny, Data::Munge, or Mojo::File.',
32             'FindBin' => 'FindBin depends on the sometimes vague definition of "initial script" and can\'t be updated to fix bugs in old Perls. Use Path::This or lib::relative to work with the absolute path of the current source file instead.',
33             'HTML::Template' => 'HTML::Template is an old and buggy module, try Template Toolkit, Mojo::Template, or Text::Xslate instead, or HTML::Template::Pro if you must use the same syntax.',
34             'IO::Socket::INET6' => 'IO::Socket::INET6 is an old attempt at an IPv6 compatible version of IO::Socket::INET, but has numerous issues and is discouraged by the maintainer in favor of IO::Socket::IP, which transparently creates IPv4 and IPv6 sockets.',
35             'IP::World' => 'IP::World is deprecated as its databases are in one case discontinued, in the other no longer updated. Therefore its accuracy is ever-decreasing. Try GeoIP2 instead.',
36             'JSON::Any' => 'JSON::Any is deprecated. Use JSON::MaybeXS instead.',
37             'JSON::XS' => 'JSON::XS\'s author refuses to use public bugtracking and actively breaks interoperability. Cpanel::JSON::XS is a fork with several bugfixes and a more collaborative maintainer. See also JSON::MaybeXS.',
38             'Net::IRC' => 'Net::IRC is an ancient module implementing the IRC protocol. Use a modern event-loop-based module instead. Choices are POE::Component::IRC (and Bot::BasicBot based on that), Net::Async::IRC, and Mojo::IRC.',
39             'Switch' => 'Switch.pm is a buggy and outdated source filter which can cause any number of strange errors, in addition to the problems with smart-matching shared by its replacement, the \'switch\' feature (given/when). Try Switch::Plain or Syntax::Keyword::Match instead.',
40             'XML::Simple' => 'XML::Simple tries to coerce complex XML documents into perl data structures. This leads to overcomplicated structures and unexpected behavior. Use a proper DOM parser instead like XML::LibXML, XML::TreeBuilder, XML::Twig, or Mojo::DOM.',
41             );
42              
43             sub _violation {
44 19     19   402 my ($self, $module, $elem) = @_;
45 19         56 my $desc = "Used module $module";
46 19   33     56 my $expl = $modules{$module} // "Module $module is discouraged.";
47 19         61 return $self->violation($desc, $expl, $elem);
48             }
49              
50             sub violates {
51 60     60 1 5177 my ($self, $elem) = @_;
52 60 100 66     146 return () unless defined $elem->module and exists $modules{$elem->module} and not exists $self->{_allowed_modules}{$elem->module};
      100        
53 19         1298 return $self->_violation($elem->module, $elem);
54             }
55              
56             1;
57              
58             =head1 NAME
59              
60             Perl::Critic::Policy::Community::DiscouragedModules - Various modules
61             discouraged from use
62              
63             =head1 DESCRIPTION
64              
65             Various modules are discouraged by some subsets of the community, for various
66             reasons which may include: buggy behavior, cruft, performance problems,
67             maintainer issues, or simply better modern replacements. This is a high
68             severity complement to
69             L<Perl::Critic::Policy::Community::PreferredAlternatives>.
70              
71             =head1 MODULES
72              
73             =head2 AnyEvent
74              
75             L<AnyEvent>'s author refuses to use public bugtracking and actively breaks
76             interoperability. L<POE>, L<IO::Async>, and L<Mojo::IOLoop> are widely used and
77             interoperable async event loops.
78              
79             =head2 Any::Moose
80              
81             L<Any::Moose> is deprecated. Use L<Moo> instead.
82              
83             =head2 Class::DBI
84              
85             L<Class::DBI> is an ancient database L<ORM|https://en.wikipedia.org/wiki/Object-relational_mapping>
86             abstraction layer which is buggy and abandoned. See L<DBIx::Class> for a more
87             modern L<DBI>-based ORM, or L<Mad::Mapper> for a L<Mojolicious>-style ORM.
88              
89             =head2 CGI
90              
91             L<CGI>.pm is an ancient module for communicating via the CGI protocol, with
92             tons of bad practices and cruft. Use a modern framework such as those based on
93             L<Plack> (L<Web::Simple>, L<Dancer2>, L<Catalyst>) or L<Mojolicious>, they can
94             still be served via CGI if you choose. Use L<CGI::Tiny> if you are limited to
95             the CGI protocol.
96              
97             =head2 Coro
98              
99             L<Coro> abuses Perl internals in an unsupported way. Consider L<Future> and
100             L<Future::AsyncAwait> in combination with event loops for similar semantics.
101              
102             =head2 Error
103              
104             L<Error>.pm is overly magical and discouraged by its maintainers. Try
105             L<Throwable> for exception classes in L<Moo>/L<Moose>, or L<Exception::Class>
106             otherwise. L<Try::Tiny> or L<Syntax::Keyword::Try> are recommended for the
107             C<try>/C<catch> syntax.
108              
109             =head2 FindBin
110              
111             L<FindBin> is often used to retrieve the absolute path to the directory
112             containing the initially executed script, a mechanism which is not always
113             logically clear. Additionally, it has serious bugs on old Perls and can't be
114             updated from CPAN to fix them. The L<Path::This> module provides similar
115             variables and constants based on the absolute path to the current source file.
116             The L<lib::relative> module resolves passed relative paths to the current
117             source file for the common case of adding local module include directories.
118             Each of these documents examples of achieving the same behavior with core
119             modules.
120              
121             =head2 File::Slurp
122              
123             L<File::Slurp> gets file encodings all wrong, line endings on win32 are messed
124             up, and it was written before layers were properly added. Use L<File::Slurper>,
125             L<Path::Tiny/"slurp">, L<Data::Munge/"slurp">, or L<Mojo::File/"slurp">.
126              
127             =head2 HTML::Template
128              
129             L<HTML::Template> is an old and buggy module, try L<Template::Toolkit>,
130             L<Mojo::Template>, or L<Text::Xslate> instead, or L<HTML::Template::Pro> if you
131             must use the same syntax.
132              
133             =head2 IO::Socket::INET6
134              
135             L<IO::Socket::INET6> is an old attempt at an IPv6 compatible version of
136             L<IO::Socket::INET>, but has numerous issues and is discouraged by the
137             maintainer in favor of L<IO::Socket::IP>, which transparently creates IPv4 and
138             IPv6 sockets.
139              
140             =head2 IP::World
141              
142             L<IP::World> was built from two free publicly available databases. However, over
143             the years one of them was discontinued, and the other is no longer being updated.
144             Therefore the module's accuracy is ever-decreasing. Try L<GeoIP2> as an alternative.
145             That code is I<also> deprecated, but at least its database is still updated.
146              
147             =head2 JSON::Any
148              
149             L<JSON::Any> is deprecated. Use L<JSON::MaybeXS> instead.
150              
151             =head2 JSON::XS
152              
153             L<JSON::XS>'s author refuses to use public bugtracking and actively breaks
154             interoperability. L<Cpanel::JSON::XS> is a fork with several bugfixes and a
155             more collaborative maintainer. See also L<JSON::MaybeXS>.
156              
157             =head2 Net::IRC
158              
159             L<Net::IRC> is an ancient module implementing the IRC protocol. Use a modern
160             event-loop-based module instead. Choices are L<POE::Component::IRC> (used for
161             L<Bot::BasicBot>), L<Net::Async::IRC>, and L<Mojo::IRC>.
162              
163             =head2 Switch
164              
165             L<Switch>.pm is a buggy and outdated source filter which can cause any number
166             of strange errors, in addition to the problems with smart-matching shared by
167             its replacement, L<feature/"The 'switch' feature"> (C<given>/C<when>). Try
168             L<Switch::Plain> or L<Syntax::Keyword::Match> instead.
169              
170             =head2 XML::Simple
171              
172             L<XML::Simple> tries to coerce complex XML documents into perl data structures.
173             This leads to overcomplicated structures and unexpected behavior. Use a proper
174             DOM parser instead like L<XML::LibXML>, L<XML::TreeBuilder>, L<XML::Twig>, or
175             L<Mojo::DOM>.
176              
177             =head1 AFFILIATION
178              
179             This policy is part of L<Perl::Critic::Community>.
180              
181             =head1 CONFIGURATION
182              
183             Occasionally you may find yourself needing to use one of these discouraged
184             modules, and do not want the warnings. You can do so by putting something like
185             the following in a F<.perlcriticrc> file like this:
186              
187             [Community::DiscouragedModules]
188             allowed_modules = FindBin Any::Moose
189              
190             The same option is offered for L<Perl::Critic::Policy::Community::PreferredAlternatives>.
191              
192             =head1 AUTHOR
193              
194             Dan Book, C<dbook@cpan.org>
195              
196             =head1 COPYRIGHT AND LICENSE
197              
198             Copyright 2015, Dan Book.
199              
200             This library is free software; you may redistribute it and/or modify it under
201             the terms of the Artistic License version 2.0.
202              
203             =head1 SEE ALSO
204              
205             L<Perl::Critic>