423962 (6) [Avatar] Offline
As per DDD aggregate is constrained by transaction boundary. What that means is any update on an aggregate has to be performed in saparate trasaction or a transaction should only impact one aggregate at a time. Either in reaction to a command or event. If I take the example of fund transfer among two accounts in your book. I cannot see any such transaction boundary being honored there.

Can you please share what is the reason behind it?
Debasish Ghosh (111) [Avatar] Offline
We say an aggregate is a unit of consistency. Transaction is an overloaded term - in the age of distributed systems we have realized that ACID transactions don't scale. Please have a look at this awesome presentation from Jonas Boner .. http://www.slideshare.net/jboner/life-beyond-the-illusion-of-present.

Having said that you can of course design aggregates as a unit of consistency using all the functional tools described in the book. If you want ACID, you can do that using db interfacing libraries like Slick or Doobie. I have not gone into the details of these libraries as I wanted to keep the discussion generic. Have a look at the places in the book where I discuss aggregates and elaborate on this topic.

Let me know if u need any specific pointer or help on this subject.

423962 (6) [Avatar] Offline
Thanks for your reply.

As you rightly mentioned that ACID do not scale well and I was also not inclined to have ACID across multiple aggregates.

Let's take a simple example of fund transfer from your book. A fund transfer involves at least two accounts and aggregates being unit of consistency should be updated in separate transactions to gain more scalability.

In order to achieve above, we need to have some process manager/ saga that can help us update multiple aggregates as a long-running business process.

Most of the DDD books that I read, excites the reader by emphasizing more on the DSL, consistency unit/ transaction boundary, but pay very less attention to process manager/ saga.

I forsee process managers/ saga to be implemented as reader monad, but it will be great if you can shed some light on this aspect also.

Thanks again,
Debasish Ghosh (111) [Avatar] Offline
As I recommend in the book, as part of functional thinking we start with the functions or use cases. Related functions go in modules and composing modules lead to larger functionalities.

Now with this thinking, a use case like funds transfer may be conceived as a domain behavior. Depending on the complexity of the use case it can be a single function or a module. But, yes, the interface / algebra of such a function should be a ReaderT, as it expects stuff from the environment (db connection, config info etc.).

Once we have the info from the environment through a Reader monad, we need to implement transactional semantics to ensure that aggregates are consistently updated. For simplicity we can think of ACID here and use the transaction semantics of some library like Slick or doobie.

Here are some of the steps ..

1. Model anything that takes stuff from environment as a ReaderT. This decouples the environment from the domain model and allows you to build your computation separately from executing it
2. Within the function consider using monadic or applicative semantics depending on the use case. In case of funds transfer I think it can be monadic as we want a fast fail semantics
3. Ensure consistency of aggregates using transaction semantics of the underlying db access library. Both Slick and doobie offer compositional semantics for this.

HTH, let me know if u need any more details on this.