On 2009-Jul-8, at 1:49 pm, Ovid wrote:
That being said, roles also have two competing uses (though they don't conflict as badly). As units of behavior, they provide the functionality your code needs. However, they can also serve as an interface.


Maybe there are Interfaces, which are, well, just interfaces, and there are Roles, which are Interfaces plus a partial or full implementation. Like roles and classes, roles and interfaces could be transparently interchanged when suitable. Add some bodies to an Interface and you've got a Role; cast a Role to an Interface and you strip out everything but the declarations.


Behavioral: if you are primarily relying on roles to provide behavior (as we do at the BBC), then silently discarding the role's behavior by providing a method of the same name in your class can lead to very confusing bugs. I've lost a lot of time debugging this behavior.


    role Stuff
    {
        suggest method foo { ... }
        method bar { ... }
    }

    class Thing does Stuff
    {
        method foo { ... }
        supersede method bar { ... }
    }


Since foo() is only suggested by this role, you can easily override it; whereas bar() needs to be explicitly superseded. (Or maybe it should be "method foo :suggested"....)

The idea being that certain methods are expected to work by accepting what's provided in the role most of the time, so you should rarely have to supersede them; or they're merely suggestions, and therefore you are expected to role^H^H roll your own most of the time. (And if you find yourself getting annoyed that you have to type "supersede" so much, that's probably a good clue that something went wrong somewhere in the design.)

Either that, or just have suitable warnings that can be toggled on or off depending on what sort of policies you need. That was actually my first thought, and I think we should have adjustable warnings for everything anyway, but the more I look at the above example, the more it's growing on me.


-David

Reply via email to