বুধবার, ২০ নভেম্বর, ২০১৩

Command Query Responsibility Segregation (CQRS)

  • CQRS Øviv †evSvq Command Query Responsibility Segregation
  •  A‡b‡KB g‡b K‡ib CQRS GKwU architecture.
  •  wKš‘ bv |
  • CQRS GKwU simple pattern hvnv architecture G A‡bK opportunities enable K‡i|
  •  Greg Young Ges Udi Dahan me©cÖ_g GB pattern introduce K‡ib| 
  • CQRS G command side I query side Gi method mg~n separate object G ivLv nq A_©vr command side Gi Rb¨ GKwU object Ges query side Gi Rb¨ Av‡iKwU object _vK‡e | 
  •  cÖkœ n‡jv command I query wK?
o   Command side:  †h mKj method mg~n object wKsev entire system Gi state change K‡i ZvnvB Command side method.  Save(), Update(), Delete() etc. Command side method Kvib Bnv‡`i Øviv object Gi state change Kiv nq|
o   Query side: †h mKj method mg~n Øviv ïaygvÎ results  return  Kiv‡bv nq Ges Dnv‡`i Øviv object wKsev entire system Gi state Gi †Kvb change nq bv Zvnviv Query side method. Get(), GetById() etc. Query side method Kvib Bnv‡`i Øviv ïaygvÎ results  return Kiv‡bv nq Ges object Gi state Gi †Kvb change nq bv|
  • mvavibZt Avgv‡`i Transactiona Class definition wb¤œiƒc nq-
EmployeeDataAccess
SaveEmployee(Employee employee)
UpdateEmployee(Employee employee)
DeleteEmployee(int employeeId)
PopulateEmployee()
PopulateEmployeeById(int employeeId)
  •  CQRS Pattern Abyhvqx  Dc‡iv³ EmployeeDataAccess class wU‡K Dnvi method mg~‡ni responsibility Abyhvqx  †f‡½ `yBwU fv‡M fvM Kiv n‡e-
  • Command Side Gi Rb¨ EmployeeCommandDataAccess  class hvnv wb‡¤œv³ method mg~n contain Ki‡e-
EmployeeCommandDataAccess 
SaveEmployee(Employee employee)
UpdateEmployee(Employee employee)
DeleteEmployee(int employeeId)
  •  Query Side Gi Rb¨ EmployeeQueryDataAccess  class hvnv wb‡¤œv³ method mg~n contain Ki‡e-
PopulateEmployee()
PopulateEmployeeById(int employeeId)
  • BnvB CQRS pattern.

Upcoming Posts

Dear readers
Successfully completed some patterns that defined in Martin Fowler's Patterns of Enterprise Architecture (PEA). Next we will discuss about
  1. Command and Query Responsibility Segregation (CQRS) Pattern  
  2. Event Sourcing(ES) pattern
  3. Messaging Pattern

Wish all of yours cooperation and suggestion.

Thanks for reading
Mojammel Haque

Identity Map



  • Ensure Kiv nq †h cÖwZwU object GKeviB gvÎ loaded n‡q‡Q|
  • GRb¨ cÖwZwU loaded object ‡K GKwU map Gi g‡a¨ ivLv nq|
  • hLb †Kvb object ‡K  refer Kiv nq ZLb Dnv‡K GB map Gi g‡a¨ †LuvRv nq  |
  •  hw` map Gi g‡a¨ cvIqv hvq Z‡e †mLvb †_‡K return Ki‡e bZzev database ‡_‡K object data load Ki‡e| AZtci D³ loaded data map G store Ki‡e| Then map ‡_‡K return Ki‡e|
  • Identity map use K‡i wb‡¤œv³ benefit mg~n cvIqv hvq-
    •  Resource consumption reduce K‡i| 
    •  Database Gi same object data Gi duplicate retrieval prevent Kivi Rb¨ Bnv context-specific, in-memory cache provide K‡i| d‡j performance improve nq| 

Example:
public abstract class Entity
{
        private readonly int _id;
       
        public int Id
        {
               get { return _id; }
        }
       
        internal Entity(int id)
        {
               _id = id;
        }
}
       
public sealed class Widget : Entity
{
        private static readonly EntityMap<Widget> _map = new EntityMap<Widget>(id => new Widget(id));
       
        public static EntityMap<Widget> Map
        {
               get { return _map; }
        }
       
        private Widget(int id) : base(id) { }
}
       
public sealed class Gadget : Entity
{
        private static readonly EntityMap<Gadget> _map = new EntityMap<Gadget>(id => new Gadget(id));
       
        public static EntityMap<Gadget> Map
        {
               get { return _map; }
        }
       
        private Gadget(int id) : base(id) { }
}
       
public class EntityMap<T> where T : Entity
{
        private readonly Dictionary<int, T> _entities = new Dictionary<int, T>();
        private readonly object _getLock = new object();
        private readonly Func<int, T> _entityGenerator;
       
        public T Get(int id)
        {
               lock (_getLock)
               {
                       T entity;
       
                       if (!_entities.TryGetValue(id, out entity))
                               _entities[id] = entity = _entityGenerator(id);
       
                       return entity;
               }
        }
       
        internal EntityMap(Func<int, T> entityGenerator)
        {
               _entityGenerator = entityGenerator;
        }
}
  • Client code G wb‡b¥v³fv‡e call Kiv n‡e-
// The following line results in a compilation error
// because Widget has no public constructors.
Widget badWidget = new Widget(1);
        
// Same for this one.
EntityMap<Widget> badWidgets = new EntityMap<Widget>();
        
// A Widget is properly retrieved like so...
Widget widget = Widget.Map.Get(1);