As long as the validation function does not need an external resource I would reuse the dependency directly and avoid it's injection.
A domain object encapsulates domain rules and should contain all necessary information to ensure these rules. It is designed more around high cohesion than low coupling (the concept of aggregates itself serves as a means for reducing interdependencies).
The Email
class in your example should be the single point of failure for email address validation. If all domain objects validate emails via that class, then reusing existing framework (or even third party) functionality is an implementation detail and becomes less of a problem regarding loose coupling. If the validation rules change you would have to reimplement the function anyway - using Zend_Validate_Email
or some custom code.
Injecting the validation logic into entities or value objects would bring a lot of problems with it:
- logic that belongs in the domain object would be moved to another class
- injecting services into entities is generally not advised
- introducing an interface only for the
EmailValidator
class violates the Reused Abstractions Principle - calling a static
isValid
method onEMail
would be impossible
Only in the rare case where the validation logic needs an external resource I would tend to use a factory with an injected service that validates on creation of the domain object -- but only after rethinking the design of the domain model.