Tips For Converting Base Classes Into Roles

Ovid on 2009-04-27T13:35:27

This is a short list of guidelines I've found useful when converting base classes into roles.

  1. Look for all methods called on the invocant and add them to 'requires'. This won't solve the false cognate problem, but that exists even without roles. It will, however, give you composition-time safety for missing methods (no more 2:00 AM panic phone calls because you've called a missing method!)
  2. Look for everything directly requiring inheritance such as SUPER, NEXT, next::method, etc., and act accordingly. "before", "after" and "around" help here.
  3. Avoid composing roles out of other roles. List them explicitly in the class using them. An exception can be made for an "interface" role such as Does::Serializable providing the interface for Does::Serializable::YAML, Does::Serializable::JSON, etc. This allows you to open up any class see instantly what its capabilities are. The downside is a small amount of duplicated code. I don't see any easy way around this. Still thinking about it.
  4. Always use a single "with" statement. Multiple "with" statements will not provide composition safety.
  5. Be careful if you apply roles at runtime. We had a nasty, hard-to-debug case where we kept applying the same role to a singleton and caused a recursion warning after it layered on too many anonymous classes.
  6. Avoid inheritance except in the case where you cannot abstract a class into a role (DBIx::Class::ResultSource being an example).
  7. When naming a role, look for methods which don't appear related to the name. Either your name is wrong or you have methods which don't belong in that role.

That last tip has led us to see tons of garbage which slipped into base classes because that was the only place we could easily see to wedge in this behavior.


great tips

markjugg on 2009-04-27T14:34:18

Great tips! Thanks. I'm getting sold on roles-centric programming.

It would be great to have a index page somewhere of all your posts about roles.

Re:great tips

Ovid on 2009-04-27T14:48:41

If use.perl had tags, I would be adding a "roles" tag and merely clicking on that would give you what you want.

Re:great tips

chromatic on 2009-04-27T19:37:28

I created a page on the Perl 5 wiki called Roles Best Practices. Now anyone else interested can contribute.