Validating aggregate collections: when and whose job is it?

<[email protected]>
Newsgroups gmane.comp.programming.domain-driven-design
Message-ID <[email protected]>
Hi all,
 

 I would like to have your input on a relatively simple problem that has me looking everywere for guidelines.  Here it goes.
 

 Let's consider a relatively simple subset of the application on which I'm working.  Aside from other considerations, this application allows users to:
 - manage the inner structure of their company: head office, departments, employees, etc.
 - manage the relationships their company has with external customers
 

 If we focus on the relationship management part, we learn that a customer can be:
 - registered: referring to a company already registered in the application, or
 - virtual: not referring to any registered company (and basically a placeholder until the company actually registers)
 

 There are two main rules that must be respected:
 1. for a given company, no virtual company can be created with a given website if that website is already owned by an existing company (basically, don't create virtual customers when registered customers exist), and
 2. for a given company, no two customers, virtual or registered, must own the same website
 

 To clarify, considering two registered companies, company1 (website company1.com) and company2 (company2.com):
 1. company1 cannot add a virtual customer with website company2.com, instead it must add company2 as a registered customer
 2. company1 cannot add twice the virtual customer company3 with website company3.com
 

 Although we could get into a discussion of which contexts exist, for the moment let's consider a single "company management" context with two aggregates: 
 - Company { companyId, name, website }
 - Customer { customerId, ownerCompanyId, name, website, registeredCompanyId }
 

 There are two basic questions: when are the two above business rules validated and by whom? I see two options:
 

 1. The rules can be verified when instantiating the Customer aggregate or when saving it to the data store. Validating at instantiation time benefits us since we know that there can never be an invalid Customer in memory. Instantiation would be performed by the Company aggregate. That would require Company or its Company.createCustomer methods to have access reference to both a CompanyRepository and a CustomerRepository to lookup any Company or Customer by website. Introducing a dependency between Company and these repositories doesn't produce a clean and intuitive API, plus doesn't feel like a very healthy dependency.
 2. The rules can be verified when saving to the data store. This would be performed by the CustomerRepository implementation. This approach removes the Company - repository dependencies, and having an invalid Customer in memory isn't really an issue.  But is validation logic really part of a Repository's responsibilities? Also, this would require the CustomerRepository.add and CustomerRepository.update methods to have a reference to a CompanyRepository to lookup any Company website. Introducing a dependency between two repositories doesn't feel right: my understanding is that a repository should only manage instances of a given aggregate regardless of its environment, but maybe this is too short-sighted.
 

 What do you think? How do you usually model these kinds of business rules?
 

 Thanks a bunch!
 GB
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.