CQRS Query Naming: Screen's Intent or Type of View?

273 views
Skip to first unread message

Steven Harrison

unread,
Mar 27, 2020, 4:53:19 PM3/27/20
to DDD/CQRS
Hi, I'm looking for any advice on which path to take when structuring and hence, naming Queries. It basically comes down to whether the query models the intent of the screen or what it will ultimately return. The choice seems to subsequently have some structural implications. Note: This is example is all in a single Bounded Context.

Up until now, for simple screens, I've been returning a read model per screen (1 to 1 relationship) which is executed with a query handler. Say:

GetAllOrdersForCustomerQuery returns <list>OrderView
GetOrderDetailsQuery returns OrderDetailsView

These seem to follow most examples I've seen out there.


Imagine a more complicated case, say where an order is to be assigned to a specific delivery company from a list of those that deliver to the order's destination.

The screen supporting this needs the Order Details (and address), and also a list of the delivery companies supporting that address.

I can see two potential approaches:

- Stick to the current current style of CQRS pattern I'm using. The outcome of this appears to be that I will need to utilise two queries (and read models) for that screen:

GetOrderDetailsQuery returns OrderDetailsView

Then use the Query:

GetDeliveryCompaniesSupportingLocation returns <list>DeliveryCompanyView.

Basically breaking the screen up into subviews with each subview having it's own query.



- Continue to follow 1 read model per screen, in which naming of the query alters to follow the ultimate intent of the screen.

So:

GetAssignDeliveryCompanyToOrderQuery returns AssignDeliveryCompanyToOrderView (which contains the order details / address and a list of delivery companies).

For consistency it would then seem apt to rename my existing queries:

GetAllOrdersForCustomerQuery becomes GetSelectOrderForCustomerQuery
GetOrderDetailsQuery becomes GetDisplayOrderDetailsQuery


So seems to land on whether best practises call for 
- A single query for a whole screen, or whether it's allowable in some scenarios to call multiple queries for a screen.
- Whether queries reflect that intent of the screen, or the type of information it will be returning.

Thanks



Ben Kloosterman

unread,
Mar 28, 2020, 8:15:37 PM3/28/20
to ddd...@googlegroups.com
No such things as a generic "best practice" it all depends on the use case...   Anyway naming does not matter that much, on the view side i tend to use Crud / Http patterns here.  eg orderList, orders.

Specifically 

"- A single query for a whole screen, or whether it's allowable in some scenarios to call multiple queries for a screen."

I think this is bad practice for a single query except for simple screens the advice is normally to  have duplication between views and normalized data with no dependencies eg you want to be able to build views independently / in parallel  I think its counter productive and bad to link and provide data from other BC's eg Delivery.
So especially with complex screens and micro services you want to enrich the data from other BC this can be static or fetched in a different query to another service.  If you have a monolith I would still use 2 separator queries as it  makes the code simpler with less dependencies/ coupling and allows the view to be more flexible eg if you need to change Customer your dont change all the order views that use it. 

For complex screens i would normally have an aggregation layer in the client., this is more and more common as more functionality comes from external sources.

- Whether queries reflect that intent of the screen, or the type of information it will be returning.

Should not be a consideration it should be the rough function of the part of the screen your using and if ( and only if ) convenient with not a lot of coupling the whole screen For simple screens this will be 1:1  . Many screens use 2 BC's domains / are too complex to have it as 1 query and you certainly wont have analytics/ security in the same query.  Others you need to create an aggregation API to make it convenient to the client.,  It depends a lot on the overall arch (Web , Micro services  , Offline App etc)

Remember the Key goals which drives these simple views 
- Avoid a complex de-normalized RDBMS on the read side , the complexity and managing schema/ migrations is not warranted as the heavy lifting is done on the write side and IMHO replaying 10-50G messages to rebuild would be unacceptable in most cases .. which then forces snap shots etc. ..All this can be avoided in most cases. 
- Keep read side and views VERY simple  they should  just a dictionary with few dependencies 
- There should be no dependency between views, ( do this at the client)  . That way when you play views and scale them independently you dont have eventual consistency / order between views.
- Unless its a small project ( in which case you should not be using CQRS/ES) you dont want to couple front end development to backend eg every time the screen changes you need to change the API. In many cases the screen will be a subset of the data anyway and later will require more data. 

These simple persisted views can be enriched by an in between service or in the client / consumer.   

I have some samples that extend Gregs Simple CQRS which i will post later though they dont have complex screens / APIs.,

Ben

Steven Harrison

unread,
Apr 1, 2020, 9:30:35 AM4/1/20
to DDD/CQRS
Hi Ben, thank you for the reply.

Your guidance on duplication between views and normalised data with no dependencies makes sense, in terms of making the view more flexible.

Your examples (orderList) is the path I've already started down: ProjectList, TaskDetail etc etc. This tends to align well with applying a REST API as needed.

If you get a chance to post those samples you indicated that would be great.

Steve
Reply all
Reply to author
Forward
0 new messages