views:

281

answers:

1

I've just started working with DDD, so maybe this is a silly question...

Is it ok for an entity to access a repository (via some IRepository interface) to get a value at runtime? For example, I want to enforce a "default" selection for a property:

class Person {
    private Company _employer;

    public Company Employer {
        get { return _employer; }
        set { 
            if(value != null) {
                _employer = value;
            } else {
                _employer = employerRepository.GetDefaultEmployer();
            }
        }
    }

    ...
}

My question is whehter doing something like this is a horrible violation of DDD principles. And if it isn't, my next question would be what it the best way to provide the repository to use? Should it be supplied when the Person object is created?

Thanks, P

+5  A: 

it's not a horrible violation of DDD it's a horrible violation of... well... it's just plain horrible (i say this tongue in cheek) :).

First off, your entity becomes dependent on having a repository... that's not ideal. Ideally you'd want to have your repository create the Person and then assign it everything it needs to be effective in the current domain context.

So when you need a Person, you'll go personRepository.GetPersonWithDefaultEmployer() and get back a person which has default employer populated. The personRepository will have a dependency on an employerRepository and use that to populate the person before returning it.

PersonReposotory : IPersonRepository
{
    private readonly IEmployerRepository employerRepository;

    //use constructor injection to populate the EmployerRepository
    public PersonRepository(IEmployerRepository employerRepository)
    {
        this.employerRepository = employerRepository;
    }

    public person GetPersonWithDefaultEmployer(int personId)
    {
        Person person = GetPerson(personId);
        person.Employer = employerRepository.GetDefaultEmployer(personId);
        return person;
    }
}
lomaxx
I'm glad to know that having the entity know about the repository was a bad code smell!That said, I like your solution above for creating new Person objects (and in fact already do something like that), but how I handle the situation where the Employer is being changed after the Person has been created? One solution would be to move the logic out to a separate domain service class that has the logic for selecting the default Employer. But that service would still need access to the Employer repository - perhaps that's preferable?
why can't you just save the person using the personRepository and put the encapsulating logic in there?
lomaxx
I'm not sure if I follow you - this is not an issue of saving, but rather, updating the in-memory Person object. The rule of not allowing the Employer to be null seems like it would be a business rule that shouldn't be in the repository. My app is not a web app, but rather one with a full object graph in memory at all times. I'm not constantly loading objects from the database, only when the app starts.
regardless, you don't want a dependency on the EmployerRepository in your Person entity. When the person is created it is the job of the repository or a seperate service that calls the repository and returns the person to make sure the person object is in a valid state. When you need a person, call the person service which will call the person repository and the employer repository and construct a valid person object for you to use. It's even more important you do this with your full object graph as you will want your service to keep track of your person instances
lomaxx