in reply to Informal Poll: why aren't you using traits?

Because Perl5's OO system sucks rocks and is not to be trusted beyond a simple usage. I say this as someone whose CPAN distros are either OO (Tree, PDF::Template, Excel::Template) or OO-related (Perl6::Roles, Class::LazyLoad). Perl5 OO is kinda like the Wizard of Oz - as long as you don't look behind the curtain, everything is ok. The moment you do, even if by accident!, you're completely and utterly screwed. And, the worst part is that you may not realize you're screwed until you lose the client's data.

Adding roles to an introspective OO language that supports aliasing, like Ruby, isn't hard. I may do that for Ruby, now that I'm thinking about it. Ruby's traits.rb isn't Traits, it's a better version of attribute declarations. So, maybe I should call it roles.rb.

Adding it to Perl, however, is way too complicated. Writing Perl6::Roles was a pain in my butt. Not because the code was hard, but because I had to write so much scaffolding and assume so much about how things worked that it made my head hurt. And, that was with punting a whole lot to the user. That's why it's so limited in what it does. There is no attributes, not expectations, or anything. The free-for-all that is Perl's OO actually makes things worse than better.

As for your question - I would gladly use traits/roles/whatever-they're-called-this-week. But, only if they were well-defined. Right now, as Zaxo said, they're an experimental concept. For example:

Yes, I know a lot of those questions have answers. stvn has done a lot of work in Class::Traits, in his work on the Perl6 metamodel, and in helping me write Perl6::Roles. In all that, he's come up with some darn good answers to a bunch of those questions. That doesn't mean that his answers are complete. And, frankly, his answers may be wrong for some situations.

(Note: stvn doesn't use traits in his production work ... maybe that's a sign that traits aren't ready for primetime.)


My criteria for good software:
  1. Does it work?
  2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
  • Comment on Re: Informal Poll: why aren't you using traits?

Replies are listed 'Best First'.
Re^2: Informal Poll: why aren't you using traits?
by stvn (Monsignor) on Nov 19, 2005 at 17:22 UTC

    Keep in mind that Traits are not Roles. Traits provide much more functionality than Roles do, in fact, they solve most of the things on your list.

    • Can roles demand certain things? If so, can that be satisfied by another role?
    • Any trait can have a list of methods in @REQUIRES and those methods must be provided by either another trait or the consuming class.

    • What happens when conflicts occur?
    • If the conflict occurs during trait composition, the method in conflict is added ot the @REQUIRES array to be satisfied later.

      You can also avoid conflict in two possible ways; 1) rename a method, or 2) exclude a method (which then adds the method to the @REQUIRES array). This is done by the consuming class/trait during compile time.

      Conflicts cannot occur during class composition though, they can only happen between traits. However, if they do happen between traits, and there are methods in the @REQUIRES which are not satisifed by the consuming class, then BOOM your program does at compile time.

    • What happens when conflicts occur between parent roles? For example, if Class A does roles B and D and role B does C and role D does E. If roles C and E both defined foo(), what happens?
    • See above

    • What happens when role B does roles C and E? Does B have to resolve the conflict? If it does, what's the mechanism? If it doesn't, then doesn't Class A have to know too much about role B?
    • B can resolve it (if it makes sense to do so), or it can leave it a "conflict in statis" (aka - @REQUIRES). Keep in mind that Traits (and Roles) will just not be the black boxes that classes are (supposed) to be. In fact, it is probably best to not look at Traits/Roles as being just a "name", but being an entire signature, meaning a name + method list.

    • Can roles have private methods? How does that work with roles composing roles?
    • Traits do not have a direct notion of private methods, however, they are easily accomplished. One possible approach is to use an anon-sub, which would assure the privacy, another would be to ask Ovid to provide some kind of support for them :)

    • What happens when role B does role D and role C does role D, then class A does roles B and C? Does this mean that role D conflicts with itself?
    • Nope, method conflicts in Class::Trait are checked in 2 ways. First we check the name of the method, then if they are the same name, we compare them by strigifying their references, if they are different, then we have a conflict, if they are the same, then we don't. This means that Class::Trait sees the D methods in B and C as the same method, and therefore not a conflict.

    • We have class A does role B which provides foo(). Now, instance A1, at runtime, does role C which provides foo(). What now?
    • Traits are not composable at runtime. Problem solved ;)

    Yes, I know a lot of those questions have answers. stvn has done a lot of work in Class::Traits, in his work on the Perl6 metamodel, and in helping me write Perl6::Roles. In all that, he's come up with some darn good answers to a bunch of those questions. That doesn't mean that his answers are complete. And, frankly, his answers may be wrong for some situations.

    Well, you are absolutely correct, in many situations my answers might be wrong. However, many of my answers are actually me just repeating things I have read which were written by people waaaaay smarter than I will ever be. Not that I assume those people are any more "right", but that they have given it much deeper thought that I have/can. Standing on the shoulders of giants and all that :)

    It is also important that you keep Traits and Roles distinct in your mind. Roles are a limited version of Traits with many (IMO) important features missing. And as you well know, those missing features make things much more complicated since you need to make so many assumptions.

    (Note: stvn doesn't use traits in his production work ... maybe that's a sign that traits aren't ready for primetime.)

    There are a number of reasons for that, but mostly it came down to the fact that (at the time) I did not know how to really properly use Traits. In fact, I am still unsure of how to best utilize them, although Ovid's current usage in his testing work has given me some ideas. I think Traits/Roles requires that you re-wire your brain somewhat, and sometimes production work is not always the best place to test out that re-wiring.

    -stvn

      One possible approach is to use an anon-sub, which would assure the privacy, another would be to ask Ovid to provide some kind of support for them :)

      My support for them is probably going to be limited to documentation unless someone can convince me otherwise. If someone wants private methods, go the anonymous subroutine route. This approach has the benefit of being extremely lightweight and adds no code to Class::Trait.

      I could add code to simply ensure that methods in traits which begin with an underscore are not flattened into the class, but what if someone wants to create a trait with helper methods a class uses but which should not be publicly available? Then I thought "private method could beging with a double underscore". The problem with that is some programmers use single underscores to denote a protected method and double underscores to denote private methods (and I know of one shop which perversely uses the reverse convention). That's when I realized that for me to enforce an abritrary method naming convention on folks was a bad idea. Anonymous subroutines is the way to go.

      Cheers,
      Ovid

      New address of my CGI Course.