Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

Sensible ordering of 'use' (if any)

by anneli (Pilgrim)
on Nov 01, 2011 at 09:34 UTC ( [id://935070]=perlquestion: print w/replies, xml ) Need Help??

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

Dear monks;

Is there any generally accepted wisdom as to the ordering of use statements in the header of a .pm? Here's the header of one of my modules:

use strict; use warnings; use utf8; use namespace::autoclean; use Coro; use AnyEvent; use LWP::Protocol::AnyEvent::http; use Net::Twitter; use AnyEvent::Twitter::Stream; use YAML::Any; use DateTime::Format::Strptime; use Data::Visitor::Callback; use Log::Log4perl qw(:easy); Log::Log4perl->easy_init($DEBUG); use Moose; has 'twitter' => (is => 'rw', required => 1, isa => 'Net::Twitter'); has 'listener' => (is => 'rw', required => 1, isa => 'AnyEvent::Twitte +r::Stream'); has 'mongo' => (is => 'rw', required => 0, isa => 'MongoDB::Databas +e');

As you can see, it grew quite organically. I could sort it alphabetically (which at least puts namespaces together), but then that throws Net::Twitter and AnyEvent::Twitter::Stream apart (for instance), which isn't great for determining what sorts of things I'm pulling in.

Any advice is appreciated.

Anneli

Replies are listed 'Best First'.
Re: Sensible ordering of 'use' (if any)
by GrandFather (Saint) on Nov 01, 2011 at 09:47 UTC

    You could group by "association" then sort within groups. I tend to separate groups by a blank line in such a case.

    True laziness is hard work
      use strict and warnings first. 'use utf8' is a bug. The rest doesn't matter.

        use utf8 is a bug? These source files happen to contain a lot of non-ASCII, but maybe I'm misunderstanding you...

Re: Sensible ordering of 'use' (if any)
by davido (Cardinal) on Nov 01, 2011 at 15:48 UTC

    I've seen alphabetical, but I tend to do it like this:

    1. First, the pragmas, and Perl version number if necessary.
    2. The "helpers"; things like List::Util, Readonly... very general utility modules.
    3. The more specific utility modules such as File::Find, Text::Template.
    4. The "This is why we're here." modules such as WWW::Mechanize, Benchmark, XML::Twig.

    To me the idea is to start with the generalities that may be most applicable to all scripts, and then work my way toward the most specific modules to this particular application. At the same time I try to cluster modules that work together... together.

    As I think about it, that's sort of a bottom up approach. Perhaps I should reverse the order to add clarity in reading the source, but I'm in this habit, and would probably only change if strong benefits are shown to be embodied in another approach.

    One caveat is that there are a few modules which specifically state that you must use this one before that one. Inline::Files has to be listed before Inline::C, for example. In such cases it's important to # document the need, because today it may be obvious but tomorrow you (or I) will forget.

    If I'm using a module for one small portion of a program, and not specifying an import list, I often # comment on what specific need this module is filling. That way if the program changes and that use is removed, I can quickly identify the module that is no longer necessary.

    That's a habit that came from C, where it's common to list a whole bunch of header files to #include, and then quickly forget why they're being included.

    I've considered # documenting along side my module uses which ones came from core, which I installed from CPAN, and which I wrote myself, but that level of documentation is more ambitious than I've been able to self-enforce.

    Update:

    I just checked, and unless I'm missing it, Perl Best Practices is silent on the issue of order of using modules. I recently re-read the book too, but that still doesn't mean I haven't forgotten. :) I wonder if the omission is because it doesn't matter, because it's too obvious to mention, or because it just wasn't considered.


    Dave

Re: Sensible ordering of 'use' (if any)
by Khen1950fx (Canon) on Nov 01, 2011 at 10:14 UTC
    Your ordering is good. As for me, I try to order in a stair-step fashion, left to right, strict first and warnings second, but that's just my habit.
    #!/usr/bin/perl use strict; use warnings; use utf8; use Coro; use AnyEvent; use YAML::Any; use Net::Twitter; use namespace::autoclean; use Data::Visitor::Callback; use AnyEvent::Twitter::Stream; use DateTime::Format::Strptime; use LWP::Protocol::AnyEvent::http; use Log::Log4perl qw(:easy); Log::Log4perl->easy_init($DEBUG); use Moose; has 'twitter' => ( is => 'rw', required => 1, isa => 'Net::Twitter', ); has 'listener' => ( is => 'rw', required => 1, isa => 'AnyEvent::Twitter::Stream', ); has 'mongo' => ( is => 'rw', required => 0, isa => 'MongoDB::Database', );
Re: Sensible ordering of 'use' (if any)
by Anonymous Monk on Nov 01, 2011 at 11:31 UTC

    I put both strict & warnings pragmas listed first on a single line. Rest are alphabetically sorted.

    That will be followed by other pragmas in a group, which will be followed by group of modules. If the list is "large enough" and/or list has highly unrelated modules, modules will be divided into subgroups by function.

    Above could be then ...

    use strict; use warnings; use utf8; use namespace::autoclean; use AnyEvent; use AnyEvent::Twitter::Stream; use Coro; use LWP::Protocol::AnyEvent::http; use Net::Twitter; use Data::Visitor::Callback; use DateTime::Format::Strptime; use YAML::Any; use Log::Log4perl qw(:easy);
Re: Sensible ordering of 'use' (if any)
by ForgotPasswordAgain (Priest) on Nov 01, 2011 at 23:38 UTC

    I help maintain a lot of code, so this is my preference, for what it's worth (code style is basically a flamewar kind of topic; I don't really care if anyone follows what I prefer, I usually follow the existing style and don't add extraneous diffs by editing things to fit my style).

    After use strict and warnings, I prefer all CPAN modules in ABC order, followed by all internal (company) modules in ABC order. Sometimes a module must be loaded before another one, in which case do that and comment why the order is unusual.

    I prefer not to have superfluous comments like

    # modules here ... # globals here ... or ########################################### # Class Methods ...

    as these should be obvious. (To me, these comments just take up vertical space.)

    After that'd I prefer any global variables, including constants (even if use constant is used). Any "runtime" code follows that (populating a hash dynamically, for example), followed by methods (subs). Non-API methods or functions should be preceded by an underscore, IMHO.

    Runtime code shouldn't be interspersed with (compile-time) methods, though there are naturally exceptions. For example, I've found it's convenient to put BEGIN { memoize 'method' } after subs when you use Memoize. It's also occasionally though rarely necessary to wrap a lexical (or BEGIN) block around a method (or group of methods), for example for (closured) cache variables; but cache variables might as well be global ones at the top, with a note that that's what they are (you could argue for limiting them lexically to the methods where they're used, but it clutters things and adds indentation, not to mention the "surprise" of runtime code in the middle of the module).

    After all code, end with a 1;, nothing cute, followed by __END__ and POD (hopefully).

    For scripts, it's pretty much the same. Try to lexically scope variables as much as possible; some globals are fine, but being sloppy with them is not only harder to maintain but also invites wasting RAM. I also prefer logical units of code to be in subs, not just a long string of stream-of-thought code. I used to put everything like

    main(); exit; sub main { sub1(); .... }

    but I found that naming the sub "main" is a potential problem (extremely rarely, to the point of pedantry - but it's because the default package of Perl is called "main"), so anymore I call it something else. Sometimes I just put a lexical block around the runtime code, maybe even label the block with "MAIN:", but I'm not really sure what's best there. I still follow this runtime block by exit;, then follow that by only non-runtime subroutines as for modules above.

    I know some people prefer putting script code in modules, then basically just having something like this:

    use My::App; My::App->run();

    but as someone who maintains a lot of code, I find this kind of script a bit annoying. (I think of it as "decoy" code, since where you see the error/warning will not actually be where the problem is.) I understand the desire for reusable code, but I don't know if I've ever seen the structure/logic of a script re-used anywhere. Ok, command-line parsing. I can still find it annoying, can't I? :)

    For what it's worth. :)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://935070]
Approved by Ratazong
Front-paged by planetscape
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (7)
As of 2024-03-19 02:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found