Aggregate root are cluster / group of objects that are treated as a single unit of data.
I am sure lots of developers are already using this pattern unknowingly, via this short note I would like to inform you formally what you are doing.
Let us try to understand the above definition with an example. Consider the below “Customer
” class which has the capability to add multiple “Address
” objects to it. In order to achieve the same, we have exposed an address
collection from the customer
class to represent the 1 to many relationships.
class Customer
{
public string CustomerName { get; set; }
public DateTime DateofBirth { get; set; }
public List
Addresses { get; set; } } class Address { public string Address1 { get; set; } public string Type { get; set; } }
The above class structure works perfectly well. You can create object of customer
and add multiple addresses
object to it.
Customer cust = new Customer();
cust.CustomerName = "Shiv koirala";
cust.DateofBirth = Convert.ToDateTime("12/03/1977");
Address Address1 = new Address();
Address1.Address1 = "India";
Address1.Type = "Home";
cust.Addresses.Add(Address1);
Address Address2 = new Address();
Address2.Address1 = "Nepal";
Address2.Type = "Home";
cust.Addresses.Add(Address2);
Now let's say we want to implement the following validations:
“Customer can only have one address of Home type”.
At this moment, the address collection is a NAKED LIST COLLECTION which is exposed directly to the client. In other words, there are no validations and restrictions on the “Add
” method of the list. So you can add whatever and how much ever address
objects as you wish.
cust.Addresses.Add(Address2);
So how to address this problem in a clean and logical way. If you think logically, “Customer
” is composed of Addressescollection
, so Customer
is like a main root. So rather than allowing DIRECT NAKED ACCESS to Addresses
list, how about accessing the address list from the customer
class. In other words, centralizing access to address
objects from the customer
class.
So below are three steps which I have implemented to put a centralize address
validation.
Step 1: I have made the address
list private
. So no direct access to the collection is possible.
Step 2: Created a “Add
” method in the “Customer
” class for adding the “Address
” object. In this add
method, we have put the validation that only one “Home
” type address can be added.
Step 3: Clients who want to enumerate through the address
collection for them we have exposed “IEnumerable
” interface.
class Customer
{
private List
_Addresses; // Step 1 :- Make list private public void Add(Address obj) // Step 2 :- Address objects added via customer { int Count=0; foreach (Address t in _Addresses) { if (t.Type == "Home") { Count++; if (Count > 1) { throw new Exception("Only one home address is allowed"); } } } _Addresses.Add(obj); } public IEnumerable
Addresses // Step 3 :- To browse use enumerator { get { return _Addresses; } } }
If you analyze the above solution closely, the customer
is now the root and the address
object is manipulated and retrieved via the customer
class.
Why did we do this? Because “Customer
” and “Address
” object is one logical data unit. To maintain integrity of address
validation, we need to go via the “Customer
” class. In the same way loading of data, updation, deletion, etc. should all happen via the “Customer
” class so that we have proper data integrity maintained.
So when we say load customer
from database, all the respective address
objects should also get loaded.
So when a group of objects which form one logical unit should have centralized root via which the manipulation of the contained object should happen. This kind of arrangement is terms as “Aggregate Root”.
For Further reading do watch the below interview preparation videos and step by step video series.