Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How To Implement The Query Side Of CQRS in DDD?

I have implemented the command side of DDD using the domain model and repositories, but how do I implement the query side?

Do I create an entirely new domain model for the UI, and where is this kept in the project structure...in the domain layer, the UI layer, etc?

Also, what do I use as my querying mechanism, do I create new repositories specifically for the UI domain objects, something other than repositories, or something else?

like image 400
Laz Avatar asked Oct 04 '09 18:10

Laz


People also ask

Is CQRS part of DDD?

The short answer is: Yes, you can. CQRS as an architectural style came after DDD. It's based on the Command-Query Separation (CQS). As a pattern CQRS can be used to optimize your application.

Why do we fail to implement CQRS in Microservice architecture?

Main reason for this failure was wrong implementation and most of them are not related to CQRS. What I learned from this is that we must understand key concepts of both Microservice and CQRS, only then we can merge these.

How is CQRS design pattern related to Microservices?

CQRS is another design pattern used in microservices architecture which will have a separate service, model, and database for insert operations in the database. This acts as a command layer and separate service, model, and database for query data that acts as a query layer.


2 Answers

From my understanding of CQRS you would create a set a DTOs that fulfil the requirements of the user interface screens or applications that may need to consume them.

Where this exists in the project is based on the requirements as it would depend if you were going to expose these DTOs via web services. In which case I wouldn't put it in the Web Layer but rather in the Application layer or a dedicated Façade layer.

Then you would have a read only repository or data access layer which populates the DTOs directly. I think that the Query side of things should be optimized for read performance in which case direct queries/stored procedures on database views or tables and SqlDataReaders would do the best job here. But it would definitely be worth abstracting this access behind an interface so you can add a cached implementation later down the track.

If you're using an ORM and want to map from your Domain Entities to the DTOs then you could have a generic QueryRepository which has methods which take an ISpecification or similar construct for defining your queries then a DtoAssembler object for creating the Dtos from your Domain objects. Then have an implementation has a first class object for each of the queries you are going to perform.

Here's a fairly contrived example but I hope it gives you an idea.

       public interface ISpecification<T>
        {
            Expression<Func<T, bool>> Predicate { get; }

        }

       public class ActiveCustomersSpecification : ISpecification<Customer>
        {
            private Expression<Func<Customer, bool>> predicate;
            public ActiveCustomersSpecification()
            {
                predicate = c => c.IsActive; 
            }
            #region ISpecicfication<Customer> Members

            public Expression<Func<Customer, bool>> Predicate
            {
                get { return predicate; }
            }

            #endregion
        }

        public interface IQueryRepository<T>
        {
            IQueryable<T> GetQuery(ISpecification<T> specification);

            IEnumerable<T> FindAllBy(ISpecification<T> specification); 
        }



public class CustomerDtoAssembler
    {
        public CustomerDto AssembleFrom(Customer customer)
        {
            var customerDto = new CustomerDto
            {
                Id = customer.Id
            };

            return customerDto; 
        }
    }
like image 91
willbt Avatar answered Sep 28 '22 05:09

willbt


I think willbt has given you a really good starting point.

I would add that if you do opt to continue to use the ORM as the data-access strategy for queries you would be well-advised to consider defining a fetching strategy tailored to the data you expect you'll need to access (I'm thinking specifically about NHibernate here, by the way). What this means is you can decide whether to lazy-load or to eager-load the objects and collections associated with a particular Aggregate Root object.

The NCommon project by Ritesh Rao offers an excellent (work in progress) demonstration of how to define a different fetching strategy for different purposes.

Ritesh explains it really well in his blog.

Go ahead and have a look at the source:

  • here's the IFetchingStrategy interface
  • and this shows the use of fetching strategies in a unit test

In the test 'Repository_For_Uses_Registered_Fetching_Strategies' the call to

NHRepository<Order>().For<NHRepositoryTests>()

...causes the fetching strategies registered against the NHRepositoryTests class to be used, and therefore the OrderItems and Products will be eager loaded without messing about with NHibernate mapping configurations.

like image 29
rohancragg Avatar answered Sep 28 '22 04:09

rohancragg