Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Tuesday April 28, 2009
03:23 AM

Solving the Role Debacle

[ #38885 ]

In reading this rather long and contentious debate on roles, you might get a a bit confused on a few points. If you read through one of chromatic's rebuttals carefully, you'll see that he listed the following four design goals behind roles:

  1. Inheriting from other classes which perform those roles
  2. Composing in the behavior of various roles
  3. Delegating specific activity to other entities which perform those roles
  4. Reimplementing part or all of the behavior encapsulated in the role

He then points out that for the latter two cases, you don't want to compose in the behavior of those roles. By consuming a role, you declare that you provide its capabilities, but you provide the implementation. While this is not what we're doing at the BBC, it's a very reasonable use case. However, chromatic then goes on to argue the following:

The moment you throw a mandatory default warning on two of the four appropriate and specified uses of roles, you've penalized them. You're subtly encouraging people not to use the most important and most powerful features of roles! You're actively discouraging people from taking advantage of allomorphism using well-established and long-recommended design techniques explicitly made safer and more understandable by roles.

Had this been said up front rather than buried in a thread, I would have had a much clearer understanding of the issue and much debate could have been avoided. Regrettably, the warning is now getting pulled from roles and people who don't want silent "action at a distance" are now penalized.

So if it's inconvenient to silence those warnings and thus they're argued against, isn't the goal here to go to the root cause of the problem and make it convenient to silence those warnings? In fact, I've sent off a proposal to the Moose list which not only makes it convenient, but proposes an addition to Moose roles which makes chromatic's use both case explicit and easier to use. It silences those warnings but in a safe way.

package My::Customer;
use Moose;
with 'Role::Serializable' => { includes => [] };

In other words, design goals 1 and 2 would tend to have "excludes" scattered here and there, just as we do here. Design goals 3 and 4 would have "includes" here and there. It would be the mutually exclusive exact opposite of "excludes". If you have "includes => []" for your role, all "non-included" methods would be added to "requires" and you have an interface. No warnings needed in this case. Heck, if you want to treat a role as an interface but still include, say, their "to_xml" method:

package My::Customer;
use Moose;
with 'Role::Serializable' => { includes => [ 'to_xml' ] };

All methods must be overridden except that one. Simple, explicit, satisfies my needs and seems to satisfy chromatic's. I think it's a good compromise.

The syntax still isn't perfect, but there's only so much you can do with straight Perl. However, I think this illustrates a point which too many of us forget about: when you have a problem, start looking for the root cause and see if you can solve that problem. Coming up with an interim solution which just shoves the problem elsewhere doesn't do anybody any good.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • I would prefer to have warnings for possible problems that you would only run into by accident. If you would not want that to happen, you could just declare so.

    What's Rolsky's position on the subject, If I may ask?

    • I don't know how Dave feels, but Stevan Little has already said "no". He prefers new features to be tested in a MooseX:: class and that makes sense to me.

      • We always return to the same issue though, of whether new users should have to explicitly declare features which make it easier to use, instead of experts explicitly expressing to ignore different warnings.

        Moose has become a stepping stone in an Enlightened Perl and any Enlightened programming language, and users should not be bitten by these simple things. Also, users should not (by design), have to know about various MooseX modules to fix the behavior for them.

        We should work on making these easy to use fo

        • You're not stepping out of line at all. I think everyone who has thoughts on these matters should feel free to chip in.

        • The difference, and this is the important one here, strict enables warnings about features in Perl that we actively want to discourage, Symbolic references, global variables, undeclared barewords. The Role warning specifically is triggered on valid and more importantly encouraged use cases.

          There's an idiom of role usage where you define a default implementation of a method and then override that in classes where you need a more specific version of it. You may recognize this, it's one of the reasons people u

          • First I want to thank you for taking the time/effort to inform me more about this. Sorry for the late response.

            Secondly, there are still two issues that make me ponder:

            • What about beginners who have their methods overridden without knowing? I'm not saying that warning everyone is the only solution, I just know this is an issue we should think of, because it's more important, IMHO.
            • I wish I could say that most beginners don't use Perl::Critic, but unfortunately the case is that most programmers don't use P
            • One thing which might help is that I just uploaded MooseX::Role::Strict [cpan.org] (it will be a bit before that link is good). Hopefully that will help people who are concerned about this.

              Now I'm looking into adding includes into Moose.

            • Perhaps this is possible?

              It's possible, but I believe it's inadvisable. It's not the role's business how anyone else wants to perform the role. Any role which dictates how people perform the role (composition, inheritance, delegation, allomorphism) is not a role anymore.

              • Sure it's OK. The role isn't telling any class how to perform that role. It's just providing a way of meeting a need that you apparently don't have. Your objection was that by adding the warning, it forced programmers to use clumsy ways of getting around the fact that you might want to use a role as an interface or primarily as an interface. By combining strict roles and 'includes', some of the difficulty goes away. For example:

                package My::Class;
                use Moose;
                # or whatever the final syntax is, if accepted

                • Strict roles reintroduce one of the problems that I always intended roles to solve: enforcing implementation details at the worst possible place, where you know the least about how people will actually use them.

                  Let me put it this way. I believe that allowing the creator of a role to specify that you must use inheritance or delegation or allomorphism or reimplementation to satisfy the demands of the role is like allowing the creator of a class to say that you cannot inherit from it. The real responsibility

                  • To be fair, there's one category of behavior where it's acceptable for the creator of a role to enforce a usage strategy: where the role only requires the presence of other methods without providing implementations. Note, however, that even that case does not dictate how the composing class provides those methods.

                  • I apologize. You have offered a solution and just because I'm so frustrated with this discussion, I've mischaracterized your position. I'm sorry about that and I certainly didn't mean to.

      • Actually, I said no to the idea of:

        with 'Role::Serializable' => { includes => [] };

        meaning "don't compose any methods, but i still want to do this role", because I think that it is not very clear and could very easily be confusing to people. After all you would never say:

        with 'Role::Serializable' => { excludes => [] };

        it just wouldn't make sense. I just really never liked APIs where the lack of something was significantly meaningful.

        Now, all that said, I actually really kind of like:

        with

  • Regrettably, the warning is now getting pulled from roles and people who don't want silent "action at a distance" are now penalized.

    I have to agree with perigrin, this is a rather unfair characterization of the situation. We initially enabled the warning because it is useful and helpful, however the big downside that we all saw was that for people who were well versed in Roles and knew well how they worked were forced to add code to silence the warning. After considerable debate, both in the use.perl t

    • Additionally some work has been done (not sure how final/releasable it is) on making it actually easier for you to write something like MooseX::Roles::Strict, which would be quite painful with the current codebase.

      Actually the basic hook you need I think has been released. I went about doing this when this whole discussion started because it *should* have been possible, and Sartak made it work the right way (as opposed to my ugly hack). You can now say: use Moose::Role -metaclass => 'MyRole::Metaclass'