Join the Stack Overflow Community
Stack Overflow is a community of 6.6 million programmers, just like you, helping each other.
Join them; it only takes a minute:
Sign up

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 );
}
share|improve this question
2  
Check this out stackoverflow.com/questions/1734385/… – aggaton Jan 6 at 23:48
    
there doesn't seem to me to be any reason not to just call it as $self->_private_sub(%arg) – ysth Jan 6 at 23:55
up vote 3 down vote accepted

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.

share|improve this answer
    
Doesn't that make it hard for subclasses to inherit your private method? – mob Jan 6 at 23:57
    
@mob Well, it does, thus the warning. It still can be a choice, for those that will not be subclassed. Are you saying that it shouldn't be used really (as a matter of "good practices")? – zdim Jan 6 at 23:59
1  
No, but I am saying I just learned that $sqrt=sub{sqrt($_[0])}; print 9->$sqrt will actually output 3! – mob Jan 7 at 0:00
1  
@mob Huh ... ?? ... um, it does work! I don't get it (yet -- don't tell me please! :). – zdim Jan 7 at 0:04
    
While you are at it, look up mst's talk you did what? on YouTube. :-) – simbabque Jan 7 at 9:48

To my knowledge, there's no "correct" way. Perl doesn't provide the ability to hide the functions, at least that I've ever run across. What I've done is use a naming standard where I start the internal-only function names with an underscore and clearly document that they're never to be called by external callers.

EDIT: The other answers triggered a thought. In each private method, you could check the results of the "caller ()" function and abort if the caller is anyone other than the local module. Honestly, I personally wouldn't go to the trouble, but if it's really important to you for some reason, that would emphasize the private nature of these methods.

share|improve this answer
    
I think you're right, and your convention of using a leading underscore is widely used. – reinierpost Jan 7 at 0:05

As opposed to $self->_private_sub(...)? In my mind, the $obj->_method notation is always used with function that act on an instance of your class, and other kinds of calls are always used for other kinds of functions.

But if you're going to be paranoid, why not use an unconventional way of packing your arguments that will confound anyone that tries to use your private method in an object oriented way?

sub do_stuff {
    my ( $self, %arg ) = @_;
    ...
    _private_sub( %arg, $self );
}

sub _private_sub {
    my $self = pop;
    my %args = @_;
    ...
}
share|improve this answer
    
Alright, this is a real mind-job :) (Just ... they'll probably look it up in the source and still go ahead) – zdim Jan 7 at 0:06
    
That is horrible. Private or not, security through obscurity is hardly a good idea. This will make your maintenance programmer hate you (remember that could be you), and stuff will break every time a user (or you) tries to call that _private_sub as a method. Mixing methods and functions in one class should not be the way to go. – simbabque Jan 7 at 9:53
    
I often wish I could upvote my own answers, but yeah, sometimes I wish I could downvote them, too. – mob Jan 7 at 17:33

All of the answers you have received so far say that it can't be done. But it can - in Perl 5.18 and later. See the section on lexical subroutines in perldoc perlsub.

Lexical Subroutines

WARNING: Lexical subroutines are still experimental. The feature may be modified or removed in future versions of Perl.

Lexical subroutines are only available under the use feature 'lexical_subs' pragma, which produces a warning unless the "experimental::lexical_subs" warnings category is disabled.

Beginning with Perl 5.18, you can declare a private subroutine with my or state. As with state variables, the state keyword is only available under use feature 'state' or use 5.010 or higher.

These subroutines are only visible within the block in which they are declared, and only after that declaration:

no warnings "experimental::lexical_subs";
use feature 'lexical_subs'; 

foo();              # calls the package/global subroutine

state sub foo {
  foo();            # also calls the package subroutine
}

foo();              # calls "state" sub
my $ref = \&foo;    # take a reference to "state" sub

my sub bar { ... }
bar();              # calls "my" sub

To use a lexical subroutine from inside the subroutine itself, you must predeclare it. The sub foo {...} subroutine definition syntax respects any previous my sub; or state sub; declaration.

my sub baz;         # predeclaration
sub baz {           # define the "my" sub
  baz();            # recursive call
}
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.