Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reducing Repositories to Aggregate Roots

I currently have a repository for just about every table in the database and would like to further align myself with DDD by reducing them to aggregate roots only.

Let’s assume that I have the following tables, User and Phone. Each user might have one or more phones. Without the notion of aggregate root I might do something like this:

//assuming I have the userId in session for example and I want to update a phone number List<Phone> phones = PhoneRepository.GetPhoneNumberByUserId(userId); phones[0].Number = “911”; PhoneRepository.Update(phones[0]); 

The concept of aggregate roots is easier to understand on paper than in practice. I will never have phone numbers that do not belong to a User, so would it make sense to do away with the PhoneRepository and incorporate phone related methods into the UserRepository? Assuming the answer is yes, I’m going to rewrite the prior code sample.

Am I allowed to have a method on the UserRepository that returns phone numbers? Or should it always return a reference to a User, and then traverse the relationship through the User to get to the phone numbers:

List<Phone> phones = UserRepository.GetPhoneNumbers(userId); // Or User user = UserRepository.GetUserWithPhoneNumbers(userId); //this method will join to Phone 

Regardless of which way I acquire the phones, assuming I modified one of them, how do I go about updating them? My limited understanding is that objects under the root should be updated through the root, which would steer me towards choice #1 below. Although this will work perfectly well with Entity Framework, this seems extremely un-descriptive, because reading the code I have no idea what I’m actually updating, even though Entity Framework is keeping tab on changed objects within the graph.

UserRepository.Update(user); // Or UserRepository.UpdatePhone(phone); 

Lastly, assuming I have several lookup tables that are not really tied to anything, such as CountryCodes, ColorsCodes, SomethingElseCodes. I might use them to populate drop downs or for whatever other reason. Are these standalone repositories? Can they be combined into some sort of logical grouping/repository such as CodesRepository? Or is that against best practices.

like image 664
e36M3 Avatar asked Mar 01 '11 17:03

e36M3


People also ask

What is an aggregated root?

Aggregate Root is the mothership entity inside the aggregate (in our case Computer ), it is a common practice to have your repository only work with the entities that are Aggregate Roots, and this entity is responsible for initializing the other entities. Consider Aggregate Root as an Entry-Point to an Aggregate.

Can aggregates use repository?

Because aggregates are the consistency boundaries exposed to the application layer. Which is to say that, yes, the repositories are responsible for taking the snapshot of state from the data store, and building from it the graph of entities and values that make up the aggregate.

Can an aggregate root reference another aggregate root?

What you cannot do is reference anything inside the other aggregate root.

What problem does repository pattern solve?

They decouple application and domain design from persistence technology, multiple database strategies, or even multiple data sources.


1 Answers

You are allowed to have any method you want in your repository :) In both of the cases you mention, it makes sense to return the user with phone list populated. Normally user object would not be fully populated with all the sub information (say all addresses, phone numbers) and we may have different methods for getting the user object populated with different kind of information. This is referred to as lazy loading.

User GetUserDetailsWithPhones() {     // Populate User along with Phones } 

For updating, in this case, the user is being updated, not the phone number itself. Storage model may store the phones in different table and that way you may think that just the phones are being updated but that is not the case if you think from DDD perspective. As far as readability is concerned, while the line

UserRepository.Update(user) 

alone doesn't convey what is being updated, the code above it would make it clear what is being updated. Also it would most likely be part of a front end method call that may signifiy what is being updated.

For the lookup tables, and actually even otherwise, it is useful to have GenericRepository and use that. The custom repository can inherit from the GenericRepository.

public class UserRepository : GenericRepository<User> {     IEnumerable<User> GetUserByCustomCriteria()     {     }      User GetUserDetailsWithPhones()     {         // Populate User along with Phones     }      User GetUserDetailsWithAllSubInfo()     {         // Populate User along with all sub information e.g. phones, addresses etc.     } } 

Search for Generic Repository Entity Framework and you would fine many nice implementation. Use one of those or write your own.

like image 161
amit_g Avatar answered Oct 09 '22 02:10

amit_g