Events for CRUD always bad?

242 views
Skip to first unread message

Dan Malcolm

unread,
Mar 1, 2011, 9:34:53 AM3/1/11
to DDD/CQRS
I am looking into using domain events, CQRS and messaging for a system
used to manage online hotel bookings. I’m using the phrase “domain
events” to mean a domain model (using either ES / ORM for persistence)
that publishes events that are subsequently handled to manage
integration / auditing / read model concerns.

Some aspects of the system are a good fit for this architecture. The
reservation process can be modelled as a sequence of events (selecting
rooms, placing order, fulfilment), with messaging providing resilience
needed for long-running processes, such as fulfilment via 3rd party
systems.

At the same time, there are simpler CRUDy configuration and content
management requirements:

- This is a multi-tenant solution and tenant administrators need to be
able to manage settings like IP addresses used to connect to 3rd party
web services

- 3rd party online booking systems have the concept of a Room Type
(“Luxury Double Room”, “Standard Double Room”, etc). Our system has a
RoomTypeContent class, which allows users to enrich the basic
information supplied by 3rd party systems with rich text descriptions
and a collection of images, flash, videos etc.

The advice is to _not_ use events / CQRS for simpler CRUD systems.
These objects don’t have any real behaviour and there isn’t a pressing
need for a separate read model either. Creating commands, events,
handlers etc to manage changes to a string property of a
RoomTypeContent object feels overly complex and I am wondering whether
to put the configuration / CMS parts of the system into a separate
bounded context with an ORM-managed read-write model.

On the other hand, there are advantages to using domain events / CQRS
for the CRUD parts of the system, especially if that system is already
using domain events elsewhere:

- Users are interested in when content / configuration changes are
made – so we might as well benefit from the auditing / reporting
support offered by our existing events infrastructure.
- Even if the domain objects that trigger the events are anaemic and
don’t have any interesting behaviour themselves, the loose coupling
offered by events makes our system more flexible and future proof.
e.g. a monitoring service could be added / changed when a tenant
changes the configuration information of a 3rd party system

So, having written this, I think I’ve convinced myself to stubbornly
press on and use domain events / CQRS for the CRUD aspects of the
system and swallow the additional complexity that this brings. Does
anybody disagree strongly with this?

Tom Janssens

unread,
Mar 1, 2011, 10:55:21 AM3/1/11
to DDD/CQRS
I am not sure whether I understand the question, but this is how I
would do it:
Create a domain model that has the concept of hotels, rooms,
reservations, ... which contains all the necessary info for your
business decisions.
Store all your descriptive room/room type/hotel info in some kind of
wiki, allowing each tenant to adjust his own info... (link the info to
the AR using either the AR ID, or store some kind of slug/uri on the
AR).
In the UI, simply grab the wiki content or display a browser window in
line...

Does this answer your question ?

@seagile

unread,
Mar 1, 2011, 4:25:25 PM3/1/11
to DDD/CQRS
Is this within the same bounded context?
Is it core to your system?
Can you "describe" the behavior on the RoomTypeContent (i.e. those are
your commands)?

On 1 mrt, 15:34, Dan Malcolm <danm...@gmail.com> wrote:

Dan Malcolm

unread,
Mar 1, 2011, 6:43:45 PM3/1/11
to DDD/CQRS
On Mar 1, 9:25 pm, "@seagile" <yves.reynh...@gmail.com> wrote:
> Is this within the same bounded context?

> Is it core to your system?

I'd say there are probably 2 separate bounded contexts, both of which
are core to the system:

1. Interaction of end-user with the system, e.g. registration, making
bookings, applying for loyalty programme

2. Tenant configuration and customisation. The level of customisation
offered to tenants is a first class feature and includes environment
configuration, content management and other enhancements.

> Can you "describe" the behavior on the RoomTypeContent (i.e. those are
> your commands)?

The commands relating to RoomTypeContent and other content-related
classes will represent changes made by the tenant administrators.
These are classic CRUD operations, e.g. CreateRoomTypeContent,
UpdateRoomTypeContent. This is the bit that's making me question
whether to go the domain events / CQRS route in the tenant
customisation bounded context. Updates could be managed via regular
ORM persistence without events / CQRS, or even using a separate CMS /
Wiki as Tom suggests..

However, I think there are still practical reasons why I might want to
use events / CQRS to manage these simpler CRUD operations (auditing,
exposure of events for cache updates, notifications etc). If the
project only involved CRUD, then domain events / CQRS might be over-
the-top, but if the infrastructure is already in place for other parts
of the system...

Dan Malcolm

unread,
Mar 1, 2011, 6:50:16 PM3/1/11
to DDD/CQRS
Thanks for the suggestion, I've often thought that content management
concerns could be separated off in the way you suggest, and if the
wiki / CMS used supports auditing / versioning that's great.

What about the tenant configuration though, e.g. tenant needs to be
able to edit connection details used to access their 3rd party system?

Tom Janssens

unread,
Mar 1, 2011, 8:45:09 PM3/1/11
to DDD/CQRS
How about renaming your command to "DescribeRoomType" ? (i.e. behavior
instead of CRUD)

Dan Malcolm

unread,
Mar 2, 2011, 5:56:40 AM3/2/11
to DDD/CQRS
Yes, makes sense

@seagile

unread,
Mar 2, 2011, 6:53:54 AM3/2/11
to DDD/CQRS
Personally, I'd say go for the events, it's just passing through the
system anyways (your read model can deal with putting it in the proper
tables), and you seem to have behavior around those same concepts as
well, and they seem pretty core to your model. Putting things
"elsewhere" also has it's issues, such as making you deal with the
question "what if they go out-of-sync?".

On 2 mrt, 00:43, Dan Malcolm <danm...@gmail.com> wrote:

Dan Malcolm

unread,
Mar 3, 2011, 6:12:58 AM3/3/11
to DDD/CQRS
Thanks, I agree and this is probably the way we are going to go.

I'm wondering how granular the CRUD events need to be. Users are
mainly interested in when edits are made, so we could go with
something fairly coarse like (events):

RoomTypeContentCreated
RoomTypeContentEdited

Each of these would need to contain information about what was edited
within the RoomTypeContent aggregate. At its simplest this would be a
copy of the properties of the updated RoomTypeContent, e.g.
ShortDescription (string), Description (string) property and Media
(collection of Media value objects). The duplication required here
feels a bit clunky, but I guess that's the price of using events /
CQRS for CRUD rather than simply updating a read-write database in
place.

Tom suggested the more behaviour oriented event names like
DescribeRoomType – how could we differentiate between the creates and
updates here?

Alternatively, we could go with something more granular:

RoomTypeContentDescriptionChanged
RoomTypeContentMediaAdded
RoomTypeContentMediaRemoved
RoomTypeContentMediaUpdated

However this doesn't really correspond with tasks that the user is
going to perform, they might update / reorder media items in one go.

Caleb Vear

unread,
Mar 3, 2011, 8:35:12 AM3/3/11
to ddd...@googlegroups.com
You don't need to have lots of duplication in the change event.  You could just make the event contain a delta of the changes so it only includes what has changed.

@seagile

unread,
Mar 3, 2011, 11:18:04 AM3/3/11
to DDD/CQRS
> Tom suggested the more behaviour oriented event names like
> DescribeRoomType – how could we differentiate between the creates and
> updates here?

Does it matter? I tend to look at this from the perspective of my
event consumers: Are they interested in a difference in behavior/
intent? Do/Should they react differently? Up to a certain extent they
dictate how granular events should be. Granularity goes hand in hand
with the task a user is performing, so that dictates granularity as
well. So to conclude, it depends on how granular you can capture
intent (task-based UI should solve this) and how granular you need to
capture intent (for your event consumers).
Reply all
Reply to author
Forward
0 new messages