Subject: | nested Roles broken on requires |
Date: | Fri, 5 Dec 2014 17:28:45 +0000 |
To: | "bug-Moose [...] rt.cpan.org" <bug-Moose [...] rt.cpan.org> |
From: | John Macdonald <John.Macdonald [...] oicr.on.ca> |
If a role wishes to consume another role as part of its implementation, and the consumed role has a 'requires' that must be provided; the consuming role can be written as a self-contained role.
The search for 'requires' values is done in the grand(n)parent consumer (the top level consumer which is not a role). Attributes and methods provided by the parent role do not get installed into the top level object until the end of processing of the 'with' statement. So, they have not yet been installed at the point when the parent role tries to consume the child role.
The only way to make it work is for the top level object to consume the parent role, and then, in a separate 'with' statement, consume the child role. (Even listing both the parent and the child in the same 'with' statement does not work - the parent's attributes/methods are not installed when the child 's 'requires' statement is processed.)
This breaks encapsulation badly. Every consumer of the parent role must be coded to provide the child role that the parent needs for its internal implementation, and must provide it in a separate with statement. If the parent role is changed to use a different implementation, then all consuming object definitions must be found and fixed to deal with the revised internal needs of the consumed role.
I suspect that this problem is inherent in the way roles have been implemented - the attributes and methods of a collection of roles are only inserted into the final parent after they have been fully processed. That suggests that fixing it may cause existing code to break. I'd be happy to be wrong about this though, and see someone find a safe way of fixing the problem.
In the attached tar,
BRole.pm is the child role
ARole.pm is the parent role written in a fully encapsulated way
ARoleNoWith.pm is the same role, excluding the 'with' statement consuming BRole
ABRole.pm is a grandparent role that tries to express the separated 'with' statement requirement to provide the encapsulation again
test1.pl is the way the non-role top level consumer "should" be written - only requesting the role that it is actually using - it fails because ARole's attempt to consume BRole complains about the requirement missing from 'main' - it fails because ARole|BRole have a requirement that isn't provided in 'main'
test2.pl re-writes the top level consumer to "know" that ARole also implies a need for BRole but using a single 'with' statement
test3.pl re-writes the top level consumer with the addition implementation knowledge that the two roles must be consumed separately and in the right order - it compiles correctly
test4.pl uses the ABRole attempted workaround - it again gets the complaint thatABRole has a requirement that must be provided in 'main'
John Macdonald
Software Engineer
Ontario Institute for Cancer Research
MaRS Centre
661 University Avenue
Suite 510
Toronto, Ontario
Canada M5G 0A3
Tel:
Email: John.Macdonald@oicr.on.ca
Toll-free: 1-866-678-6427
Twitter: @OICR_news
www.oicr.on.ca<http://www.oicr.on.ca/>
This message and any attachments may contain confidential and/or privileged information for the sole use of the intended recipient. Any review or distribution by anyone other than the person for whom it was originally intended is strictly prohibited. If you have received this message in error, please contact the sender and delete all copies. Opinions, conclusions or other information contained in this message may not be that of the organization.
Message body not shown because it is not plain text.