Sunday, November 1, 2015

Value Object design pattern in C#

Introduction of Value object design pattern

Definition: - “Value object is an object whose equality is based on the value rather than identity. “

Let us understand the above statement with more clarity. When you create two objects and even if their values are same they represent different entities. For example in the below code we have created two person objects with the same name “Shiv”.

Person PersonfromIndia = new Person();
 PersonfromIndia.Name = "Shiv";
 PersonfromIndia.Age = 20;
 
 Person PersonfromNepal = new Person();
 PersonfromNepal.Name = "Shiv";
 PersonfromNepal.Age = 20;
 
But the first person stays in “India” and the other stays in “Nepal”. So in other words “PersonFromIndia” object is different from “PersonFromNepal” object even if the person’s name and age is same. In other words they have DIFFERENT IDENTITIES.

If you try to compare the above C# object it will return false and this is completely in line with our expectations. You can use the “Equal” method or you can use “==”.



if (PersonfromIndia.Equals(PersonfromNepal))
 {
                
 }
 
But now consider the below scenario of a money example. We are creating two money objects of 1 rupee value but one is using a paper material and the other is made of steel material.



But in this case “OneRupeeCoin” value is equal to “OneRupeeNote” value. So even if the objects are of different instances they are equal by money value. So if the money and currency type matches both the objects are equal.

Money OneRupeeCoin = new Money();
 OneRupeeCoin.Value = 1;
 OneRupeeCoin.CurrencyType = "INR";
 OneRupeeCoin.CurrencyType = "INR";
 OneRupeeCoin.SerialNo = "A3123JJK332";
 
 Money OneRupeeNote = new Money();
 OneRupeeNote.Value = 1;
 OneRupeeCoin.CurrencyType = "INR";
 OneRupeeCoin.CurrencyType = "INR";
 OneRupeeNote.Material = "Paper";
 OneRupeeCoin.SerialNo = "Z2232V4455";

In other words value objects when compared are same when the values of the properties are same.

Implementing Value object pattern in C# is a two step process , so in the further article let us run through those steps.

Step 1 :- Making Value object pattern work logically in C#

Now for the above “Money” value object to function properly the below comparison should work both for “Equals” and “==”. But technically C# does object reference comparison and not value.



if (OneRupeeCoin==OneRupeeNote)
 {
 Console.WriteLine("They are equal");
 }
 if (OneRupeeCoin.Equals(OneRupeeNote))
 {
 Console.WriteLine("They are equal");
 }

So to achieve the same we need to override the “equals” methods and overload “==” operator as shown in the code below. You can see now the equality is compared on the base of “Value” and “CurrencyType”. If the “CurrencyType” and “Value” is same that means the objects are same.


class Money
     {
         public override bool Equals(object obj)
         {
             var item = obj as Money;
             if (item.Value == Value)
             {
                 return true;
             }
             return false;
         }
         public static bool operator !=(Money money1, Money money2)
         {
             if ((money1.Value == money2.Value) &&
                 (money1.CurrencyType == money1.CurrencyType))
             {
                 return true;
             }
             return false;
         }
         public static bool operator ==(Money money1, Money money2)
         {
             if ((money1.Value == money2.Value)&&
                 (money1.CurrencyType == money1.CurrencyType))
             {
                 return true;
             }
             return false;
         }
     }

Once the above methods are incorporated the equality will work on the values and not the reference. This is in synch with the Value object pattern behavior we discussed in the introduction.

Step 2 :- Value objects should be immutable

Now let us say we are using the above money object inside a product class. So you can see we have created two product objects one for shoes and one for chocolates.

But BY MISTAKE we have assigned the same “Money” object to both the products. In other words the money object is now shared between both the products.



Product shoes = new Product();
 shoes.ProductName = "WoodLand";
 
 // Step 1:- Money object set to 100 INR
 Money Cost = new Money();
 Cost.CurrencyType = "INR";
 Cost.Value = 100;
 shoes.Cost = Cost;
 
 // Step 2 :- the same money  object is modified to 1 value
 // this affected the shoes cost as well
 Product Chocolates = new Product();
 Chocolates.ProductName = "Cadbury";
 Chocolates.Cost = Cost;
 Chocolates.Cost.Value = 1;
 Chocolates.Cost.CurrencyType = "USD";
 
So in Step 1 the money object was set to 100 INR and in step 2 it was modified to 1 USD. Step 2 affected the cost of Shoes product as well. This can cause lot of defects and unusual behavior.

A Value “100” cannot be replaced by anything, “100” is “100”. In other words value objects should be made IMMUTABLE to avoid confusion. In case you are new to the concept of immutability I would suggest reading this article on C# Immutable objects.

Immutable means once the object is filled with data, that data cannot be changed.

To make the money class immutable is a 2 step process:-
  • Make the property set as private.
  • Make provisions to set data via constructor.
Below is the code with comments of both the steps.


class Money
 {
         // Step 1 :- Make the sets private
         public readonly double Value { get; private set; }
         public readonly string CurrencyType { get; private set; }
         public readonly string Material { get; private set; }
         
 // Step 2 :- Pass data via constructor
         public Money(double _Value,
                      string _CurrencyType,
                     string _Material)
         {
             Value = _Value;
             CurrencyType = _CurrencyType;
             Material = _Material;
         }
 // Code of Equals and == operator removed for simplification
 }
 
Below is the code which shows how the product object will be assigned with money immutable object. This would further avoid changes to the money object and any confusion around the same. Now the money value object of shoes is different from chocolates.


Product shoes = new Product();
 shoes.ProductName = "WoodLand";
 shoes.Cost = new Money(100, "INR", "Paper");
 
 Product Chocolates = new Product();
 Chocolates.ProductName = "Cadbury";
 Chocolates.Cost = new Money(1, "USD", "Coin");
 


Conclusion about Value object pattern


  • Value objects equality is based on value rather than identity.
  • Value objects should me IMMUTABLE to avoid confusion.
  • In C# to ensure proper behavior of value object we need to override “Equals” method and “==” operator.
The best way to learn design pattern is by doing a project. Below is a simple customer project in which I have implemented 8 design patterns (Factory Pattern,Lazy Loading,RIP Pattern,Stratergy Pattern,Decorator pattern,Repository,Unit of Work and Template pattern).

Below is the first video of Learn Design pattern in 8 hours.

No comments: