In light of Traits available to us for Drupal 8. Yay! OK, so where do we want to use them?being approved by Dries, we will have
Remember, traits are *not* an alternative for proper object composition. Their main use is for reducing boilerplate code and providing utility code without relying on inheritance. Crell would describe them as "a cleaner alternative to utility base classes".
It general, traits, like interfaces, should be small and focused. It is *really really easy* to include multiple traits in a single class, and ends up being nicely self-documenting.
Note that traits may not implement an interface; however, a class may implement an interface by using a trait that happens to do so. For example: http://3v4l.org/07EQM
- All abstract base classes SHOULD be considered as possible candidates to replace with one or more traits, particularly if they are used primarily for code sharing and not "is a special case of" relationships. (Reason: abstract classes often exist only to provide incomplete partial implementations, which traits do as well but without "stealing" the "is a special case of" relationship.)
- Traits SHOULD be single-purpose. That is, ControllerBase should not be unilaterally replaced with ControllerTrait, but the various bits and pieces of ControllerBase MAY be replaced with multiple targeted traits.
- Traits used for common application-level dependency injection (like translation) MUST include an override method for easier testing.
- Traits used for common application-level dependency injection (like translation) SHOULD use private variables. (This helps enforce the previous point.)
- An Interface that implies two or more "this method will be identical for 99% of all implementers" methods SHOULD provide a trait that does so, and SHOULD NOT provide an abstract base class.
- Infrastructure-level and domain-level classes (ie, things that we do want to unit test in the majority case) MUST NOT use traits as an alternative to proper dependency injection. ONLY application-level code (controllers, forms, etc.) should do that. (They may still use other traits as appropriate, but not as an alternative to dependency injection.)
- Services surfaced in \Drupal are good candidates to consider offering a trait for, but that does not imply that there should be a 1:1 correlation between the two.
Possible candidates for conversion
- Probably can get split up to lots of small traits; MAY be removed entirely
- The same utilities that are on ControllerBase can be removed in favor of traits. Default form implementations MAY be replaced with a trait, TBD.
- The same utilities that are on ControllerBase can be removed in favor of traits. We should investigate if other aspects can be replaced with traits, too. TBD.
Proposed application-level traits
- $this->t(). See .
- $this->config() (returns a config object, not the factory)
- The bridge code to make an otherwise unserializable object serializable through the DIC. See .
- $this->currentUser() (should this be called account, since that's the actual object that's returned?)
- $this->generator() (should this return the generator service, or be multiple methods for the various generator methods?)
- Agree on standards/policies/guidelines for using Traits.
- Make a Coding Standards page under https://drupal.org/coding-standards describing these guidelines, or add it to the existing page on classes/interfaces (https://drupal.org/node/608152)
- Agree on which classes to convert to using Traits.
- File separate issues to convert those classes to using Traits.
- Make sure that api.drupal.org can deal with Traits -- which will involve updates to the Grammar Parser and API module projects.
User interface changes
Some abstract and/or base classes will be converted to using the PHP 5.4 "Traits".