Search code examples
dependency-injectiondomain-driven-designrepositoryrepository-patternddd-repositories

DDD: is it ok to inject a Repository into an Entity?


Possible Duplicate:
Why not use an IoC container to resolve dependencies for entities/business objects?

I asked a very similar question in the past. However, I believe this is not a self-duplicate: the (good) answer to my original question was very specific to this domain problem, and does not discuss the problem in general.

Let's take a new example I came accross:

  • I have a Zone entity, with an associated boundary;
  • I have a Store entity, which has a location as well as a zone property;
  • A ZoneRepository can find which Zone contains a specific location.

The zone property of the Store should never be set directly, but instead deducted from the location when this property is assigned. Therefore, it sounds logical to me to do this:

class Store
{
    public void setLocation(Point location, ZoneRepository repo)
    {
        this.location = location;
        this.zone = repo.findByLocation(location);
    }
}

Are there drawbacks, caveats to this approach? If so, can you suggest realistic alternatives?


Solution

  • What is the relationship between Zone and Location? Zone must have a Location property, correct? Or otherwise you wouldn't be able to search zone by location. Could this be a bi-directional relationship? What I'm getting at, is why can't you do this?

    class Store
    {
        public function setLocation(Point $location)
        {
            $this->location = $location;
            $this->zone = $location->zone;
        }
    }
    

    alternatively, you cold use the repository in the layer above, and then just pass in what you need:

    class Store
    {
        public function setLocation(Point $location, Zone $zone)
        {
            $this->location = $location;
            $this->zone = $zone;
        }
    }
    

    Generally, I would not inject the repository in unless absolutely necessary, and in this situation it is not. Even then, I would not pass it into the method, I would pass it in using an IOC container.