perloop

How to organize private methods on Perl objects?


What is the correct way to handle methods which will not be called by the user? For example if the user calls a method, say do_stuff() from a driver script, and if do_stuff() relies on other subroutines, is it best practice to call those subs from within the do_stuff() method as follows:

sub do_stuff {
    my ( $self, %arg ) = @_;
    #does it things
    #and then calls the private sub as follows
    _private_sub( $self, %arg );
}

Solution

  • If your do_stuff method needs the functionality that you decided should be kept "private" then by all means call _private_sub within it. That is precisely its purpose. Of course, having a sub be "private" is a matter of convention as it cannot be enforced.

    I'd like to mention another way, of using coderefs for private subs

    my $_private = sub { ... };  # must be at least predeclared
    
    sub do_stuff {
        my ($self, %arg) = @_;
        # ...
        my $from_private = $self->$_private->(@args);    # or
        my $more_private = $_private->($self, @args);
    }
    

    The syntax is odd but that surely warns the users that it is a private method. This makes it hard for subclasses to inherit, thanks to mob for emphasizing this.

    The second invocation uses $_private as a function rather than a method, so we have to pass the object if it needs it. This further warns against its use. Then it also doesn't undergo the normal method lookup process (and is thus slightly faster), something to be well aware of.

    I am a little uncertain as to what exactly the question seeks.

    If it is about whether to use "private" subroutines in your code, then there is really no accepted best practice. They are very useful, but they are not truly private. I use them, liberally.

    A full answer is to use Moose or Moo, or some other module.