DDD on a website? Or CQRS / EventSourcing without DDD?

606 views
Skip to first unread message

Sébastien Lorber

unread,
Jun 17, 2015, 11:25:08 AM6/17/15
to ddd...@googlegroups.com
Hi,

In this video Greg Young seems to say it's not worth using DDD on a internet site (around 13min30)


At work we are building a Single-Page-Application with ReactJS + mobile apps that rely on a backend API.
Can it be considered as an "internet site" like Greg Young mention?

Our business is not that complex, there's no "domain experts" as we are kind of all developers in the company for now. 
I don't think we don't have multiple contexts in which the same word may have different meanings.


We really want to explore CQRS / event-sourcing as we need:
- a full audit trail for UX but also for future analytics
- 100% offline capabilities (it's easier to sync with clients with an event log).
- to iterate fast on UX screens without impacting the whole system and with better performances that we have now

Some things I really like about DDD:
- The model has no dependency, it is easy to test it's behavior
- The transaction boundaries of Aggregate Roots that seems to prevent concurrency issues


I'm not at all an expert in DDD. I don't know if DDD is suitable for an application with a simple (for now at least) domain.
Yet with this simple domain, I struggle how to design the aggregate roots so that a transaction can be managed by a single Aggregate Root (or I end up with a big fat single AggregateRoot)


My domain is very similar to a set of unix file systems with users:
- A filesystem is a tree of nodes of type folders and files
- Each user owns 1-* file systems
- Each user can give access to his file systems to other users at any node level so that all the subtree of this node is available for read/write/manage
- The permissions given to an user on a given node can be overrriden but any child node's permission
- Move of files inside a filesystem is allowed if you can write on both the moved node and the target node
- Move of files from one filesystem to another is possible if you are admin on both the move node and the target node
Obviously it's not that simple but here are the core requirements of our domain.

Do you see any aggregate root here?
I don't know how to split that filesystem set into multiple aggregate roots, particularly with the "move accross filesystems" because if I create an aggregate root for a filesystem, that move wouldn't be transactional.
I don't really know how to solve this kind of problem with DDD. Maybe I should consider it like real physical drives, where the moved node is first copied on the target node, and then deleted in its original place? 



Do you think my domain is well suited for DDD?

If not, what do you recommend so that I can still use CQRS / event-sourcing and so that there won't be concurrency issues when issuing the events? 
Do you have any useful readings about that?

Maybe it's kind of premature to think so much about concurrency as we don't have so much load right now and could probably deal with a more optimistic model that works not so bad in most CRUD apps... until it fails and some data gets overriden at some point.



Please give me your thoughts ;)








Tom Janssens

unread,
Jun 18, 2015, 4:10:53 AM6/18/15
to ddd...@googlegroups.com
Make sure only one react component instance owns (can modify) the data, others can subscribe to changes, and you'll see that a DDD-like design emerges...

I'm currently using react for an app of mine, without event sourcing.

I do publish statechange events, but mostly have simple state shared along components, i.e. polygons, value dictionaries, 3D objects and some specifics: a BSP tree, an equirectangular pic and it's relative 3D coordinates to the scene etc.

Because my state is very specific to the domain, and will probably not change in the future, I decided against using event sourcing. All of my builders and other instances reacting upon the statechange events are currently conformist. 

In the future I might switch to ES, f.e. for my BSP tree or dictionary statechange events, but ATM it hasn't been a problem.

FWIW my app is running completely client-side using localstorage, and I'm currently in the process of building a back-end to sync changes.

ES might be a perfect fit if I ever need to merge different versions upon syncing, (i.e. construct a DAG and just apply events from different branches in all orders possible, compare state and if they are not the same you have a merge conflict that needs to be resolved manually).
However, this might add a lot of overhead, and as I'd rather keep the app simple unless it's strictly necessary, I'll probably never follow that path.

TL;DR: think about data ownership in react, and a DDD-like design will probably emerge.

Op woensdag 17 juni 2015 17:25:08 UTC+2 schreef Sébastien Lorber:

Sébastien Lorber

unread,
Jun 18, 2015, 5:23:44 AM6/18/15
to ddd...@googlegroups.com
Hi Tom.

Thanks for your reply but I think you misunderstand what I'm asking :)


I'm asking about using DDD for the backend, and not the frontend ReactJS application.
I'm already using React in a very functional way, with a single immutable data structure managed outside of React components. 
I don't use local component state at all and use my React tree as a big but efficient HTML template.
Our internal framework on top of React is inspired by CQRS / ES / DDD / Flux
I have an event log on the frontend and I can replay it, producing "user session videos".
I've made a video of this replay feature for those interested.
It works really nicely in our production app, but does not yet capture in state things like scroll position, window size, CSS like :hover etc...



Our backend is currently a legacy monolithic API (without DDD / CQRS / EventSourcing) that progressively moves away from its iinitial CRUD implementation of our startup early days.
Currently everything is tightly coupled and its architecture will make it a pain to design offline features for the frontend app.I mean we will have to manually handle local caching on the client, and have to manage correctly cache invalidation.
I want to sync the client with a stream of events so that it will be much easier to have local data up to date (at least eventually consistent) and handle cache invalidation easily.
In addition the browser is evolving with stuff like ServiceWorkers, push and background sync so that it will be much simpler to continuously sync browser apps state (like we can already do with mobile apps). 


I have a good idea of how my backend and my frontend will interact and sync in our future architecture (I may write soon about it as I think it's an interesting architecture).
For that the backend needs event-sourcing. For simplicity this initial event stream will be ordered and not partitionned.
My question is actually the single piece I don't know yet of my architecture.


Here's the final question rephrased: 
For my future event-sourced backend and the domain explained above (a set of unix file systems):
How am I supposed to produce the events?
Should I use DDD's Aggregate Root? 
Is there another possible way not involving DDD, that handles nicely concurrency? 




--
You received this message because you are subscribed to a topic in the Google Groups "DDD/CQRS" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/dddcqrs/ERT_TD8WQAo/unsubscribe.
To unsubscribe from this group and all its topics, send an email to dddcqrs+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tom Janssens

unread,
Jun 18, 2015, 7:00:25 AM6/18/15
to ddd...@googlegroups.com
Thanks for the video; impressive tech!

As for DDD: my 2 cents: I wouldn't use it in this case, but TBH it depends on what you want to do on the server side. For me personally the server side is only about storage/authentication/authorization, so I compose my back-end like that; I'd assume you could call that BC's. As for the implementations, I don't use any specific DDD tactics, although that might change over the time.

TL;DR: start with DDD strategy, you can always do tactics later.



Op donderdag 18 juni 2015 11:23:44 UTC+2 schreef Sébastien Lorber:

Ben Kloosterman

unread,
Jun 18, 2015, 7:59:18 AM6/18/15
to ddd...@googlegroups.com


At work we are building a Single-Page-Application with ReactJS + mobile apps that rely on a backend API.
Can it be considered as an "internet site" like Greg Young mention?

Depends on the API style is it commands or CRUD ?

Our business is not that complex, there's no "domain experts" as we are kind of all developers in the company for now. 
I don't think we don't have multiple contexts in which the same word may have different meanings.


We really want to explore CQRS / event-sourcing as we need:
- a full audit trail for UX but also for future analytics
- 100% offline capabilities (it's easier to sync with clients with an event log).

This implies 
1) Domain is partly on hand helds since they will want to process them whole offline.
2) There are some arguments for event sourcing here.
 
- to iterate fast on UX screens without impacting the whole system and with better performances that we have now

Wont make any difference if you run off line you run against the local store and the local store communicates with the back end API. 

Some things I really like about DDD:
- The model has no dependency, it is easy to test it's behavior
- The transaction boundaries of Aggregate Roots that seems to prevent concurrency issues

It helps for consistency not concurrency you can both modify the same aggregate while offline . Event Sourcing does help for concurrency.


I'm not at all an expert in DDD. I don't know if DDD is suitable for an application with a simple (for now at least) domain.
Yet with this simple domain, I struggle how to design the aggregate roots so that a transaction can be managed by a single Aggregate Root (or I end up with a big fat single AggregateRoot)


My domain is very similar to a set of unix file systems with users:
- A filesystem is a tree of nodes of type folders and files
- Each user owns 1-* file systems
- Each user can give access to his file systems to other users at any node level so that all the subtree of this node is available for read/write/manage
- The permissions given to an user on a given node can be overrriden but any child node's permission
- Move of files inside a filesystem is allowed if you can write on both the moved node and the target node
- Move of files from one filesystem to another is possible if you are admin on both the move node and the target node
Obviously it's not that simple but here are the core requirements of our domain.

Do you see any aggregate root here?

I dont see business logic  . Is it a service ?

I don't know how to split that filesystem set into multiple aggregate roots, particularly with the "move accross filesystems" because if I create an aggregate root for a filesystem, that move wouldn't be transactional.
I don't really know how to solve this kind of problem with DDD. Maybe I should consider it like real physical drives, where the moved node is first copied on the target node, and then deleted in its original place? 



Do you think my domain is well suited for DDD?

Based on what has been provided so far not really.  


Maybe it's kind of premature to think so much about concurrency as we don't have so much load right now and could probably deal with a more optimistic model that works not so bad in most CRUD apps... until it fails and some data gets overriden at some point.

When designing distributed systems i think 1st  Comms ( latency , reliability , band width , coverage) , then concurrency( it has nothing to do with load , what matters i show long they will be disconnected and how much information is shared)  , then contracts /business logic , then the rest of the system . I have seen many  failures in large distributed systems .   For normal apps / services business logic comes first then contracts/ screens.

Note offline , distributed and Event sourcing apps cost a lot more. Can easily be 3 fold. 

Ben

Sébastien Lorber

unread,
Jun 18, 2015, 8:59:36 AM6/18/15
to ddd...@googlegroups.com
Hi,

Thanks Tom will check your link.


Ben you are absolutately right actually wanted to say consitency issues yes.
And you are right the load does not matter as concurrency issues can happen easily when 2 users edit the same thing while being offline and reconnect. 
I am aware of the need of automatic or manual conflict resolution for such cases but what I want is to not have any unexpected data override for the end users in case of concurrent updates.

I know this is much more expensive to build such apps but we absolutely need this :)
We want to build something akin to Pocket reader but more advanced, and Pocket's offline capabilities are one of the things that make it very attractive to use.


My domain is not CRUD and is command based. 
In the future we will probably have a single command endpoint to receive all commands.
There are commands to create comments to files, add metadata, to like files, to add them to favorites, to share them with other users, send them by email, import files from Evernote etc...


What do you mean by "I dont see business logic  . Is it a service ?" 
What do you mean by "is it a service?" What is a service for you?
The business logic is things like how permissions are managed on the filesystems. 
Each user can perform some commands only according to their permissions.
For example an user can't create a comment on a file he has no read access to.
Or an user can only move a file outside a shared folder if he's the file creator, or the filesystem owner.
I didn't express that logic as I wanted to make it simple to understand the core: a set of unix filesystems.
The business rules are quite similar to the ones of an unix filesystem, with groups and chmod etc...



Please don't take too much in consideration I am building frontend apps with full support for offline, I mentionned that simply to explain some motivations for the event-sourced backend :)

What I'm interested in is now to use event-sourcing with my backend for my domain. 
Should I use DDD or something else?



Ben Kloosterman

unread,
Jun 18, 2015, 9:41:50 PM6/18/15
to ddd...@googlegroups.com
By service i mean  IT infrastructure , "files" are normally a back end "thingy" unless your someone like dropbox..

If Files are shared and you want concurrency you have no choice but to go to either field based data  or   event sourcing  . 

Whether to go CQRS  ,  DDD or OO with ES  is a different consideration which is hard for us to judge.  You should look at what your client to server API looks like.  I would not make the decision based on performance  because if your moving files that IO cost will dominate. 

Regards,


Ben

Sébastien Lorber

unread,
Jun 19, 2015, 8:21:18 AM6/19/15
to ddd...@googlegroups.com
Ben actually I made an analogy to the file system domain because my domain is quite similar to the behavior of a file system, but I'm not at all involved into hardware stuff :)

There's no file system IO cost to take into consideration, moving a file is actually a simple DB query like "UPDATE FROM file SET folderId=newFolderId WHERE fileid = movedFileId". Got it ? :)


My real domain could also be described like: a set of blogs (ie file systems) where blog posts (ie files) are ordered in a tree of categories (ie folders). Permissions can be given to users on blog posts and categories. Blog posts may be moved from one blog to another etc... 
This is another possible analogy, but I'll keep with the filesystem analogy.


So, in my domain, files are entities and not value objects. 
Files are collaborative (we may implement real-time things like CRDT / OT, like Google Doc is doing for collaborative editing)


"Whether to go CQRS  ,  DDD or OO with ES  is a different consideration which is hard for us to judge.  "
Yes, this is what I am asking ;) 
How to make that judgement? 
If not using DDD, how to stay consistent?
And are there any ressources on how to build an ES app without DDD?


So as far as I understand you can do OO + ES. 
Ok I guess but how to do this? Who has already done this and be successful and for which reasons?






--

Greg Young

unread,
Jun 19, 2015, 8:22:29 AM6/19/15
to ddd...@googlegroups.com
"
There's no file system IO cost to take into consideration, moving a
file is actually a simple DB query like "UPDATE FROM file SET
folderId=newFolderId WHERE fileid = movedFileId". Got it ? :)"

This still looks like io
> You received this message because you are subscribed to the Google Groups
> "DDD/CQRS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
--
Studying for the Turing test

Sébastien Lorber

unread,
Jun 19, 2015, 8:30:35 AM6/19/15
to ddd...@googlegroups.com

Haha sure it is IO but almost any app has this kind of IO.
What I mean is that I'm not at all involved in moving terabytes of files from one datacenter to another.
My filesystems are virtual

Maybe I should have given you an in-memory example of the move operation? movedFile.folderId = targetFolder.id



Reply all
Reply to author
Forward
0 new messages