5. Collaborations – when users are working on same set of data
Staleness – when data may expire between read and write
6.
7.
8.
9. Data is stale anyway. Why don’t admit it?
We can create read-optimized database to show data.
Remember OLAP and OLTP?
SELECT
title, short_text, publish_date, publisher_name, comme
nt_count FROM posts_list
Good scalability, good performance
You can use direct mapping from tables to UI
10. 1. Manager loads client info
2. He’s editing data
a) Address is changed
b) Status is changed to ‘preferred’
3. In background status is changed to ‘delinquent’
4. Manager submits data
What would you do?
Example by Udi Dahan
11. Conventional way – here’s updated copy of your data, save it to database
CQRS (in fact, DDD) way – do this with your entity
12. Commands are verbs – RenameUser, PublishPost
Most of them will be idempotent – no more double submit problem
Include version of your data – will help to resolve conflicts
Commands are asynchronous – remember about DDD’s CQS concept?
Do command validation before sending it – if you can’t do it without making command
synchronous, it’s no longer a validation and we’ll talk later about it
13. public final class ChangeStatus implements Serializable {
// private final fields skipped
public ChangeStatus(Status status, EntityKey userId, long
version, String description) {
assertNotNull(status);
if (status == Status.REQUIRES_ACTION) {
assertNotNull(description);
}
// and so on
}
}
14. Usually it’s Domain Model – commands matches perfectly with DDD’s entities and
services.
Still you can use Transaction Script or Table Module patterns – CQRS doesn’t care.
15. Stale data – most of the time you’ll be able to merge changes in different branches without
conflicts.
do you see DCVS terminology here?
Example:
CustomerStatus(delinquent) + ChangeCustomerAddress = merge automatically
CustomerStatus(delinquent) + CustomerStatus(preferred) = depends on a
business logic, but probably make it delinquent and notify manager
What if billing command would be late?
CustomerStatus(preferred) + CustomerStatus(delinquent) = make it delinquent
and notify manager
16. Database deadlock
Some component down
Kernel panic somewhere
Bug in our software
Other infrastructure issues
Retry!
18. Read database is the most obvious subscriber:
UPDATE post_lists SET comments_count = comments_count
+ 1 WHERE post_id = #{post_id}
INSERT INTO comments_list SET …
Do you still remember our OLTP/OLAP analogy?
19. Send email notification
Write to file
Notify other system via Web service or ESB
Push notification to Web-client with Web sockets
Ring the alarm
20.
21.
22. Pros
Better scalability
Taking staleness into account
Works better in collaboration scenarios
Cons
Harder to understand and implement
Not widely known/adopted
Requires more setup that conventional architecture
In simple cases is overcomplicated
23. Complex business domain
Users that collaborate on common data
Scalability and performance
Large or distributed team
24. Conventional way to store domain objects – database tables.
Post(id: 5, title: ‘CQRS+ES’, content: ‘Today I want
to…’)
25. Other way be storing it as a series of events:
1. PostCreated(id: 1)
2. PostTitled(‘CQRS+ES’)
3. PostContentSet(‘Will add content later’)
4. PostContentSet(‘I want to…’)
5. PostPublished(Fri, 13)
26. Pros
Audit for free
Event centric
Better conflict merging
Simpler testing
Cons
Even more infrastructure to set up (snapshots, cleanups, etc)
Not very known/popular
Higher entrance threshold