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   1036 use strict;
  1         3  
  1         44  
4 1     1   6 use warnings;
  1         3  
  1         60  
5              
6 1     1   7 use Perl::Critic::Utils qw(:severities :classification :ppi);
  1         2  
  1         70  
7 1     1   534 use parent 'Perl::Critic::Policy';
  1         4  
  1         6  
8              
9             our $VERSION = 'v1.0.4';
10              
11             sub supported_parameters {
12             (
13             {
14 4     4 0 32245 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 243 sub default_severity { $SEVERITY_HIGH }
21 0     0 1 0 sub default_themes { 'community' }
22 4     4 1 415575 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. Note that JSON (the distribution) uses JSON::XS by default when installed.',
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   549 my ($self, $module, $elem) = @_;
45 19         54 my $desc = "Used module $module";
46 19   33     67 my $expl = $modules{$module} // "Module $module is discouraged.";
47 19         90 return $self->violation($desc, $expl, $elem);
48             }
49              
50             sub violates {
51 60     60 1 9284 my ($self, $elem) = @_;
52 60 100 66     195 return () unless defined $elem->module and exists $modules{$elem->module} and not exists $self->{_allowed_modules}{$elem->module};
      100        
53 19         1849 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>. Note that L<JSON>
156             (the distribution) uses L<JSON::XS> by default when installed.
157              
158             =head2 Net::IRC
159              
160             L<Net::IRC> is an ancient module implementing the IRC protocol. Use a modern
161             event-loop-based module instead. Choices are L<POE::Component::IRC> (used for
162             L<Bot::BasicBot>), L<Net::Async::IRC>, and L<Mojo::IRC>.
163              
164             =head2 Switch
165              
166             L<Switch>.pm is a buggy and outdated source filter which can cause any number
167             of strange errors, in addition to the problems with smart-matching shared by
168             its replacement, L<feature/"The 'switch' feature"> (C<given>/C<when>). Try
169             L<Switch::Plain> or L<Syntax::Keyword::Match> instead.
170              
171             =head2 XML::Simple
172              
173             L<XML::Simple> tries to coerce complex XML documents into perl data structures.
174             This leads to overcomplicated structures and unexpected behavior. Use a proper
175             DOM parser instead like L<XML::LibXML>, L<XML::TreeBuilder>, L<XML::Twig>, or
176             L<Mojo::DOM>.
177              
178             =head1 AFFILIATION
179              
180             This policy is part of L<Perl::Critic::Community>.
181              
182             =head1 CONFIGURATION
183              
184             Occasionally you may find yourself needing to use one of these discouraged
185             modules, and do not want the warnings. You can do so by putting something like
186             the following in a F<.perlcriticrc> file like this:
187              
188             [Community::DiscouragedModules]
189             allowed_modules = FindBin Any::Moose
190              
191             The same option is offered for L<Perl::Critic::Policy::Community::PreferredAlternatives>.
192              
193             =head1 AUTHOR
194              
195             Dan Book, C<dbook@cpan.org>
196              
197             =head1 COPYRIGHT AND LICENSE
198              
199             Copyright 2015, Dan Book.
200              
201             This library is free software; you may redistribute it and/or modify it under
202             the terms of the Artistic License version 2.0.
203              
204             =head1 SEE ALSO
205              
206             L<Perl::Critic>