Daniel,

On Jul 26, 2009, at 5:06 AM, Daniel Pittman wrote:
G'day.

In implementing a Moose::Role I have run into a question that I can't find an
easy or obvious answer to in the documentation.

So, in my role I have several methods that need to perform some non- trivial operations that are identical, but which are also strictly internal: they are not part of the API, because they are not really useful outside the code,
especially if I change the implementation at all.[1]

So, at the moment I do this:

 package Example;
 my $find_stage = sub { my ($self, $arg) = @_; ...; };

 sub dance {
    my ($self, $where) = @_;
    my $stage = $find_stage->($self, $where);
    ...;
 }

 sub sing {
    my ($self, $where) = @_;
    my $stage = $find_stage->($self, $where);
    ...;
 }

That ensures that I don't go leaking the 'find_stage' method as part of the API, or conflicting with other roles or the base class, or whatever. The "Stage", for what it is worth, is an implementation detail; it isn't useful
without the context of the role.

So, is there a better way to implement a private method — one that isn't
available outside the context of the role, and isn't exported?

No, I think this way is the best if you truly want privacy.


Hmmm. In writing this all down I had to think about it, and it occurs to me that I might be facing this problem because of a higher level design decision.

At the moment I create one attribute each time a "stage" is created on the class; the methods in the role then look those up using the MOP by name in
order to obtain the internal implementation.

This sounds wrong unless you are creating an anon-class for each instance. Otherwise your class will just keep getting attributes added to it that all instances share (even if they have different "stage"s).

I could, I guess, replace that with a single attribute containing a hash, mapping names to "stage" instances. The sing and dance methods would then need to do a hash lookup in a know attribute, so the entire helper could be
eliminated...

This sounds a lot saner to me.

In this case the "stage" is a semantic feature similar enough to an attribute, so an object could conceivably have quite a few of them, but the average would
probably be somewhere around half a dozen or so.

If you actually "program" with these stages, then you might consider moving them up to the meta-level. There is a great paper in the book "Advances in object-oriented metalevel architectures and reflection" called "Using the CLOS metaobject protocol to Implement a Frame Language" that describes adding meta-level "things" to CLOS to implement a sort of embedded language. Here is a link to the google book version - http://books.google.com/books?id=pvoefFn_lToC&pg=PA129&lpg=PA129&dq=Using+the+CLOS+metaobject+protocol+to+Implement+a+Frame+Language&source=bl&ots=Veq-Gd7Sj5&sig=ZsgYGcR3cuyxWWIr4U29e-hyTX0&hl=en&ei=oHVsSvbTMsWFtgfP4oibAQ&sa=X&oi=book_result&ct=result&resnum=1

It is a pretty good read even if it is not what you are looking for.

- Stevan

Reply via email to