Designing Repositories – Now I don’t feel so bad

Last week I was working with a client and we were creating some repositories to use with EF4 entities in her application. I felt kinda dumb because I couldn’t reason out where to put a method to retrieve “child” data, e.g., GetEmployeesForCompany(Company company). The method not only retrieves the employees but attaches them to the company, returning a graph.

My conundrum was should the method call go in to a repository who’s root was Company or the one with the root, Employee?

So I tweeted it but thanks to the 140 char limit, simplified the method to GetEmployeesForCompany(int companyId).

I got a lot of responses very quickly and they went back and forth which only confused me more.

Not until I put them all in this table (below) did I see that generally people were leaning towards returning it from employee.

But the best response was: “The answer is that it depends upon what you’re building – and how it would make most sense to aggregate 😉 i.e. aggregates only make sense in CONTEXT.” Thanks Mikey! 🙂

In the end, I think that I won’t fail by choosing one over the other. The important thing, which for me is also a great benefit of creating repositories, is the fact that I have put some thought into where the method goes and am making an explicit choice that works for me. And that is the lesson I can leave my client with, along with another which I repeated a few times – “I’m not the expert on this topic. We’re just taking baby steps (in the right direction) here.”

Company Employee

only make sense on the Company class, so I’d say Company.

Employee Repo!
I’d say Company Employee rep. Company is just a lookup parameter.
gsin u have emp and comp both as aggr. still, comp might restrict which emp it returns…so i’d put in comp Employee Repo!

I’d go with the company as the aggregate in this case.

I’d go with Employees and calling it GetByCompany(string companyId)
EmloyeeRepo.GetAllForCompany(123
 

I generally go with the convention that a rep only returns the type it is associated with but takes any type as a parameter

  so if reps other than employees returned employees, it would be hard to predict where all the places are that return employees
  your getting a collection of employees and not dealing with a Company object at all, I would put it in employee rep
  employee repository… it’s returning employees
  I’d say employee. You want a collection of employees, not a collection of companies. Think of it as a slippery slope.
 

Since you are getting employee’s, I would put it in the EmployeeRepository.

  Sign up for my newsletter so you don't miss my conference & Pluralsight course announcements!  

4 thoughts on “Designing Repositories – Now I don’t feel so bad

  1. Your post made me chuckle as I’ve been in that situation more than a few times (and in some ways still am ;)), i.e. learning the concepts of DDD and figuring out how to do things "the right way" as I go along. I have to agree that in that context, that method makes more sense with the Employee repo since employees are being returned. Thanks for sharing.

  2. Glad to see you figured this out. And it looks like you’ve nailed it.

    Work out some rules for what makes the most sense (based on your objects, models, and interactions) – and then stick with them (as you’ve done here).

  3. My take: If Employee is already an aggregate root, then put this particular method in EmployeeRepository.

    But going beyond that, my repositories almost always allow people to specify an optional boolean for inclusion of relationships. E.g.:

    CompanyRepository.GetCompany(int companyId, boolean includeEmployees = false)

  4. The deciding factor is as easy as looking at the return type of the call to the data. If your returning an Employee then it should live in the employee domain object in the business layer or in the employee repository if its the initial call which would make an even easier decision.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.