Avoid Dependency Injection

At least, avoid it when building DDD Aggregates:

Dependency injection of a Repository or a Domain Service into an Aggregate should generally be viewed as harmful. The motivation may be to look up a dependent object instance from inside the Aggregate. The dependent object could be another Aggregate, or a number of them. … Preferably, dependent objects are looked up before an Aggregate command method is invoked, and passed into it.

… Take great care not to add unnecessary overhead that could be easily avoided by using other design principles, such as looking up dependencies before an Aggregate command method is invoked, and passing them into it.

This is only meant to warn against injecting Repositories and Domain Services into Aggregate instances. Of course, dependency injection is still quite suitable for many other design situations. For example, it could be quite useful to inject Repository and Domain Service references into Application Services.

— “Implementing Domain Driven Design”, Vaughn Vernon, p 387.

On a related note, regarding where Entity validation logic goes, we have this …

Validation is a separate concern and should be the responsibility of a validation class, not a domain object.

— ibid., p 208

… and this …

Embedding validation logic inside an Entity give it too many responsibilities. It already has the responsibility to address domain behavior as it maintains its state.

— ibid., p 212

… but then we see this:

How do clients ensure that Entity validation occurs? And where does validation processing begin? One way places a validate() method on all Entities that require validation. … Any Entity can safely have its validate() method invoked. …

However, should Entities actually validate themselves? Having its own validate() method doesn’t mean the Entity itself performs validation. Yet, it does allow the Entity to determine what validates it, relieving clients from that concern:

public class Warble extends Entity {
    public void Validate(ValidationNotificationHandler aHandler) {
        (new WarbleValidator(this, aHandler)).validate();

… The Entity needs to know nothing about how it is validated, only that it can be validated. The separate Validator subclass also allows the validation process to change at a diferent pace from the Entity and enables complex validations to be thoroughly tested.

— ibid., p 214-215

It seems like a small step after that to inject a fully-constructed validation object into the Entity at construction time, and have the validate() method call that, instead of creating a new validation object inside the Entity.

Are you stuck with a legacy PHP application? You should buy my book because it gives you a step-by-step guide to improving your codebase, all while keeping it running the whole time.

5 thoughts on “Avoid Dependency Injection

  1. That’s one of the biggest questions I found when I started with DDD.

    Many developers validate entity data in the entity class itself, which supposes a violation of the Single Responsibility Principle. In the other hand, creating the validator class inside the entity violates the Dependency Inversion Principle.

    After a long time thinking in how could I preserve the SRP without creating any class inside the entity, I found an approximation: a class that validates the data and stores it. That class would become the new entity constructor argument.

    There’s a lot of issues that this workaround causes, but all of them can be solved easily with the Factory Pattern.

  2. I think that fully-constructed validation object should be injected via double dispatching exactly in the entity’s validate() method. We may need different ways of validation in different use cases and(or) at different moments of entity’s life-cycle.

    • /me nods

      On the other hand, if you need different validations in different use cases, perhaps that indicates that there should be an additional Bounded Context; or indeed, a different Entity for that use case?

      • Not always. It may be simple UI/UX requiring like multi-steps registration form. Today they want 3 steps, tomorrow – 5 steps. It is not domain logic, but different validation rules.

        • > It may be simple UI/UX requiring like multi-steps registration form. Today they want 3 steps, tomorrow – 5 steps.

          Maybe; though at that point, you’re talking about something more like an Application Controller (POEAA) rather than Entity validation — in which case, the validation might better be invoked as part of a Application Service or Domain Service, rather than embedded in the Entity.

Leave a Reply

Your email address will not be published. Required fields are marked *