http://www.perlmonks.org?node_id=1206883

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

Hello monks, This is my first forum post and seeking advice as limited experience w/ Perl. I have a perl package Foo, and several submodules for purpose of structuring my code (Foo::Util, Foo::Bar, etc.). The client shouldn't be interfacing directly with these submodules. Are there any best practices around packaging, documenting. etc., that I should know about? It is pointless to document the submodules, but at same time, they would get installed into the user's library path so I feel like something should be documented (even if just to indicate do not call directly). Any help / advice is much appreciated. Thanks!
  • Comment on documentation best practices for internal modules

Replies are listed 'Best First'.
Re: documentation best practices for internal modules
by eyepopslikeamosquito (Bishop) on Jan 08, 2018 at 09:59 UTC

    I agree with Discipulus that you should document all your modules for those that must maintain them in the future (even if that is only you).

    For advice on how to document your modules, see this recent general advice on documenting Perl code.

    Update: Some further commenting and documentation tips from On Coding Standards and Code Reviews:

    1. Prefer to make the code obvious.
    2. Don't belabour the obvious.
    3. Generally, comments should describe what and why, not how.
    4. Remove commented-out code, unless it helps to understand the code, then clearly mark it as such.
    5. Update comments when you change code.
    6. Include a comment block on every non-trivial method describing its purpose.
    7. Major components should have a larger comment block describing their purpose, rationale, etc.
    8. There should be a comment on any code that is likely to look wrong or confusing to the next person reading the code.
    9. Every non-local named entity (function, variable, class, macro, struct, ...) should be commented.
    10. Separate user versus maintainer documentation.
    11. CPAN Module Documentation. Tutorial and Reference; Examples and Cookbook; Maintainer; How your module is different to similar ones; Change log; Notes re portability, configuration & environment, performance, dependencies, bugs, limits, caveats, diagnostics, bug reporting.

Re: documentation best practices for internal modules
by Discipulus (Abbot) on Jan 08, 2018 at 07:58 UTC
    Hi hotshoe and welcome to the monastery!

    I'm not the best one here around to answer your question, but with my limited experience to document a module, even a sub one (as you call them) is always a plus and something worth to be done.

    Primarly because you as author will be the first consumer of documentation later on when you will have forgotten all details of the sub modules.

    In second place an eventual user of the main module can be interested or in the need to know how Foo::Bar exposes it's functionalities to Foo and will be grateful to you to find what they need in the docs, instead of reading your source code.

    Third the submodule doc is the place where to state clearly that the module must not be called directly and you put this in the synopsis and in the very beginning of the doc. Then a short list of included functions and what they expect and what they return is the bare minimum you must put inside the submodule documentation.

    Take one of many module that includes sub modules not intended to be called directly as, even if it is a bit particular case, the core module File::Spec Infact File::Spec::Win32 File::Spec::Unix File::Spec::Mac and company all have their own short but useful documentation.

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: documentation best practices for internal modules
by Athanasius (Bishop) on Jan 09, 2018 at 07:27 UTC

    Hello hotshoe, and welcome to the Monastery!

    You have received some good answers above. I just want to add a couple of points:

    (1) Your statement:

    The client shouldn't be interfacing directly with these submodules.

    is ambiguous. Do you mean that the client must not access these modules directly; or only that the client doesn’t need to do so to use the Foo module? As a general rule, you should aim for the latter. Good design entails loose coupling between modules. Even if a given module is not likely to be reused, design it as though it could be reused and your architecture will be cleaner and easier to maintain.

    (2) In those rare cases where access to a module such as Foo::Util really must be restricted to Foo, you can take stevieb’s ingenious approach. But bear in mind this famous quote from Larry Wall:

    Perl doesn’t have an infatuation with enforced privacy. It would prefer that you stayed out of its living room because you weren’t invited, not because it has a shotgun.

    Perl has a simple convention to indicate “not invited” — an initial underscore. So, if you rename Foo::Util to Foo::_Util, any experienced Perl programmer will immediately know that this module is for internal use only. An example is provided by the Moo::_Utils module in the Moo distribution on CPAN.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thanks for the advice monks! Comments were helpful. Athanasius, in regards to your question, it's that client doesn't need to (i.e., the latter). Although, as mentioned, several of the internal classes I'm working on would have little or no value outside of Foo class. Regardless, I'l take advice to document and may utilize the underscore in internal module name that has no value whatsoever outside of Foo. Thanks again!! -Roland.
Re: documentation best practices for internal modules
by stevieb (Canon) on Jan 08, 2018 at 15:33 UTC

    I'm with the others; document everything. Because that's been covered, I'll leave it alone.

    If you don't want your internal modules/subs being used by external code, you can catch that. Here's a rudimentary example:

    use warnings; use strict; package Internal; { sub foo { my $caller = (caller(1))[3]; my $me = (caller(0))[3]; if ($caller !~ /^Internal::/){ die "$me is only available internally\n" } ... } } package External; { sub bar { Internal::foo(); } } package main; External::bar(); __END__ Internal::foo is only available internally

      If you don't want your internal modules/subs being used by external code, you can catch that.

      Abide by the ethos?

      Why assume you're smart enough to know what your users are paying for today/tomorrow?

      This is all the checks you need

      =head1 FOR INTERNAL USE ONLY This is private api for internal use only, it can change at any time, +standard disclaimers apply, use at your own risk.... =cut
Re: documentation best practices for internal modules
by sundialsvc4 (Abbot) on Jan 08, 2018 at 23:55 UTC

    I have read plenty of unfamiliar code that was written by someone whose then-present motivations I simply did not understand, except for the comments that he left behind ... and that person was me.   If you set-aside a program that you wrote, even for a very short time, then you will frankly be amazed at how little you actually remember of what you did and why.   The programmer’s intentions will now be an utter mystery.   Comments and per-sub documentation is therefore quite essential.

    I also believe that you should maintain your code in a change-control system and keep an issue-tracker ... even though you imagine that no one other than yourself will ever touch this code and that you will remember everything.   You will not.

    “Code review” awareness is also crucial even if you are reviewing yourself.   Would someone who had never encountered this piece of code before, manage to understand it ... accurately and quickly?   Is the logic “stupid simple?”   Yes, this is important, because soon enough that person will come along.   And that person could very well be you.