Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Informal Poll: why aren't you using traits?

by Ovid (Cardinal)
on Nov 18, 2005 at 21:09 UTC ( [id://509958]=perlmeditation: print w/replies, xml ) Need Help??

Out of curiosity, why aren't you using traits?

    ( ) I don't understand traits.
    ( ) I've never heard of traits.
    ( ) I prefer multiple inheritance or mixins.
    ( ) Single inheritance is good enough for me.
    ( ) I don't know of a robust/good Perl implementation.
    ( ) Traits are bad, m'kay.
    ( ) Other _______________.

Would you be interested in learning more about traits or do you think they're just another silly buzzword? If you are interested in traits, what would it take to get you to start using them?

One thing I've noticed about traits is that most discussions of traits seem to revolve around examples which don't really match up with what people need in the real world. This, curiously, is the same problem that many beginning OO examples have. As a result, people learn about OO and often say "why bother?" I think the same problem affects traits despite how useful they are. I do have a rather long journal entry about my real-world use of traits, but it assumes a bit of knowledge about what traits are.

Cheers,
Ovid

New address of my CGI Course.

  • Comment on Informal Poll: why aren't you using traits?

Replies are listed 'Best First'.
Re: Informal Poll: why aren't you using traits?
by BrowserUk (Patriarch) on Nov 19, 2005 at 04:13 UTC

    [X] Other: I've never been one for buzzword compliance

    Before anyone gets too upset about that, I'll explain that so far, "Traits" are nothing more than a buzzword to me.

    Unlike a lot of the other responders so far, I have read the traits paper--several times in fact--and I am convinced that the basic issue that they are trying to address needs tackling.

    I also think that "roles", "mix-ins", "behaviours", the "decorator pattern", "type classes" and several other similar concepts under different names, depending upon where and what language they are associated with and described in terms of, are all attempts to address the same problem.

    The problem being addressed is that single inheritance forces copy&paste code re-use upon the programmer because you cannot (easily) abstract common behaviour from two classes and place it in a separate module from which both can inherit that common code.

    Yes, you can do this once, but if 3 classes share common behaviours, but not all of them are common to all three modules, then you have a partitioning problem. If you lump all the common behaviours into a single module and inherit it by all three modules, then some are going to acquire behaviours that they should not have. If you segregate the behaviours into non-overlapping modules, you cannot inherit the two (or more) modules each of the inheriting classes needs. And if the inheriting modules are derived from other modules, you're completely stymied.

    You can achieve the requirement using multiple inheritance, but this makes for a zillion tiny classes that get inherited at many different levels throughout the inheritance hierarchy. This has a number of bad side effects:

    1. Every time another class comes along that needs one of the behaviours in one of these tiny classes, but not another that it contains, you either have to:
      • split the class. Which results in a maintenance problem updating all the existing classes that previously inherited from one class but now must inherit from two.
      • Subclass the class and override the unwanted behaviour to "remove it". Adding layers and another form of maintenance problem
    2. As the MI inheritance tree get deeper and broader, so everything associated also gets more complex.

      Eg. Documentation gets deeply nested and cross-linked making it extremely difficult to both follow and produce. Trying to work out exactly what interfaces any given class will respond to becomes a nightmare.

    3. Method resolution gets very messy, very quickly.

      Should the inheritance tree be search breadth-first, or depth-first, or depth-within-breadth, or breadth-within-depth, or depth-within-breadth-within-depth, etc.

      In addition, there is the problem that if the search pattern is wholly pre-determined, then what ever that pattern is will never be right for all situations with the result that the class writer will end up having to try and circumvent the default search pattern to achieve his goals. When that starts to happen, everyone--from the class writer, to the class user, to the maintainer, to the documenter--has problems.

      Alternatively, the language/API designer can punt the search pattern decisions off to the class writer by providing APIs/keywords/options that allow each class to specify the search order from it's position within the class hierarchy on up (down?). The most flexible option of all, but also the one guaranteed to cause most headaches for most people. No-one will be able to predict--or document--the search pattern beyond any one class, or any one level, because the next level up (down/through) may change it. Unpredictable and therefore impossible to document.

      And even when you have sorted out the desired search pattern and correctly implemented it--whether in the compiler or interpreter or the classes themselves--there is still the problem that what the code can do correctly time after time, the programmer will often have extreme difficulty in understanding, never mind remembering.

    4. If any level of dynamism in the class hierarchy is allowed--introspection, never mind runtime modification--then the overheads are huge.

      The cost of maintaining the data required for runtime introspection of a wide and deep MI tree are daunting enough.

      If runtime modification of the tree is allowed by the language, then the costs of allowing dynamic modifications to vtables and wholesale duplication of them when new classes are derived from existing ones at runtime, creates the need for a vast runtime database of hierarchical introspection data.

      If additions to, or modifications of, the vtables are allowed, on an instance by instance basis, these costs get even larger.

    5. The runtime cost of method lookup in a dynamic languages--in the face of dynamic search paths, dynamic classes and possibly dynamic instances--means that method lookup will be very slow.

      Even with the addition of method caching at multiple levels, the effect of each modification will result in cascading cache invalidation.

    So far, the various mechanisms I've read about for tackling this underlying problem of OO hierarchies seem to concentrate on the differences in details from the other solutions being proposed.

    What I have yet to see is any research into how to deal with the runtime penalties--memory usage and performance--that are common to all of the proposals.

    The complex hierarchies that result from MI can be reduced at compile time to highly efficient--space and time--vtable structures that effectively eliminates the runtime overhead completely. You trade slow compile times for fast runtime. The programmer may have problems getting his brain around the complexity, but the compiler doesn't.

    Once you move MI, or any of the proposed solutions for reducing or eliminating MI, into a dynamic language, the need to support introspection and dynamic updates to both the hierarchy itself and the vtables that encapsulate it, creates a huge problem for implementing efficient data structures and algorithms to support them.

    From the looking around the web I've done, there seems to be little or no information on ways of implementing this efficiently; nor even any visible ongoing research into it.

    In 10 years time, when we are all using 64-bit processors with effectively unlimited memory (barring cost) and processors are doubled in performance 4 more times, the need for efficient implementation will have disappeared; classes will be downloaded from the web, or will run as services on web; the JofACM will have carried many papers into the problem of efficient implementation; and there will be half a dozen or more live implementations upon which to base judgements of the merits and downsides.

    Until then, arguing about the details--whether "mix-ins" are the same as "traits", or subtly different--all seems way premature.

    So to me, "traits", along with all the rest, are rather ill-defined buzzwords all groping toward a solution to a problem that does need solving. However, as yet, they are presenting opinions about the requirements of the solution and not actual solutions that I can download and use. When the various sets of opinions start to coalesce into a one or two well-defined implementations, that will be the time to go looking for the one that most closely matches my own thoughts.

    Or maybe I should just implement my own ideas--I'll call them "Ingredients". That's catchy. My catch phrase will be "Bake your own classes quickly and easily with pre-prepared Ingredients!" :)

    Your question is a little like asking why I haven't yet bought a Blu-Ray drive. Whilst the two sides in the Blu-Ray -v- HD DVD continue to argue with each other (and amongst themselves) over the details of the next generation of DVD formats, I've only just got around to getting a writable DVD player for my computer.

    If I had bought into (and bought) every new type of DVD reader, writer, or re-writer that has come to the market place over the last 5 or so years, I would now have a dozen or more and have paid premium prices for each as they became available, to the a tune of several thousand pounds I would guess.

    As it is, I just bought one drive for £56, that reads, writes and re-writes 3 different forms of DVD and 2 (or more) types of CD. Worth waiting for.


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      The way this post reads to me is that MI is expensive in dynamic languages, and traits are one of many attempts to address that – that if MI were cheap, we wouldn’t need traits.

      But what about the complexity issue? Programming has always evolved in the direction of greater abstraction; the complexity of software systems we build today is orders of magnitude greater than that of the artifacts created by any other engineering discipline. (And unlike other disciplines, you can do repetitive work once only, and then factor it away – so the complexity keeps growing. This is why software will never be industrialised like other engineering disciplines (not that they are industrialised even remotely to the extent the software types always seem to think they are, and anyway, I digress).) Even the simplicity of throwaway scripts is deceptive: you have an OS beneath, and they run inside an interpreter which takes care of memory management and many other menial tasks; and neither the OS (to a large extent) nor the interpreter are written in assembly, so you also need a compiler. The amount of work that has gone into making Perl oneliners simple is quite imposing.

      Anyway, I’m rambling. The point is that complexity management is by far the most important aspect of designing programming systems (ie. meta-programming), and to me it seems like your post does not go into this at all. You admit that MI becomes unworkable for the programmer in large hierarchies; I believe that’s a much more salient point than its performance.

      Makeshifts last the longest.

        The way this post reads to me is that MI is expensive in dynamic languages, and traits are one of many attempts to address that – that if MI were cheap, we wouldn’t need traits.

        Then I failed dismally in my attempt to convey what I was trying to say :(

        Yes, MI becomes rapidly unworkable in extended hierarchies.

        Yes, Traits and it's kin are an attempt to reduce that complexity.

        Yes, MI is expensive in dynamic langauges.

        But definately NO to if MI were cheap, we wouldn’t need traits..

        I did say (twice) that I am convinced that the basic issue that they are trying to address needs tackling.

        What I hoped to point out is that there are many subtly different attempts at descriptions for solutions being proferred currently, but that they are concentrating on their differences--which are minutae relative to the problems of performance and footprint that they bring with them.

        In compiled languages, where most of the groundwork for Traits and the others is being done, the complexities of method resolution and search order are compile time only costs. By runtime, the method call has been resolved either to a vtable entry, or to the actual entrypoint address.

        Perl, (and all dynamic languages), already have a performance problem with method lookup. One of the major benefits that is hoped to come from the Parrot project is a reduction in the overheads associated with the mechanics of subroutine invokation--stack setup, scope maintenance, closure propagation, etc. If that effort succeeds, then it could reduce the costs of calling a sub to the point where static (compile time) MI would be tolorable from a performance point of view, though the inherent brain-melting problem of MI would persist.

        It would also make Traits (and similar solutions) a practical solution to that MI complexity--but only if the method resolution can be fully resolved at compile-time

        The fear I have is that Perl 6, and other dynamic languages that are trying to adopt trait-like behaviours, are also adding

      • Pre & post method entrypoints.
      • Dynamic inheritance resolution.
      • Dynamic vtables at the class (and maybe instance) level.
      • Full introspection.
      • Runtime macro capabilities.

        Each of these things adds runtime cost to the process of invoking a method.

        The code reads:

        $obj->method();

        The interpreter has to do

        1. Is method a macro? If so, expland it.
        2. What is the class of $obj?

          That's at least a two levels of indirection. One to look up the class name. One to look up the hash storing the method names associated with that classname.

        3. Can classX do method?

          If not, then look up the list of classes/traits/roles that it might inherit this method from.

          Also look up classX' search pattern (depth/breadth/etc.).

          For each superthing, lookup the address of it's vtable and check if it can do the method.

          If not, then look up the list if it's superthings and their search patterns, and vtables and see if they can supply the method.

          Keep going until you find it, or exhaust all possibilities and raise a non-existant method error.

          What happens if you find two (or more) superthingies that could provide that method? Now you have to go through a conflict arbitration process.

        4. Assuming that after all that, we isolated a resolution for the method, we now have to go through lookups for PRE() & POST() methods, and about half a dozen other SPECIAL subs that can be associated with a method or the class it is a part of.

        And that lot, even with the inherent loops I've tried to indicate, is far from a complete picture of the processes involved if all the features muted for P6 come to fruition. All of that was just to find the method to invoke.

        Now you have to sort out all the actual-to-formal parameter mappings, with all the

      • slurpy/non-slurp.
      • named/un-named.
      • required/optional.
      • read-only/read-write
      • by-reference/by value.
      • defaulted/no-default.
      • type constrained.
      • range constrained.
      • does constrained.
      • is constrained.
      • will constrained.

        possibilities and combinations thereof.

        And many of those will themselves require class hierarchy and method resolutions.

        Yes, I agree that there is a complexity problem with MI that must be addressed, but I also see huge performance problems arising out of the solutions be proposed, which when combined with all the other performance sapping, runtime costs being added through the desire for even greater introspection and dynamism.

        Combined, these mean that the single biggest issue I have with the current crop of dynamic language implemetations, performance--which Perl is currently the best of the bunch--is going to get worse in the next generation, not better.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

      I only want to address a few of your points here where I think you actually are mistaken in your assumptions.

      3. Method resolution gets very messy, very quickly.

      Should the inheritance tree be search breadth-first, or depth-first, or depth-within-breadth, or breadth-within-depth, or depth-within-breadth-within-depth, etc.

      ... snipping a bunch of other stuff ....

      You should take a look at the C3 method resolution order (see the SEE ALSO section of Class::C3 for some links). It preserves local precendence ordering of classes so that method lookup becomes much more consistent and predictable from any given point in the class hierarchy, as opposed to other (more common) method resolution orders which can change depending upon where you are looking at them from. In short, it makes MI method resolution order Just Work.

      I think your (sort of) proposal for classes to control their own dispatching is a really bad idea for all the reasons you pointed out. IMO it would make it almost impossible for a programmer to understand the path his method resolution would take.

      4. If any level of dynamism in the class hierarchy is allowed--introspection, never mind runtime modification--then the overheads are huge.

      The cost of maintaining the data required for runtime introspection of a wide and deep MI tree are daunting enough.

      ... snipping a bunch of other stuff ....

      You are making assumptions here about how the introspection mechanism is being implemented. IMO there is absolutely no need to maintain any seperate data for runtime introspection. Sure, that is how C++ and Java do it, but they were never meant to be "dynamic" languages, and any "dynamic" features they have are clobbered on (very poorly too, IMO of course).

      You also mention vtables a lot in your discussions, but vtables is not the only way to implement objects/classes. In fact it is a very poor way to do it (again IMO). If you have a cached method resolution order (MRO), especially one like C3 provides, then method lookup is not nearly as painful as Perl 5's depth-first-left-to-right mess. And since your MRO will only change if your class heirarchy changes, then the cost of cache maintaince can be managed quite easily.

      In fact the Perl6-MetaModel prototype I created did just this. The MRO would be cleared out and re-generated if and only you changed a class's superclass list, which meant that adding methods to class dynamically (a far more likely usage) would have no penalty. I also memoized the method lookup (since we have a predictable MRO and we can pretty much assume that method lookup is a side-effect free operation), which is really the only other place we needed to deal with cache issues (although I say that with some hesitation since I am sure there is something I am overlooking). This approach is IMO a far better approach that vtables.

      -stvn

        This is a placeholder for a full reply. I was just about ready to respond to this post when your other reply showed up. I want to take that on board and do some more reading. I will combine my response to both there so that this doesn't turn into a heterarchical* discussion.

        (*I just learnt that word from one of your referenced articles. I hope I used it right :)

        For now, I'd just like to say thankyou for your having taken the time to read both posts, and respond in so much detail. You given me a lot to read and a lot to think about, which is the prime motivation for posting anything more extensive than "See FAQ/Q.12345".


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Informal Poll: why aren't you using traits?
by Juerd (Abbot) on Nov 19, 2005 at 00:22 UTC

    Traits are not what a Perl 5 programmer expects, and they aren't *needed* for what I do. They might be useful sometimes, but my current thinking is that it's better to stick to what your target audience expects, than to use what's theoretically better. I do understand your position, though. I've been there. I realise that I'm quite the hypocrit, but at least I can argue from both sides.

    Sticking to what people expect is one of the most important reasons for Attribute::Property to understand the legacy new-value-in-argument convention. A similar thing can't be done correctly for traits, though, as isa just isn't does. Existing code uses isa, and so does new code unless you manage to convince a great many people!

    In Perl 6, though, or if traits get famous fast in Perl 5, I will certainly use them (though they are indeed "roles" there, not "traits"). Bootstrapping is very hard, which makes me think Class::Traits won't be common soon. The technically easy way is to get it into the Perl 5 standard module suite. Unfortunately, that's pretty tough in social context. (And, if it's a standard module, you will still have to wait at least 2 years before a reasonable amount of machines will carry it...)

    Juerd # { site => 'juerd.nl', plp_site => 'plp.juerd.nl', do_not_use => 'spamtrap' }

Re: Informal Poll: why aren't you using traits?
by dragonchild (Archbishop) on Nov 19, 2005 at 04:02 UTC
    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:

    • Can roles demand certain things? If so, can that be satisfied by another role?
    • What happens when conflicts occur?
    • 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?
    • 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?
    • Can roles have private methods? How does that work with roles composing roles?
    • 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?
    • We have class A does role B which provides foo(). Now, instance A1, at runtime, does role C which provides foo(). What now?

    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?

      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.

Re: Informal Poll: why aren't you using traits?
by Zaxo (Archbishop) on Nov 18, 2005 at 23:04 UTC

    I get traits confused with attributes and roles ;-)

    The three seem to do almost the same things, but differently. That suggests that they are not just experimental features, but instances of an experimental concept.

    As such, I doubt if I will use them in production code any time soon. I'll surely try to follow their development. Perl 5 attributes are most accessible and useful to me, but only the builtin ones look anything like stable. And not even all of them.

    After Compline,
    Zaxo

      I think there's a misunderstanding here. Traits are completely unrelated to attributes. As for Perl 6 roles, they are the same thing with the exception that in Perl 5 implementations such as Class::Trait, they're assigned at compile time and not runtime.

      As such, they are very well defined and far beyond the idea of "concept". As an experimental feature, they only remain such because people are not using them (well, I am and I've been quite happy with them. Your mileage may vary).

      So far few seem to appreciate the benefits of traits and those who claim to not see the value also appear to not know what they are. They are not attributes, decorators, or anything like that. Still, there's nothing wrong with not knowing about them. They've only been seriously discussed for a couple of years.

      Cheers,
      Ovid

      New address of my CGI Course.

        I've seen traits in C++, but does the term represent the same notion? I dimly recall a discussion where they didn't appear to be the same.

        After Compline,
        Zaxo

Re: Informal Poll: why aren't you using traits?
by BaldPenguin (Friar) on Nov 18, 2005 at 21:41 UTC
    I hope I am not alone, but my vote is the I've never heard of traits. I checked ot the link but I must say it reads like stereo instructions. Is there a 'Traits for Dummies' link that might explain it better?

    Don
    WHITEPAGES.COM | INC
    Everything I've learned in life can be summed up in a small perl script!

      No, there's no such link yet (that I'm aware of). You could read about Class Composition with Roles (near the bottom of the page) and the follow up at Perl 6 roles, but I fear those won't be much clearer. Perl 6 roles are pretty much the same thing as traits, though they allow state and runtime role assignment.

      Right now, I'm just trying to guage programmer knowledge and opinions about traits to see if there's anything to follow up with.

      Cheers,
      Ovid

      New address of my CGI Course.

      Re traits for dummies, see my response further down. There's a shorter friendlier paper written by the same guys, that's what you should be reading. (Just 15 pages) I believe this is referred to in the perl6 docu as well. This stereo instructions aspect intimidated me too at first, but the shorter intro is great and really enlightening.
Re: Informal Poll: why aren't you using traits?
by ickyb0d (Monk) on Nov 18, 2005 at 22:01 UTC

    No you're not alone, i've never heard of traits either, and after reading most of the introduction, i'm still not sure i understand them.

    Correct me if i'm wrong or point me in the right direction, but are traits just basically 'traits' of a class? From there then any other class can inherit these traits, allowing for multiple inheritance to or from any class? I can see how it's a little different than the normal methods. But specifically how does this differ that much from an 'abstract class' ? where multiple classes have all of the same methods that are inherited from one abstract class, thus that abstract class having multiple inheritance?

    Forgive me if i'm just spouting nonsense, it's been a while since i've had to deal with terms like abstract, polymorphism and inheritance all in the same sentance. Definately seems interesting though and like someone put a lot of work into that paper. When i have more time i'll definately take a more in depth look

    Update

    Read a little further... it does cover abstract classes (in C++). Looks like traits tries to solve the duplication of methods and trying to avoid 'name clashes'.

    Out of curiosity, has anyone ever used/heard the terms 'mixins' or 'glue methods' ? There seems to be a lot of terminology in this paper that i'm not familiar with

Re: Informal Poll: why aren't you using traits?
by jeffguy (Sexton) on Nov 18, 2005 at 21:58 UTC
    Never heard of them til now. The 100+ page pdf is intimidating. I'd be interested in learning, but it looks like it'll take some time. Seems like something for my "to learn someday when I have free time" list.

    If there's enough interest to warrant writing a concise article explaining them, they'd jump to near the top of my to-do list so I could learn them quickly and evaluate their merit.
Re: Informal Poll: why aren't you using traits?
by tilly (Archbishop) on Nov 19, 2005 at 07:23 UTC
    I work with simple enough class hierarchies that traits would not be worthwhile.

    That said, if you want to get others to use them, it would probably be most useful to clarify what kinds of problems traits are meant to solve, and how you can discover where they make sense in your code.

      Problems they solve/when to use them:

      • Whenever you've duplicated behavior across unrelated classes.
      • Any time you might think about MI and it's only for code reuse (in other words, the subclass is not a more specific type of a super class)
      • Any time you might want a Java-style interface but you also want an implementation to go with that.
      • Any time you might want to use mixins (have you ever considered exporting methods?)

      Cheers,
      Ovid

      New address of my CGI Course.

        As I said, I don't need them. But you may want to look at Class::Trait's documentation with an eye to making those points early. In particular I think that it is more important to be fast to explain what traits can do for you than to say what they are.
Re: Informal Poll: why aren't you using traits?
by BUU (Prior) on Nov 18, 2005 at 23:19 UTC
    I'd like to think I understand traits and I've definitely heard of them before, but I don't understand what problems they solve that inheritance doesn't, at least in perl. I suspect this is probably answered some place, but nothing I've seen has made me enthusiastic enough to go track it down and learn it.
      I'd like to think I understand traits and I've definitely heard of them before, but I don't understand what problems they solve that inheritance doesn't, at least in perl.

      Well, to start with, they are not inherited, which eliminates a whole class of possible issues, and makes refactoring much easier. There are a number of good examples in the traits paper Ovid linked too, and I would also recomend this paper Applying Traits to the Smalltalk Collection Hierarchy which demonstates how Traits are useful in refactoring a large class hierarchy.

      Inheritence is a great tool, but one that is consistently overused and for many problems, it is not even the right solution. A common (mis)use of inheritence is to create a base class with many utilitiy methods, and then have other classes inherit from it so they can easily share those methods. This is not a good use of inheritence, in fact it is debatable if this is even really OO at all. However, this is something which Traits are perfect for. Why you ask? Well, traits essentially "export" their methods into the consuming class, which is really what this (mis)use of inheritence is trying to do. Doing it with traits would avoid this (mis)use of inheritence and provide much greater control over what utility methods each class needs/uses. It is also worth mentioning that Trait's "rules" about method composition would possible catch issues which would inheritence would not such as conflicting method names, and it would do so at compile time rather than runtime.

      -stvn
Re: Informal Poll: why aren't you using traits?
by wazoox (Prior) on Nov 18, 2005 at 21:27 UTC
    C'mon, I'm struggling to grab the OO paradigm, so I'll let the clever new tricks to others for a while :)
Re: Informal Poll: why aren't you using traits?
by diotalevi (Canon) on Nov 18, 2005 at 22:06 UTC
    Is the idea of traits like saying class Foo "can do" Bar? I'd like to see real world examples that aren't about doing strange things in testing environments. Those aren't normal environments and I don't think they make good examples.

      The way I understand Traits is that they are really just mixins with lots of extra protections against method name collisions. And a mixin is really just a method that is imported into your class from another module or package.

      I do a lot of work with CGI::Application, and we have an extremely basic plugin system that just works like a mixin. Your plugin exports some useful methods to the application class. I have never been quite happy with it, and I believe traits might be a better answer to this problem (I need to investigate that more thoroughly though).

      To give you an example, we have a Session plugin that exports a 'session' method which when called just returns you an active session object. So CGI::Application doesn't know anything about sessions, but when you load the Session plugin (or trait in this case), you can now call $self->session and you get yourself a session object or a tied session hash (whichever you might prefer). So what Traits can provide is the mechanism for getting that 'session' method added to your class (that is my limited understanding of it anyway).

      This might not be a problem that traits were written to solve, but I think it may fit in nicely with what we are doing. The other option is to use Multiple Inheritance (which is what Catalyst uses), but I have never like MI, especially once you get to adding 5 or 6 entries into your @ISA. Not that mixins are better than MI, they both have their problems. I can just accept the problems with mixins easier than I can the problems that MI has.

      And perhaps Traits can solve most of the problems I currently have with mixins!

        The other option is to use Multiple Inheritance (which is what Catalyst uses).

        It is important to note thet Catalyst uses MI, but it also uses NEXT. Using NEXT allows a greater control over MI and how and when methods are called.

        But to be honest, MI doesn't have to be so scary/ugly/problematic anymore. DBIx::Class (which is associated with Catalyst) is actually in the process of transitioning from MI with NEXT to using Class::C3. Class::C3 is a module I wrote recently which imposes a sane ordering for method dispatch under multiple inheritence. It comes originally from the language Dylan, and has some roots in early LISP object systems (pre-CLOS), and has most recently been adopted by Python. There is more information on C3 in the SEE ALSO section of the Class::C3 POD docs.

        -stvn
Re: Informal Poll: why aren't you using traits?
by halley (Prior) on Nov 18, 2005 at 22:09 UTC
    (*) already built up a new object model implementing
        a stronger decorator concept than perl's traits

    --
    [ e d @ h a l l e y . c c ]

      Care to elaborate? It sounds interesting.

      I am not sure that I would classify Traits as being "decorators" either since "decorators" usually imply some kind of delegation to other instances. Trait's are not classes at all, and cannot be instantiated. Traits actually are "flattened" into the class, so that the methods of the trait become methods of the class. The difference may seem subtle, but it greatly affects how elements of the object model can interact.

      -stvn
        My object model for simulations uses decorators but treats them as if they were melted into the base instance, so syntactically they are more like traits. Also, any particular trait/decorator type manages its own index of all living instances with that trait, for some interesting searches. But they're traits which can be attached and detached at will. I call them 'qualities' but that's just my jargon.

        Writing a simulation library with this linguistic feature has a completely different feel to it. The job is more about writing many orthogonal qualities, and using classes just as handy pre-packaged combinations of qualities. If classes are nouns, then qualities are like adjectives. I call it quality-oriented programming.

        For example, let's take a "MUD" style simulation (though I've used this for other types of sims):

        quality Living; // has a life force quality Anatomical; // has a collection of body parts quality Breathing; // has limited range outside atmosphere quality Mortal; // can die quality Injurable; // can be wounded quality Motivated; // has goals // ... and so on class Item; class Thing is a Massive Palpable Item; class Lifeform is a Living Anatomical Thing; class Animal is a Breathing Mortal Injurable Motivated Emotional Gendered Lifeform; class Mammal is a Visible Viewing Eating Drinking Listening Smelling Smelly Feeling Animal; class Primate is a Wearing Manipulating Gestural Facial Wielding Mammal; class Human is a Sentient Carrying Talking Skilled Primate;

        Note here that the qualities carry ALL of the implementation and the class definitions are completely nil. These nil classes just indicate the list of qualities to be attached upon instantiation. Also, there's no problem with removing Vocal from a particularly pesky individual Human for a while, even if she were instantiated with that quality.

        I've implemented this mechanism in C++, Java and pure Perl; the pure-perl implementation has the highest overhead of course, but I find it the nicest overall language for developing custom object models.

        --
        [ e d @ h a l l e y . c c ]

        Not to mention the fact that it can be a nice performance boost and you can query the class to find out what traits/roles it implements.

        Cheers,
        Ovid

        New address of my CGI Course.

Re: Informal Poll: why aren't you using traits?
by spiritway (Vicar) on Nov 19, 2005 at 06:01 UTC

    I have to agree with many of the other posters here - don't know what they are. I *have* heard about them, once, here - but did not find any explanation of them

    Right now I have my hands full learning plain old Perl. Traits may be something I'll want to try once I have a clue about Perl itself.

Re: Informal Poll: why aren't you using traits?
by QM (Parson) on Nov 20, 2005 at 01:39 UTC
    I'm still trying to cotton the difference between traits, roles, attributes, types, prototypes, and signatures.

    OK, that's a little facetious, as I know what a prototype is.

    The rest I have to go look up. It's annoying to wonder, while I'm reading an article or post, whether the definition of that term is used correctly. So I have to read 4 or 5 entries to determine what the general meaning of one of these terms is, and then if it's useful for what I'm trying to do.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Re: Informal Poll: why aren't you using traits? (Traits for Dummies)
by tphyahoo (Vicar) on Nov 21, 2005 at 08:02 UTC
    I've seen some questions above about where there is a "traits for dummies" guide and frustration about the 100-page formal introduction to traits.

    I think there may be some confusion here, so in the interest of sanity here is Traits: The Formal Model which is the closest thing to "traits for dummies" that I have been able to find. Just 15 pages, and a damn good read.

    I believe that the "100 pager" is a companion document written by the same guys, buttressing the arguments they make in the shorter intro. So if you're looking for traits for dummies, I would say start there. My impression is that the perl6 apocalypse stuff about traits assumes you have already been introduced to the material here. (If this has already been posted, sorry.)

    As to the poll, I haven't used traits because I am too busy putting out other fires in my job, life and goals, but I think they are cool and would like to someday. And learning about them was productive because it led me to a better understanding of what could commonly go wrong in more vanilla type object inheritance models.

Re: Informal Poll: why aren't you using traits?
by japhy (Canon) on Nov 21, 2005 at 13:03 UTC
    I guess my answer is: "why should I start using traits all of the sudden?" I've been doing just fine with the "old" object-oriented way.

    Jeff japhy Pinyan, P.L., P.M., P.O.D, X.S.: Perl, regex, and perl hacker
    How can we ever be the sold short or the cheated, we who for every service have long ago been overpaid? ~~ Meister Eckhart

      Why should I use structured programming all of a sudden? I've been doing just fine with goto :)

      Your response encapsulates most people's view of traits. Though they're very easy to use and do a great job of managing complexity, there really needs to be a 'traits paper' written for Perl before the Perl community really groks them. There's a fantastic one showing how well traits performed in refactoring the Smalltalk base classes, but since most don't know Smalltalk, they don't pay attention to the paper.

      Cheers,
      Ovid

      New address of my CGI Course.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://509958]
Approved by itub
Front-paged by kutsu
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-12-07 23:53 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Which IDE have you been most impressed by?













    Results (50 votes). Check out past polls.